// auto generated by go tool dist
// goos=solaris goarch=amd64


#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "arch_GOARCH.h"
#include "malloc.h"
#define READY ((G*)1)
#define WAIT  ((G*)2)

#line 37 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
enum 
{ 
PollBlockSize = 4*1024 , 
} ; 
#line 42 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
struct PollDesc 
{ 
PollDesc* link; 
#line 51 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
Lock; 
uintptr fd; 
bool closing; 
uintptr seq; 
G* rg; 
Timer rt; 
int64 rd; 
G* wg; 
Timer wt; 
int64 wd; 
void* user; 
} ; 
#line 64 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static struct 
{ 
Lock; 
PollDesc* first; 
#line 73 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
} pollcache; 
#line 75 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static bool netpollblock ( PollDesc* , int32 , bool ) ; 
static G* netpollunblock ( PollDesc* , int32 , bool ) ; 
static void deadline ( int64 , Eface ) ; 
static void readDeadline ( int64 , Eface ) ; 
static void writeDeadline ( int64 , Eface ) ; 
static PollDesc* allocPollDesc ( void ) ; 
static intgo checkerr ( PollDesc *pd , int32 mode ) ; 
#line 83 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static FuncVal deadlineFn = { ( void ( * ) ( void ) ) deadline } ; 
static FuncVal readDeadlineFn = { ( void ( * ) ( void ) ) readDeadline } ; 
static FuncVal writeDeadlineFn = { ( void ( * ) ( void ) ) writeDeadline } ; 
void
net·runtimeNano(int64 ns)
{
	ns = 0;
	FLUSH(&ns);
#line 88 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	ns = runtime·nanotime();
	FLUSH(&ns);
}
void
net·runtime_pollServerInit()
{
#line 92 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	runtime·netpollinit();
}
void
net·runtime_pollOpen(uintptr fd, PollDesc* pd, intgo errno)
{
	pd = 0;
	FLUSH(&pd);
	errno = 0;
	FLUSH(&errno);
#line 96 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	pd = allocPollDesc();
	runtime·lock(pd);
	if(pd->wg != nil && pd->wg != READY)
		runtime·throw("runtime_pollOpen: blocked write on free descriptor");
	if(pd->rg != nil && pd->rg != READY)
		runtime·throw("runtime_pollOpen: blocked read on free descriptor");
	pd->fd = fd;
	pd->closing = false;
	pd->seq++;
	pd->rg = nil;
	pd->rd = 0;
	pd->wg = nil;
	pd->wd = 0;
	runtime·unlock(pd);

	errno = runtime·netpollopen(fd, pd);
	FLUSH(&pd);
	FLUSH(&errno);
}
void
net·runtime_pollClose(PollDesc* pd)
{
#line 115 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	if(!pd->closing)
		runtime·throw("runtime_pollClose: close w/o unblock");
	if(pd->wg != nil && pd->wg != READY)
		runtime·throw("runtime_pollClose: blocked write on closing descriptor");
	if(pd->rg != nil && pd->rg != READY)
		runtime·throw("runtime_pollClose: blocked read on closing descriptor");
	runtime·netpollclose(pd->fd);
	runtime·lock(&pollcache);
	pd->link = pollcache.first;
	pollcache.first = pd;
	runtime·unlock(&pollcache);
}
void
net·runtime_pollReset(PollDesc* pd, intgo mode, intgo err)
{
	err = 0;
	FLUSH(&err);
#line 129 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	err = checkerr(pd, mode);
	if(err)
		goto ret;
	if(mode == 'r')
		pd->rg = nil;
	else if(mode == 'w')
		pd->wg = nil;
ret:
	FLUSH(&err);
}
void
net·runtime_pollWait(PollDesc* pd, intgo mode, intgo err)
{
	err = 0;
	FLUSH(&err);
#line 140 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	err = checkerr(pd, mode);
	if(err == 0) {
		// As for now only Solaris uses level-triggered IO.
		if(Solaris)
			runtime·netpollarm(pd, mode);
		while(!netpollblock(pd, mode, false)) {
			err = checkerr(pd, mode);
			if(err != 0)
				break;
			// Can happen if timeout has fired and unblocked us,
			// but before we had a chance to run, timeout has been reset.
			// Pretend it has not happened and retry.
		}
	}
	FLUSH(&err);
}
void
net·runtime_pollWaitCanceled(PollDesc* pd, intgo mode)
{
#line 157 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	// This function is used only on windows after a failed attempt to cancel
	// a pending async IO operation. Wait for ioready, ignore closing or timeouts.
	while(!netpollblock(pd, mode, true))
		;
}
void
net·runtime_pollSetDeadline(PollDesc* pd, int64 d, intgo mode)
{
#line 164 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	G *rg, *wg;

	runtime·lock(pd);
	if(pd->closing) {
		runtime·unlock(pd);
		return;
	}
	pd->seq++;  // invalidate current timers
	// Reset current timers.
	if(pd->rt.fv) {
		runtime·deltimer(&pd->rt);
		pd->rt.fv = nil;
	}
	if(pd->wt.fv) {
		runtime·deltimer(&pd->wt);
		pd->wt.fv = nil;
	}
	// Setup new timers.
	if(d != 0 && d <= runtime·nanotime())
		d = -1;
	if(mode == 'r' || mode == 'r'+'w')
		pd->rd = d;
	if(mode == 'w' || mode == 'r'+'w')
		pd->wd = d;
	if(pd->rd > 0 && pd->rd == pd->wd) {
		pd->rt.fv = &deadlineFn;
		pd->rt.when = pd->rd;
		// Copy current seq into the timer arg.
		// Timer func will check the seq against current descriptor seq,
		// if they differ the descriptor was reused or timers were reset.
		pd->rt.arg.type = (Type*)pd->seq;
		pd->rt.arg.data = pd;
		runtime·addtimer(&pd->rt);
	} else {
		if(pd->rd > 0) {
			pd->rt.fv = &readDeadlineFn;
			pd->rt.when = pd->rd;
			pd->rt.arg.type = (Type*)pd->seq;
			pd->rt.arg.data = pd;
			runtime·addtimer(&pd->rt);
		}
		if(pd->wd > 0) {
			pd->wt.fv = &writeDeadlineFn;
			pd->wt.when = pd->wd;
			pd->wt.arg.type = (Type*)pd->seq;
			pd->wt.arg.data = pd;
			runtime·addtimer(&pd->wt);
		}
	}
	// If we set the new deadline in the past, unblock currently pending IO if any.
	rg = nil;
	runtime·atomicstorep(&wg, nil);  // full memory barrier between stores to rd/wd and load of rg/wg in netpollunblock
	if(pd->rd < 0)
		rg = netpollunblock(pd, 'r', false);
	if(pd->wd < 0)
		wg = netpollunblock(pd, 'w', false);
	runtime·unlock(pd);
	if(rg)
		runtime·ready(rg);
	if(wg)
		runtime·ready(wg);
}
void
net·runtime_pollUnblock(PollDesc* pd)
{
#line 228 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"

	G *rg, *wg;

	runtime·lock(pd);
	if(pd->closing)
		runtime·throw("runtime_pollUnblock: already closing");
	pd->closing = true;
	pd->seq++;
	runtime·atomicstorep(&rg, nil);  // full memory barrier between store to closing and read of rg/wg in netpollunblock
	rg = netpollunblock(pd, 'r', false);
	wg = netpollunblock(pd, 'w', false);
	if(pd->rt.fv) {
		runtime·deltimer(&pd->rt);
		pd->rt.fv = nil;
	}
	if(pd->wt.fv) {
		runtime·deltimer(&pd->wt);
		pd->wt.fv = nil;
	}
	runtime·unlock(pd);
	if(rg)
		runtime·ready(rg);
	if(wg)
		runtime·ready(wg);
}

