Beispiel #1
0
void
runtime·makeslice(SliceType* t, int64 len, int64 cap, Slice ret)
{
	ret.array = 0;
	ret.len = 0;
	ret.cap = 0;
	FLUSH(&ret);
#line 24 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"

	// NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
	// but it produces a 'len out of range' error instead of a 'cap out of range' error
	// when someone does make([]T, bignumber). 'cap out of range' is true too,
	// but since the cap is only being supplied implicitly, saying len is clearer.
	// See issue 4085.
	if(len < 0 || (intgo)len != len || t->elem->size > 0 && len > MaxMem / t->elem->size)
		runtime·panicstring("makeslice: len out of range");

	if(cap < len || (intgo)cap != cap || t->elem->size > 0 && cap > MaxMem / t->elem->size)
		runtime·panicstring("makeslice: cap out of range");

	makeslice1(t, len, cap, &ret);

	if(debug) {
		runtime·printf("makeslice(%S, %D, %D); ret=",
			*t->string, len, cap);
		runtime·printslice(ret);
	}
	FLUSH(&ret);
}
Beispiel #2
0
void
runtime·growslice(SliceType* t, Slice old, int64 n, Slice ret)
{
	ret.array = 0;
	ret.len = 0;
	ret.cap = 0;
	FLUSH(&ret);
#line 59 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"

	int64 cap;
	void *pc;

	if(n < 1)
		runtime·panicstring("growslice: invalid n");

	cap = old.cap + n;

	if((intgo)cap != cap || cap < (int64)old.cap || (t->elem->size > 0 && cap > MaxMem/t->elem->size))
		runtime·panicstring("growslice: cap out of range");

	if(raceenabled) {
		pc = runtime·getcallerpc(&t);
		runtime·racereadrangepc(old.array, old.len*t->elem->size, pc, runtime·growslice);
	}

	growslice1(t, old, cap, &ret);

	if(debug) {
		runtime·printf("growslice(%S,", *t->string);
		runtime·printslice(old);
		runtime·printf(", new cap=%D) =", cap);
		runtime·printslice(ret);
	}
	FLUSH(&ret);
}
Beispiel #3
0
void
runtime·growslice(SliceType* t, Slice old, int64 n, Slice ret)
{
	ret.array = 0;
	ret.len = 0;
	ret.cap = 0;
	FLUSH(&ret);
#line 59 "/home/14/ren/source/golang/go/src/pkg/runtime/slice.goc"

	int64 cap;
	void *pc;

	if(n < 1)
		runtime·panicstring("growslice: invalid n");

	cap = old.cap + n;

	if((intgo)cap != cap || cap < (int64)old.cap || (t->elem->size > 0 && cap > MaxMem/t->elem->size))
		runtime·panicstring("growslice: cap out of range");

	if(raceenabled) {
		pc = runtime·getcallerpc(&t);
		runtime·racereadrangepc(old.array, old.len*t->elem->size, pc, runtime·growslice);
	}

	growslice1(t, old, cap, &ret);

	if(debug) {
		runtime·printf("growslice(%S,", *t->string);
		runtime·printslice(old);
		runtime·printf(", new cap=%D) =", cap);
		runtime·printslice(ret);
	}
	FLUSH(&ret);
}
Beispiel #4
0
void
runtime·sigpanic(void)
{
	switch(g->sig) {
	case EXCEPTION_ACCESS_VIOLATION:
		if(g->sigcode1 < 0x1000) {
			if(g->sigpc == 0)
				runtime·panicstring("call of nil func value");
			runtime·panicstring("invalid memory address or nil pointer dereference");
		}
		runtime·printf("unexpected fault address %p\n", g->sigcode1);
		runtime·throw("fault");
	case EXCEPTION_INT_DIVIDE_BY_ZERO:
		runtime·panicstring("integer divide by zero");
	case EXCEPTION_INT_OVERFLOW:
		runtime·panicstring("integer overflow");
	case EXCEPTION_FLT_DENORMAL_OPERAND:
	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
	case EXCEPTION_FLT_INEXACT_RESULT:
	case EXCEPTION_FLT_OVERFLOW:
	case EXCEPTION_FLT_UNDERFLOW:
		runtime·panicstring("floating point error");
	}
	runtime·throw("fault");
}
Beispiel #5
0
void
runtime·makeslice(SliceType* t, int64 len, int64 cap, Slice ret)
{
#line 24 "/home/pi/go_build/hg/go/src/pkg/runtime/slice.goc"

	// NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
	// but it produces a 'len out of range' error instead of a 'cap out of range' error
	// when someone does make([]T, bignumber). 'cap out of range' is true too,
	// but since the cap is only being supplied implicitly, saying len is clearer.
	// See issue 4085.
	if(len < 0 || (intgo)len != len || t->elem->size > 0 && len > MaxMem / t->elem->size)
		runtime·panicstring("makeslice: len out of range");

	if(cap < len || (intgo)cap != cap || t->elem->size > 0 && cap > MaxMem / t->elem->size)
		runtime·panicstring("makeslice: cap out of range");

	makeslice1(t, len, cap, &ret);

	if(debug) {
		runtime·printf("makeslice(%S, %D, %D); ret=",
			*t->string, len, cap);
		runtime·printslice(ret);
	}
	FLUSH(&ret);
}
Beispiel #6
0
// growslice(type *Type, x, []T, n int64) []T
void
runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
{
	int64 cap;
	void *pc;

	if(n < 1)
		runtime·panicstring("growslice: invalid n");

	cap = old.cap + n;

	if((intgo)cap != cap || cap < old.cap || (t->elem->size > 0 && cap > MaxMem/t->elem->size))
		runtime·panicstring("growslice: cap out of range");

	if(raceenabled) {
		pc = runtime·getcallerpc(&t);
		runtime·racereadrangepc(old.array, old.len*t->elem->size, t->elem->size, pc, runtime·growslice);
	}

	growslice1(t, old, cap, &ret);

	FLUSH(&ret);

	if(debug) {
		runtime·printf("growslice(%S,", *t->string);
		runtime·printslice(old);
		runtime·printf(", new cap=%D) =", cap);
		runtime·printslice(ret);
	}
}
Beispiel #7
0
void
runtime·sigpanic(void)
{
	// Native Client only invokes the exception handler for memory faults.
	g->sig = SIGSEGV;
	if(g->sigpc == 0)
		runtime·panicstring("call of nil func value");
	runtime·panicstring("invalid memory address or nil pointer dereference");
}
Beispiel #8
0
void
runtime·sigpanic(void)
{
	if(g->sigpc == 0)
		runtime·panicstring("call of nil func value");
	runtime·panicstring(m->notesig);

	if(g->sig == 1 || g->sig == 2)
		runtime·throw("fault");
}
Beispiel #9
0
runtime·compilecallback(Eface fn, bool cleanstack)
{
	FuncType *ft;
	Type *t;
	int32 argsize, i, n;
	WinCallbackContext *c;

	if(fn.type == nil || (fn.type->kind&KindMask) != KindFunc)
		runtime·panicstring("compilecallback: not a function");
	ft = (FuncType*)fn.type;
	if(ft->out.len != 1)
		runtime·panicstring("compilecallback: function must have one output parameter");
	if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
		runtime·panicstring("compilecallback: output parameter size is wrong");
	argsize = 0;
	for(i=0; i<ft->in.len; i++) {
		t = ((Type**)ft->in.array)[i];
		if(t->size > sizeof(uintptr))
			runtime·panicstring("compilecallback: input parameter size is wrong");
		argsize += sizeof(uintptr);
	}

	runtime·lock(&cbs.lock);
	if(runtime·cbctxts == nil)
		runtime·cbctxts = &(cbs.ctxt[0]);
	n = cbs.n;
	for(i=0; i<n; i++) {
		if(cbs.ctxt[i]->gobody == fn.data && cbs.ctxt[i]->cleanstack == cleanstack) {
			runtime·unlock(&cbs.lock);
			// runtime·callbackasm is just a series of CALL instructions
			// (each is 5 bytes long), and we want callback to arrive at
			// correspondent call instruction instead of start of
			// runtime·callbackasm.
			return (byte*)runtime·callbackasm + i * 5;
		}
	}
	if(n >= cb_max)
		runtime·throw("too many callback functions");
	c = runtime·mallocgc(sizeof *c, nil, 0);
	c->gobody = fn.data;
	c->argsize = argsize;
	c->cleanstack = cleanstack;
	if(cleanstack && argsize!=0)
		c->restorestack = argsize;
	else
		c->restorestack = 0;
	cbs.ctxt[n] = c;
	cbs.n++;
	runtime·unlock(&cbs.lock);

	// as before
	return (byte*)runtime·callbackasm + n * 5;
}
Beispiel #10
0
void
runtime·sigpanic(void)
{
	if(!runtime·canpanic(g))
		runtime·throw("unexpected signal during runtime execution");

	// Native Client only invokes the exception handler for memory faults.
	g->sig = SIGSEGV;
	if(g->sigpc == 0)
		runtime·panicstring("call of nil func value");
	runtime·panicstring("invalid memory address or nil pointer dereference");
}
Beispiel #11
0
void
runtime·sigpanic(void)
{
	switch(g->sig) {
	case SIGBUS:
		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
			if(g->sigpc == 0)
				runtime·panicstring("call of nil func value");
			runtime·panicstring("invalid memory address or nil pointer dereference");
		}
		runtime·printf("unexpected fault address %p\n", g->sigcode1);
		runtime·throw("fault");
	case SIGSEGV:
		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
			if(g->sigpc == 0)
				runtime·panicstring("call of nil func value");
			runtime·panicstring("invalid memory address or nil pointer dereference");
		}
		runtime·printf("unexpected fault address %p\n", g->sigcode1);
		runtime·throw("fault");
	case SIGFPE:
		switch(g->sigcode0) {
		case FPE_INTDIV:
			runtime·panicstring("integer divide by zero");
		case FPE_INTOVF:
			runtime·panicstring("integer overflow");
		}
		runtime·panicstring("floating point error");
	}
	runtime·panicstring(runtime·sigtab[g->sig].name);
}
Beispiel #12
0
runtime·makechan_c(ChanType *t, int64 hint)
{
	Hchan *c;
	int32 n;
	Type *elem;

	elem = t->elem;

	if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
		runtime·panicstring("makechan: size out of range");

	// calculate rounded size of Hchan
	n = sizeof(*c);
	while(n & MAXALIGN)
		n++;

	// allocate memory in one call
	c = (Hchan*)runtime·mal(n + hint*elem->size);
	c->elemsize = elem->size;
	c->elemalg = elem->alg;
	c->elemalign = elem->align;
	c->dataqsiz = hint;

	if(debug)
		runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%d\n",
			c, (int64)elem->size, elem->alg, elem->align, c->dataqsiz);

	return c;
}
Beispiel #13
0
static Hchan* 
makechan ( ChanType *t , int64 hint ) 
{ 
Hchan *c; 
Type *elem; 
#line 28 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
elem = t->elem; 
#line 31 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( elem->size >= ( 1<<16 ) ) 
runtime·throw ( "makechan: invalid channel element type" ) ; 
if ( ( sizeof ( *c ) %MAXALIGN ) != 0 || elem->align > MAXALIGN ) 
runtime·throw ( "makechan: bad alignment" ) ; 
#line 36 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( hint < 0 || ( intgo ) hint != hint || ( elem->size > 0 && hint > ( MaxMem - sizeof ( *c ) ) / elem->size ) ) 
runtime·panicstring ( "makechan: size out of range" ) ; 
#line 40 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
c = ( Hchan* ) runtime·mallocgc ( sizeof ( *c ) + hint*elem->size , ( uintptr ) t | TypeInfo_Chan , 0 ) ; 
c->elemsize = elem->size; 
c->elemtype = elem; 
c->dataqsiz = hint; 
#line 45 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( debug ) 
runtime·printf ( "makechan: chan=%p; elemsize=%D; elemalg=%p; dataqsiz=%D\n" , 
c , ( int64 ) elem->size , elem->alg , ( int64 ) c->dataqsiz ) ; 
#line 49 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
return c; 
} 
Beispiel #14
0
// see also unsafe·NewArray
// makeslice(typ *Type, len, cap int64) (ary []any);
void
runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
{
	if(len < 0 || (int32)len != len)
		runtime·panicstring("makeslice: len out of range");
	if(cap < len || (int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
		runtime·panicstring("makeslice: cap out of range");

	makeslice1(t, len, cap, &ret);

	if(debug) {
		runtime·printf("makeslice(%S, %D, %D); ret=",
			*t->string, len, cap);
 		runtime·printslice(ret);
	}
}
Beispiel #15
0
runtime·makechan_c(ChanType *t, int64 hint)
{
	Hchan *c;
	uintptr n;
	Type *elem;

	elem = t->elem;

	// compiler checks this but be safe.
	if(elem->size >= (1<<16))
		runtime·throw("makechan: invalid channel element type");

	if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem / elem->size))
		runtime·panicstring("makechan: size out of range");

	// calculate rounded size of Hchan
	n = sizeof(*c);
	while(n & MAXALIGN)
		n++;

	// allocate memory in one call
	c = (Hchan*)runtime·mal(n + hint*elem->size);
	c->elemsize = elem->size;
	c->elemalg = elem->alg;
	c->elemalign = elem->align;
	c->dataqsiz = hint;
	runtime·settype(c, (uintptr)t | TypeInfo_Chan);

	if(debug)
		runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%D\n",
			c, (int64)elem->size, elem->alg, elem->align, (int64)c->dataqsiz);

	return c;
}
Beispiel #16
0
// complex128div(num, den complex128) (quo complex128)
void
·complex128div(float64 numreal, float64 numimag,
	float64 denreal, float64 denimag,
	float64 quoreal, float64 quoimag)
{
	float64 a, b, ratio, denom;

	a = denreal;
	if(a < 0)
		a = -a;
	b = denimag;
	if(b < 0)
		b = -b;
	if(a <= b) {
		if(b == 0)
			panicstring("complex divide by zero");
		ratio = denreal/denimag;
		denom = denreal*ratio + denimag;
		quoreal = (numreal*ratio + numimag) / denom;
		quoimag = (numimag*ratio - numreal) / denom;
	} else {
		ratio = denimag/denreal;
		denom = denimag*ratio + denreal;
		quoreal = (numimag*ratio + numreal) / denom;
		quoimag = (numimag - numreal*ratio) / denom;
	}
	FLUSH(&quoreal);
	FLUSH(&quoimag);
}
Beispiel #17
0
void
runtime·closechan(Hchan *c)
{
	SudoG *sg;
	G* gp;

	if(c == nil)
		runtime·panicstring("close of nil channel");

	if(runtime·gcwaiting)
		runtime·gosched();

	runtime·lock(c);
	if(c->closed) {
		runtime·unlock(c);
		runtime·panicstring("close of closed channel");
	}

	if(raceenabled) {
		runtime·racewritepc(c, runtime·getcallerpc(&c), runtime·closechan);
		runtime·racerelease(c);
	}

	c->closed = true;

	// release all readers
	for(;;) {
		sg = dequeue(&c->recvq);
		if(sg == nil)
			break;
		gp = sg->g;
		gp->param = nil;
		runtime·ready(gp);
	}

	// release all writers
	for(;;) {
		sg = dequeue(&c->sendq);
		if(sg == nil)
			break;
		gp = sg->g;
		gp->param = nil;
		runtime·ready(gp);
	}

	runtime·unlock(c);
}
Beispiel #18
0
static void 
closechan ( Hchan *c , void *pc ) 
{ 
SudoG *sg; 
G* gp; 
#line 1045 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
if ( c == nil ) 
runtime·panicstring ( "close of nil channel" ) ; 
#line 1048 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
runtime·lock ( c ) ; 
if ( c->closed ) { 
runtime·unlock ( c ) ; 
runtime·panicstring ( "close of closed channel" ) ; 
} 
#line 1054 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
runtime·racewritepc ( c , pc , runtime·closechan ) ; 
runtime·racerelease ( c ) ; 
} 
#line 1059 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
c->closed = true; 
#line 1062 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
for ( ;; ) { 
sg = dequeue ( &c->recvq ) ; 
if ( sg == nil ) 
break; 
gp = sg->g; 
gp->param = nil; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} 
#line 1074 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
for ( ;; ) { 
sg = dequeue ( &c->sendq ) ; 
if ( sg == nil ) 
break; 
gp = sg->g; 
gp->param = nil; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} 
#line 1085 "/home/14/ren/source/golang/go/src/pkg/runtime/chan.goc"
runtime·unlock ( c ) ; 
} 
Beispiel #19
0
static void 
closechan ( Hchan *c , void *pc ) 
{ 
SudoG *sg; 
G* gp; 
#line 1041 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( c == nil ) 
runtime·panicstring ( "close of nil channel" ) ; 
#line 1044 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
runtime·lock ( c ) ; 
if ( c->closed ) { 
runtime·unlock ( c ) ; 
runtime·panicstring ( "close of closed channel" ) ; 
} 
#line 1050 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
runtime·racewritepc ( c , pc , runtime·closechan ) ; 
runtime·racerelease ( c ) ; 
} 
#line 1055 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
c->closed = true; 
#line 1058 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
for ( ;; ) { 
sg = dequeue ( &c->recvq ) ; 
if ( sg == nil ) 
break; 
gp = sg->g; 
gp->param = nil; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} 
#line 1070 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
for ( ;; ) { 
sg = dequeue ( &c->sendq ) ; 
if ( sg == nil ) 
break; 
gp = sg->g; 
gp->param = nil; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} 
#line 1081 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
runtime·unlock ( c ) ; 
} 
Beispiel #20
0
void
TestRealloc(void) {
	void *p=0;

	// see: http://pubs.opengroup.org/onlinepubs/7999959899/functions/realloc.html

	free(0); // defined: no action shall occur.
	free(0);
	free(0);
	if (p=realloc(0, 0), p!=0) // NOTE: result need not be 0, but 0 would be good practice.
		runtime·panicstring("realloc failed 1");

	if (p=realloc(0, 10), p==0)
		runtime·panicstring("realloc failed 2");
	CHARP(p)[9] = 9; // trying to check here that no segfault occurs
	CHARP(p)[8] = 8;

	if (p=realloc(p, 9), CHARP(p)[8]!=8)
		runtime·panicstring("realloc failed 3");

	if (p=realloc(p, 10), p==0)
		runtime·panicstring("realloc failed 4");
	if (CHARP(p)[8]!=8)
		runtime·panicstring("realloc failed 5");

	if (p=realloc(p, 0), p!=0) // NOTE: result need not be 0, but 0 would be good practice.
		runtime·panicstring("realloc failed 6");
}
Beispiel #21
0
// growslice(type *Type, x, []T, n int64) []T
void
runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
{
	int64 cap;

	if(n < 1)
		runtime·panicstring("growslice: invalid n");

	cap = old.cap + n;

	if((int32)cap != cap || cap > ((uintptr)-1) / t->elem->size)
		runtime·panicstring("growslice: cap out of range");

	growslice1(t, old, cap, &ret);

	FLUSH(&ret);

	if(debug) {
		runtime·printf("growslice(%S,", *t->string);
 		runtime·printslice(old);
		runtime·printf(", new cap=%D) =", cap);
 		runtime·printslice(ret);
	}
}
Beispiel #22
0
// make([]T, len, cap)会调用到这个函数来。注意这里的ret是整个结构体传进来的。所以按go的函数调用协议,返回值在栈中的布局其实是一个结构体而不是结构体指针。
// see also unsafe·NewArray
// makeslice(typ *Type, len, cap int64) (ary []any);
void
runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
{
	// NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
	// but it produces a 'len out of range' error instead of a 'cap out of range' error
	// when someone does make([]T, bignumber). 'cap out of range' is true too,
	// but since the cap is only being supplied implicitly, saying len is clearer.
	// See issue 4085.
	//(intgo)len != len是将len强制转换为go的int(依赖于机器位数,32或64),这就说明make([]T, len, cap)上面支持的len其实是int类型的
	//也就意味着,在32位机器上,传一个很大的数,超过32位能表示的范围是会出错的。64位机器上没什么感觉。
	if(len < 0 || (intgo)len != len || t->elem->size > 0 && len > MaxMem / t->elem->size)
		runtime·panicstring("makeslice: len out of range");

	if(cap < len || (intgo)cap != cap || t->elem->size > 0 && cap > MaxMem / t->elem->size)
		runtime·panicstring("makeslice: cap out of range");

	makeslice1(t, len, cap, &ret);

	if(debug) {
		runtime·printf("makeslice(%S, %D, %D); ret=",
			*t->string, len, cap);
		runtime·printslice(ret);
	}
}
Beispiel #23
0
static void 
growslice1 ( SliceType *t , Slice x , intgo newcap , Slice *ret ) 
{ 
intgo newcap1; 
uintptr capmem , lenmem; 
int32 flag; 
Type *typ; 
#line 94 "/home/pi/go_build/hg/go/src/pkg/runtime/slice.goc"
typ = t->elem; 
if ( typ->size == 0 ) { 
*ret = x; 
ret->cap = newcap; 
return; 
} 
#line 101 "/home/pi/go_build/hg/go/src/pkg/runtime/slice.goc"
newcap1 = x.cap; 
#line 107 "/home/pi/go_build/hg/go/src/pkg/runtime/slice.goc"
if ( newcap1+newcap1 < newcap ) 
newcap1 = newcap; 
else { 
do { 
if ( x.len < 1024 ) 
newcap1 += newcap1; 
else 
newcap1 += newcap1/4; 
} while ( newcap1 < newcap ) ; 
} 
#line 118 "/home/pi/go_build/hg/go/src/pkg/runtime/slice.goc"
if ( newcap1 > MaxMem/typ->size ) 
runtime·panicstring ( "growslice: cap out of range" ) ; 
capmem = runtime·roundupsize ( newcap1*typ->size ) ; 
flag = FlagNoZero; 
if ( typ->kind&KindNoPointers ) 
flag |= FlagNoScan; 
#line 126 "/home/pi/go_build/hg/go/src/pkg/runtime/slice.goc"
m->locks++; 
ret->array = runtime·mallocgc ( capmem , ( uintptr ) typ|TypeInfo_Array , flag ) ; 
ret->len = x.len; 
ret->cap = capmem/typ->size; 
lenmem = x.len*typ->size; 
runtime·memmove ( ret->array , x.array , lenmem ) ; 
runtime·memclr ( ret->array+lenmem , capmem-lenmem ) ; 
m->locks--; 
if ( m->locks == 0 && g->preempt ) 
g->stackguard0 = StackPreempt; 
} 
Beispiel #24
0
static void 
growslice1 ( SliceType *t , Slice x , intgo newcap , Slice *ret ) 
{ 
intgo newcap1; 
uintptr capmem , lenmem; 
int32 flag; 
Type *typ; 
#line 94 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"
typ = t->elem; 
if ( typ->size == 0 ) { 
*ret = x; 
ret->cap = newcap; 
return; 
} 
#line 101 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"
newcap1 = x.cap; 
#line 107 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"
if ( newcap1+newcap1 < newcap ) 
newcap1 = newcap; 
else { 
do { 
if ( x.len < 1024 ) 
newcap1 += newcap1; 
else 
newcap1 += newcap1/4; 
} while ( newcap1 < newcap ) ; 
} 
#line 118 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"
if ( newcap1 > MaxMem/typ->size ) 
runtime·panicstring ( "growslice: cap out of range" ) ; 
capmem = runtime·roundupsize ( newcap1*typ->size ) ; 
flag = 0; 
#line 123 "C:\Users\ADMINI~1\AppData\Local\Temp\2\makerelease686069423\go\src\pkg\runtime\slice.goc"
if ( typ->kind&KindNoPointers ) 
flag = FlagNoScan|FlagNoZero; 
ret->array = runtime·mallocgc ( capmem , ( uintptr ) typ|TypeInfo_Array , flag ) ; 
ret->len = x.len; 
ret->cap = capmem/typ->size; 
lenmem = x.len*typ->size; 
runtime·memmove ( ret->array , x.array , lenmem ) ; 
if ( typ->kind&KindNoPointers ) 
runtime·memclr ( ret->array+lenmem , capmem-lenmem ) ; 
} 
Beispiel #25
0
void
sigpanic(void)
{
	switch(g->sig) {
	case SIGBUS:
		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
			panicstring("invalid memory address or nil pointer dereference");
		break;
	case SIGSEGV:
		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR) && g->sigcode1 < 0x1000)
			panicstring("invalid memory address or nil pointer dereference");
		break;
	case SIGFPE:
		switch(g->sigcode0) {
		case FPE_INTDIV:
			panicstring("integer divide by zero");
		case FPE_INTOVF:
			panicstring("integer overflow");
		}
		panicstring("floating point error");
	}
	panicstring(sigtab[g->sig].name);
}
Beispiel #26
0
void
runtime·panicslice(void)
{
	runtime·panicstring("slice bounds out of range");
}
Beispiel #27
0
void
runtime·panicindex(void)
{
	runtime·panicstring("index out of range");
}
Beispiel #28
0
static bool 
chansend ( ChanType *t , Hchan *c , byte *ep , bool block , void *pc ) 
{ 
SudoG *sg; 
SudoG mysg; 
G* gp; 
int64 t0; 
#line 82 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) 
runtime·racereadobjectpc ( ep , t->elem , runtime·getcallerpc ( &t ) , chansend ) ; 
#line 85 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( c == nil ) { 
USED ( t ) ; 
if ( !block ) 
return false; 
runtime·park ( nil , nil , "chan send (nil chan)" ) ; 
return false; 
} 
#line 93 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( debug ) { 
runtime·printf ( "chansend: chan=%p; elem=" , c ) ; 
c->elemtype->alg->print ( c->elemsize , ep ) ; 
runtime·prints ( "\n" ) ; 
} 
#line 99 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
t0 = 0; 
mysg.releasetime = 0; 
if ( runtime·blockprofilerate > 0 ) { 
t0 = runtime·cputicks ( ) ; 
mysg.releasetime = -1; 
} 
#line 106 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
runtime·lock ( c ) ; 
if ( raceenabled ) 
runtime·racereadpc ( c , pc , chansend ) ; 
if ( c->closed ) 
goto closed; 
#line 112 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( c->dataqsiz > 0 ) 
goto asynch; 
#line 115 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
sg = dequeue ( &c->recvq ) ; 
if ( sg != nil ) { 
if ( raceenabled ) 
racesync ( c , sg ) ; 
runtime·unlock ( c ) ; 
#line 121 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
gp = sg->g; 
gp->param = sg; 
if ( sg->elem != nil ) 
c->elemtype->alg->copy ( c->elemsize , sg->elem , ep ) ; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
return true; 
} 
#line 131 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( !block ) { 
runtime·unlock ( c ) ; 
return false; 
} 
#line 136 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
mysg.elem = ep; 
mysg.g = g; 
mysg.selectdone = nil; 
g->param = nil; 
enqueue ( &c->sendq , &mysg ) ; 
runtime·parkunlock ( c , "chan send" ) ; 
#line 143 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( g->param == nil ) { 
runtime·lock ( c ) ; 
if ( !c->closed ) 
runtime·throw ( "chansend: spurious wakeup" ) ; 
goto closed; 
} 
#line 150 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( mysg.releasetime > 0 ) 
runtime·blockevent ( mysg.releasetime - t0 , 2 ) ; 
#line 153 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
return true; 
#line 155 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
asynch: 
if ( c->closed ) 
goto closed; 
#line 159 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( c->qcount >= c->dataqsiz ) { 
if ( !block ) { 
runtime·unlock ( c ) ; 
return false; 
} 
mysg.g = g; 
mysg.elem = nil; 
mysg.selectdone = nil; 
enqueue ( &c->sendq , &mysg ) ; 
runtime·parkunlock ( c , "chan send" ) ; 
#line 170 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
runtime·lock ( c ) ; 
goto asynch; 
} 
#line 174 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
runtime·raceacquire ( chanbuf ( c , c->sendx ) ) ; 
runtime·racerelease ( chanbuf ( c , c->sendx ) ) ; 
} 
#line 179 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
c->elemtype->alg->copy ( c->elemsize , chanbuf ( c , c->sendx ) , ep ) ; 
if ( ++c->sendx == c->dataqsiz ) 
c->sendx = 0; 
c->qcount++; 
#line 184 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
sg = dequeue ( &c->recvq ) ; 
if ( sg != nil ) { 
gp = sg->g; 
runtime·unlock ( c ) ; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} else 
runtime·unlock ( c ) ; 
if ( mysg.releasetime > 0 ) 
runtime·blockevent ( mysg.releasetime - t0 , 2 ) ; 
return true; 
#line 197 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
closed: 
runtime·unlock ( c ) ; 
runtime·panicstring ( "send on closed channel" ) ; 
return false; 
} 
Beispiel #29
0
static void* 
selectgo ( Select **selp ) 
{ 
Select *sel; 
uint32 o , i , j , k , done; 
int64 t0; 
Scase *cas , *dfl; 
Hchan *c; 
SudoG *sg; 
G *gp; 
byte *as; 
void *pc; 
#line 663 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
sel = *selp; 
#line 665 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( debug ) 
runtime·printf ( "select: sel=%p\n" , sel ) ; 
#line 668 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
t0 = 0; 
if ( runtime·blockprofilerate > 0 ) { 
t0 = runtime·cputicks ( ) ; 
for ( i=0; i<sel->ncase; i++ ) 
sel->scase[i].sg.releasetime = -1; 
} 
#line 684 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
for ( i=0; i<sel->ncase; i++ ) 
sel->pollorder[i] = i; 
for ( i=1; i<sel->ncase; i++ ) { 
o = sel->pollorder[i]; 
j = runtime·fastrand1 ( ) % ( i+1 ) ; 
sel->pollorder[i] = sel->pollorder[j]; 
sel->pollorder[j] = o; 
} 
#line 695 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
for ( i=0; i<sel->ncase; i++ ) { 
j = i; 
c = sel->scase[j].chan; 
while ( j > 0 && sel->lockorder[k= ( j-1 ) /2] < c ) { 
sel->lockorder[j] = sel->lockorder[k]; 
j = k; 
} 
sel->lockorder[j] = c; 
} 
for ( i=sel->ncase; i-->0; ) { 
c = sel->lockorder[i]; 
sel->lockorder[i] = sel->lockorder[0]; 
j = 0; 
for ( ;; ) { 
k = j*2+1; 
if ( k >= i ) 
break; 
if ( k+1 < i && sel->lockorder[k] < sel->lockorder[k+1] ) 
k++; 
if ( c < sel->lockorder[k] ) { 
sel->lockorder[j] = sel->lockorder[k]; 
j = k; 
continue; 
} 
break; 
} 
sel->lockorder[j] = c; 
} 
#line 730 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
sellock ( sel ) ; 
#line 732 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
loop: 
#line 734 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
dfl = nil; 
for ( i=0; i<sel->ncase; i++ ) { 
o = sel->pollorder[i]; 
cas = &sel->scase[o]; 
c = cas->chan; 
#line 740 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
switch ( cas->kind ) { 
case CaseRecv: 
if ( c->dataqsiz > 0 ) { 
if ( c->qcount > 0 ) 
goto asyncrecv; 
} else { 
sg = dequeue ( &c->sendq ) ; 
if ( sg != nil ) 
goto syncrecv; 
} 
if ( c->closed ) 
goto rclose; 
break; 
#line 754 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
case CaseSend: 
if ( raceenabled ) 
runtime·racereadpc ( c , cas->pc , chansend ) ; 
if ( c->closed ) 
goto sclose; 
if ( c->dataqsiz > 0 ) { 
if ( c->qcount < c->dataqsiz ) 
goto asyncsend; 
} else { 
sg = dequeue ( &c->recvq ) ; 
if ( sg != nil ) 
goto syncsend; 
} 
break; 
#line 769 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
case CaseDefault: 
dfl = cas; 
break; 
} 
} 
#line 775 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( dfl != nil ) { 
selunlock ( sel ) ; 
cas = dfl; 
goto retc; 
} 
#line 783 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
done = 0; 
for ( i=0; i<sel->ncase; i++ ) { 
o = sel->pollorder[i]; 
cas = &sel->scase[o]; 
c = cas->chan; 
sg = &cas->sg; 
sg->g = g; 
sg->selectdone = &done; 
#line 792 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
switch ( cas->kind ) { 
case CaseRecv: 
enqueue ( &c->recvq , sg ) ; 
break; 
#line 797 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
case CaseSend: 
enqueue ( &c->sendq , sg ) ; 
break; 
} 
} 
#line 803 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
g->param = nil; 
runtime·park ( selparkcommit , sel , "select" ) ; 
#line 806 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
sellock ( sel ) ; 
sg = g->param; 
#line 811 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
for ( i=0; i<sel->ncase; i++ ) { 
cas = &sel->scase[i]; 
if ( cas != ( Scase* ) sg ) { 
c = cas->chan; 
if ( cas->kind == CaseSend ) 
dequeueg ( &c->sendq ) ; 
else 
dequeueg ( &c->recvq ) ; 
} 
} 
#line 822 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( sg == nil ) 
goto loop; 
#line 825 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
cas = ( Scase* ) sg; 
c = cas->chan; 
#line 828 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( c->dataqsiz > 0 ) 
runtime·throw ( "selectgo: shouldn't happen" ) ; 
#line 831 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( debug ) 
runtime·printf ( "wait-return: sel=%p c=%p cas=%p kind=%d\n" , 
sel , c , cas , cas->kind ) ; 
#line 835 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( cas->kind == CaseRecv ) { 
if ( cas->receivedp != nil ) 
*cas->receivedp = true; 
} 
#line 840 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
if ( cas->kind == CaseRecv && cas->sg.elem != nil ) 
runtime·racewriteobjectpc ( cas->sg.elem , c->elemtype , cas->pc , chanrecv ) ; 
else if ( cas->kind == CaseSend ) 
runtime·racereadobjectpc ( cas->sg.elem , c->elemtype , cas->pc , chansend ) ; 
} 
#line 847 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
selunlock ( sel ) ; 
goto retc; 
#line 850 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
asyncrecv: 
#line 852 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
if ( cas->sg.elem != nil ) 
runtime·racewriteobjectpc ( cas->sg.elem , c->elemtype , cas->pc , chanrecv ) ; 
runtime·raceacquire ( chanbuf ( c , c->recvx ) ) ; 
runtime·racerelease ( chanbuf ( c , c->recvx ) ) ; 
} 
if ( cas->receivedp != nil ) 
*cas->receivedp = true; 
if ( cas->sg.elem != nil ) 
c->elemtype->alg->copy ( c->elemsize , cas->sg.elem , chanbuf ( c , c->recvx ) ) ; 
c->elemtype->alg->copy ( c->elemsize , chanbuf ( c , c->recvx ) , nil ) ; 
if ( ++c->recvx == c->dataqsiz ) 
c->recvx = 0; 
c->qcount--; 
sg = dequeue ( &c->sendq ) ; 
if ( sg != nil ) { 
gp = sg->g; 
selunlock ( sel ) ; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} else { 
selunlock ( sel ) ; 
} 
goto retc; 
#line 878 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
asyncsend: 
#line 880 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
runtime·raceacquire ( chanbuf ( c , c->sendx ) ) ; 
runtime·racerelease ( chanbuf ( c , c->sendx ) ) ; 
runtime·racereadobjectpc ( cas->sg.elem , c->elemtype , cas->pc , chansend ) ; 
} 
c->elemtype->alg->copy ( c->elemsize , chanbuf ( c , c->sendx ) , cas->sg.elem ) ; 
if ( ++c->sendx == c->dataqsiz ) 
c->sendx = 0; 
c->qcount++; 
sg = dequeue ( &c->recvq ) ; 
if ( sg != nil ) { 
gp = sg->g; 
selunlock ( sel ) ; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
} else { 
selunlock ( sel ) ; 
} 
goto retc; 
#line 901 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
syncrecv: 
#line 903 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
if ( cas->sg.elem != nil ) 
runtime·racewriteobjectpc ( cas->sg.elem , c->elemtype , cas->pc , chanrecv ) ; 
racesync ( c , sg ) ; 
} 
selunlock ( sel ) ; 
if ( debug ) 
runtime·printf ( "syncrecv: sel=%p c=%p o=%d\n" , sel , c , o ) ; 
if ( cas->receivedp != nil ) 
*cas->receivedp = true; 
if ( cas->sg.elem != nil ) 
c->elemtype->alg->copy ( c->elemsize , cas->sg.elem , sg->elem ) ; 
gp = sg->g; 
gp->param = sg; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
goto retc; 
#line 922 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
rclose: 
#line 924 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
selunlock ( sel ) ; 
if ( cas->receivedp != nil ) 
*cas->receivedp = false; 
if ( cas->sg.elem != nil ) 
c->elemtype->alg->copy ( c->elemsize , cas->sg.elem , nil ) ; 
if ( raceenabled ) 
runtime·raceacquire ( c ) ; 
goto retc; 
#line 933 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
syncsend: 
#line 935 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
if ( raceenabled ) { 
runtime·racereadobjectpc ( cas->sg.elem , c->elemtype , cas->pc , chansend ) ; 
racesync ( c , sg ) ; 
} 
selunlock ( sel ) ; 
if ( debug ) 
runtime·printf ( "syncsend: sel=%p c=%p o=%d\n" , sel , c , o ) ; 
if ( sg->elem != nil ) 
c->elemtype->alg->copy ( c->elemsize , sg->elem , cas->sg.elem ) ; 
gp = sg->g; 
gp->param = sg; 
if ( sg->releasetime ) 
sg->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( gp ) ; 
#line 950 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
retc: 
#line 956 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
pc = cas->pc; 
if ( cas->so > 0 ) { 
as = ( byte* ) selp + cas->so; 
*as = true; 
} 
if ( cas->sg.releasetime > 0 ) 
runtime·blockevent ( cas->sg.releasetime - t0 , 2 ) ; 
runtime·free ( sel ) ; 
return pc; 
#line 966 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
sclose: 
#line 968 "/tmp/makerelease402042453/go/src/pkg/runtime/chan.goc"
selunlock ( sel ) ; 
runtime·panicstring ( "send on closed channel" ) ; 
return nil; 
} 
Beispiel #30
0
static void*
selectgo(Select **selp)
{
	Select *sel;
	uint32 o, i, j;
	Scase *cas, *dfl;
	Hchan *c;
	SudoG *sg;
	G *gp;
	byte *as;
	void *pc;

	sel = *selp;
	if(runtime·gcwaiting)
		runtime·gosched();

	if(debug)
		runtime·printf("select: sel=%p\n", sel);

	// The compiler rewrites selects that statically have
	// only 0 or 1 cases plus default into simpler constructs.
	// The only way we can end up with such small sel->ncase
	// values here is for a larger select in which most channels
	// have been nilled out.  The general code handles those
	// cases correctly, and they are rare enough not to bother
	// optimizing (and needing to test).

	// generate permuted order
	for(i=0; i<sel->ncase; i++)
		sel->pollorder[i] = i;
	for(i=1; i<sel->ncase; i++) {
		o = sel->pollorder[i];
		j = runtime·fastrand1()%(i+1);
		sel->pollorder[i] = sel->pollorder[j];
		sel->pollorder[j] = o;
	}

	// sort the cases by Hchan address to get the locking order.
	for(i=0; i<sel->ncase; i++) {
		c = sel->scase[i].chan;
		for(j=i; j>0 && sel->lockorder[j-1] >= c; j--)
			sel->lockorder[j] = sel->lockorder[j-1];
		sel->lockorder[j] = c;
	}
	sellock(sel);

loop:
	// pass 1 - look for something already waiting
	dfl = nil;
	for(i=0; i<sel->ncase; i++) {
		o = sel->pollorder[i];
		cas = &sel->scase[o];
		c = cas->chan;

		switch(cas->kind) {
		case CaseRecv:
			if(c->dataqsiz > 0) {
				if(c->qcount > 0)
					goto asyncrecv;
			} else {
				sg = dequeue(&c->sendq);
				if(sg != nil)
					goto syncrecv;
			}
			if(c->closed)
				goto rclose;
			break;

		case CaseSend:
			if(c->closed)
				goto sclose;
			if(c->dataqsiz > 0) {
				if(c->qcount < c->dataqsiz)
					goto asyncsend;
			} else {
				sg = dequeue(&c->recvq);
				if(sg != nil)
					goto syncsend;
			}
			break;

		case CaseDefault:
			dfl = cas;
			break;
		}
	}

	if(dfl != nil) {
		selunlock(sel);
		cas = dfl;
		goto retc;
	}


	// pass 2 - enqueue on all chans
	for(i=0; i<sel->ncase; i++) {
		o = sel->pollorder[i];
		cas = &sel->scase[o];
		c = cas->chan;
		sg = &cas->sg;
		sg->g = g;
		sg->selgen = g->selgen;

		switch(cas->kind) {
		case CaseRecv:
			enqueue(&c->recvq, sg);
			break;

		case CaseSend:
			enqueue(&c->sendq, sg);
			break;
		}
	}

	g->param = nil;
	g->status = Gwaiting;
	g->waitreason = "select";
	selunlock(sel);
	runtime·gosched();

	sellock(sel);
	sg = g->param;

	// pass 3 - dequeue from unsuccessful chans
	// otherwise they stack up on quiet channels
	for(i=0; i<sel->ncase; i++) {
		cas = &sel->scase[i];
		if(cas != (Scase*)sg) {
			c = cas->chan;
			if(cas->kind == CaseSend)
				dequeueg(&c->sendq);
			else
				dequeueg(&c->recvq);
		}
	}

	if(sg == nil)
		goto loop;

	cas = (Scase*)sg;
	c = cas->chan;

	if(c->dataqsiz > 0)
		runtime·throw("selectgo: shouldnt happen");

	if(debug)
		runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
			sel, c, cas, cas->kind);

	if(cas->kind == CaseRecv) {
		if(cas->receivedp != nil)
			*cas->receivedp = true;
	}

	selunlock(sel);
	goto retc;