#line 254 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
uintptr 
runtime·netpollfd ( PollDesc *pd ) 
{ 
return pd->fd; 
} 
#line 260 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
void** 
runtime·netpolluser ( PollDesc *pd ) 
{ 
return &pd->user; 
} 
#line 266 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
bool 
runtime·netpollclosing ( PollDesc *pd ) 
{ 
return pd->closing; 
} 
#line 272 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
void 
runtime·netpolllock ( PollDesc *pd ) 
{ 
runtime·lock ( pd ) ; 
} 
#line 278 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
void 
runtime·netpollunlock ( PollDesc *pd ) 
{ 
runtime·unlock ( pd ) ; 
} 
#line 285 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
void 
runtime·netpollready ( G **gpp , PollDesc *pd , int32 mode ) 
{ 
G *rg , *wg; 
#line 290 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
rg = wg = nil; 
if ( mode == 'r' || mode == 'r' +'w' ) 
rg = netpollunblock ( pd , 'r' , true ) ; 
if ( mode == 'w' || mode == 'r' +'w' ) 
wg = netpollunblock ( pd , 'w' , true ) ; 
if ( rg ) { 
rg->schedlink = *gpp; 
*gpp = rg; 
} 
if ( wg ) { 
wg->schedlink = *gpp; 
*gpp = wg; 
} 
} 
#line 305 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static intgo 
checkerr ( PollDesc *pd , int32 mode ) 
{ 
if ( pd->closing ) 
return 1; 
if ( ( mode == 'r' && pd->rd < 0 ) || ( mode == 'w' && pd->wd < 0 ) ) 
return 2; 
return 0; 
} 
#line 315 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static bool 
blockcommit ( G *gp , G **gpp ) 
{ 
return runtime·casp ( gpp , WAIT , gp ) ; 
} 
#line 323 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static bool 
netpollblock ( PollDesc *pd , int32 mode , bool waitio ) 
{ 
G **gpp , *old; 
#line 328 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
gpp = &pd->rg; 
if ( mode == 'w' ) 
gpp = &pd->wg; 
#line 333 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
for ( ;; ) { 
old = *gpp; 
if ( old == READY ) { 
*gpp = nil; 
return true; 
} 
if ( old != nil ) 
runtime·throw ( "netpollblock: double wait" ) ; 
if ( runtime·casp ( gpp , nil , WAIT ) ) 
break; 
} 
#line 348 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
if ( waitio || checkerr ( pd , mode ) == 0 ) 
runtime·park ( ( bool ( * ) ( G* , void* ) ) blockcommit , gpp , "IO wait" ) ; 
#line 351 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
old = runtime·xchgp ( gpp , nil ) ; 
if ( old > WAIT ) 
runtime·throw ( "netpollblock: corrupted state" ) ; 
return old == READY; 
} 
#line 357 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static G* 
netpollunblock ( PollDesc *pd , int32 mode , bool ioready ) 
{ 
G **gpp , *old , *new; 
#line 362 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
gpp = &pd->rg; 
if ( mode == 'w' ) 
gpp = &pd->wg; 
#line 366 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
for ( ;; ) { 
old = *gpp; 
if ( old == READY ) 
return nil; 
if ( old == nil && !ioready ) { 
#line 373 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
return nil; 
} 
new = nil; 
if ( ioready ) 
new = READY; 
if ( runtime·casp ( gpp , old , new ) ) 
break; 
} 
if ( old > WAIT ) 
return old; 
return nil; 
} 
#line 386 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static void 
deadlineimpl ( int64 now , Eface arg , bool read , bool write ) 
{ 
PollDesc *pd; 
uint32 seq; 
G *rg , *wg; 
#line 393 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
USED ( now ) ; 
pd = ( PollDesc* ) arg.data; 
#line 397 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
seq = ( uintptr ) arg.type; 
rg = wg = nil; 
runtime·lock ( pd ) ; 
if ( seq != pd->seq ) { 
#line 402 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
runtime·unlock ( pd ) ; 
return; 
} 
if ( read ) { 
if ( pd->rd <= 0 || pd->rt.fv == nil ) 
runtime·throw ( "deadlineimpl: inconsistent read deadline" ) ; 
pd->rd = -1; 
runtime·atomicstorep ( &pd->rt.fv , nil ) ; 
rg = netpollunblock ( pd , 'r' , false ) ; 
} 
if ( write ) { 
if ( pd->wd <= 0 || ( pd->wt.fv == nil && !read ) ) 
runtime·throw ( "deadlineimpl: inconsistent write deadline" ) ; 
pd->wd = -1; 
runtime·atomicstorep ( &pd->wt.fv , nil ) ; 
wg = netpollunblock ( pd , 'w' , false ) ; 
} 
runtime·unlock ( pd ) ; 
if ( rg ) 
runtime·ready ( rg ) ; 
if ( wg ) 
runtime·ready ( wg ) ; 
} 
#line 426 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static void 
deadline ( int64 now , Eface arg ) 
{ 
deadlineimpl ( now , arg , true , true ) ; 
} 
#line 432 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static void 
readDeadline ( int64 now , Eface arg ) 
{ 
deadlineimpl ( now , arg , true , false ) ; 
} 
#line 438 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static void 
writeDeadline ( int64 now , Eface arg ) 
{ 
deadlineimpl ( now , arg , false , true ) ; 
} 
#line 444 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
static PollDesc* 
allocPollDesc ( void ) 
{ 
PollDesc *pd; 
uint32 i , n; 
#line 450 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
runtime·lock ( &pollcache ) ; 
if ( pollcache.first == nil ) { 
n = PollBlockSize/sizeof ( *pd ) ; 
if ( n == 0 ) 
n = 1; 
#line 457 "/home/pbulk/build/lang/go/work/go/src/pkg/runtime/netpoll.goc"
pd = runtime·persistentalloc ( n*sizeof ( *pd ) , 0 , &mstats.other_sys ) ; 
for ( i = 0; i < n; i++ ) { 
pd[i].link = pollcache.first; 
pollcache.first = &pd[i]; 
} 
} 
pd = pollcache.first; 
pollcache.first = pd->link; 
runtime·unlock ( &pollcache ) ; 
return pd; 
} 