asyncrecv:
	// can receive from buffer
	if(cas->receivedp != nil)
		*cas->receivedp = true;
	if(cas->sg.elem != nil)
		c->elemalg->copy(c->elemsize, cas->sg.elem, chanbuf(c, c->recvx));
	c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
	if(++c->recvx == c->dataqsiz)
		c->recvx = 0;
	c->qcount--;
	sg = dequeue(&c->sendq);
	if(sg != nil) {
		gp = sg->g;
		selunlock(sel);
		runtime·ready(gp);
	} else {
		selunlock(sel);
	}
	goto retc;

asyncsend:
	// can send to buffer
	c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem);
	if(++c->sendx == c->dataqsiz)
		c->sendx = 0;
	c->qcount++;
	sg = dequeue(&c->recvq);
	if(sg != nil) {
		gp = sg->g;
		selunlock(sel);
		runtime·ready(gp);
	} else {
		selunlock(sel);
	}
	goto retc;

syncrecv:
	// can receive from sleeping sender (sg)
	selunlock(sel);
	if(debug)
		runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
	if(cas->receivedp != nil)
		*cas->receivedp = true;
	if(cas->sg.elem != nil)
		c->elemalg->copy(c->elemsize, cas->sg.elem, sg->elem);
	gp = sg->g;
	gp->param = sg;
	runtime·ready(gp);
	goto retc;

rclose:
	// read at end of closed channel
	selunlock(sel);
	if(cas->receivedp != nil)
		*cas->receivedp = false;
	if(cas->sg.elem != nil)
		c->elemalg->copy(c->elemsize, cas->sg.elem, nil);
	goto retc;

syncsend:
	// can send to sleeping receiver (sg)
	selunlock(sel);
	if(debug)
		runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
	if(sg->elem != nil)
		c->elemalg->copy(c->elemsize, sg->elem, cas->sg.elem);
	gp = sg->g;
	gp->param = sg;
	runtime·ready(gp);

retc:
	// return to pc corresponding to chosen case
	pc = cas->pc;
	as = (byte*)selp + cas->so;
	runtime·free(sel);
	*as = true;
	return pc;

sclose:
	// send on closed channel
	selunlock(sel);
	runtime·panicstring("send on closed channel");
	return nil;  // not reached
}