summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/chan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/chan.c')
-rw-r--r--src/pkg/runtime/chan.c129
1 files changed, 59 insertions, 70 deletions
diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c
index 65feacb78..ef5342353 100644
--- a/src/pkg/runtime/chan.c
+++ b/src/pkg/runtime/chan.c
@@ -81,10 +81,13 @@ static void enqueue(WaitQ*, SudoG*);
static void destroychan(Hchan*);
Hchan*
-runtime·makechan_c(Type *elem, int64 hint)
+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");
@@ -121,7 +124,7 @@ runtime·makechan_c(Type *elem, int64 hint)
void
reflect·makechan(ChanType *t, uint32 size, Hchan *c)
{
- c = runtime·makechan_c(t->elem, size);
+ c = runtime·makechan_c(t, size);
FLUSH(&c);
}
@@ -132,11 +135,11 @@ destroychan(Hchan *c)
}
-// makechan(elem *Type, hint int64) (hchan *chan any);
+// makechan(t *ChanType, hint int64) (hchan *chan any);
void
-runtime·makechan(Type *elem, int64 hint, Hchan *ret)
+runtime·makechan(ChanType *t, int64 hint, Hchan *ret)
{
- ret = runtime·makechan_c(elem, hint);
+ ret = runtime·makechan_c(t, hint);
FLUSH(&ret);
}
@@ -155,14 +158,22 @@ runtime·makechan(Type *elem, int64 hint, Hchan *ret)
* the operation; we'll see that it's now closed.
*/
void
-runtime·chansend(Hchan *c, byte *ep, bool *pres)
+runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
{
SudoG *sg;
SudoG mysg;
G* gp;
- if(c == nil)
- runtime·panicstring("send to nil channel");
+ if(c == nil) {
+ USED(t);
+ if(pres != nil) {
+ *pres = false;
+ return;
+ }
+ g->status = Gwaiting;
+ runtime·gosched();
+ return; // not reached
+ }
if(runtime·gcwaiting)
runtime·gosched();
@@ -263,21 +274,29 @@ closed:
void
-runtime·chanrecv(Hchan* c, byte *ep, bool *selected, bool *received)
+runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received)
{
SudoG *sg;
SudoG mysg;
G *gp;
- if(c == nil)
- runtime·panicstring("receive from nil channel");
-
if(runtime·gcwaiting)
runtime·gosched();
if(debug)
runtime·printf("chanrecv: chan=%p\n", c);
+ if(c == nil) {
+ USED(t);
+ if(selected != nil) {
+ *selected = false;
+ return;
+ }
+ g->status = Gwaiting;
+ runtime·gosched();
+ return; // not reached
+ }
+
runtime·lock(c);
if(c->dataqsiz > 0)
goto asynch;
@@ -385,50 +404,29 @@ closed:
// chansend1(hchan *chan any, elem any);
#pragma textflag 7
void
-runtime·chansend1(Hchan* c, ...)
+runtime·chansend1(ChanType *t, Hchan* c, ...)
{
- int32 o;
- byte *ae;
-
- if(c == nil)
- runtime·panicstring("send to nil channel");
-
- o = runtime·rnd(sizeof(c), c->elemalign);
- ae = (byte*)&c + o;
- runtime·chansend(c, ae, nil);
+ runtime·chansend(t, c, (byte*)(&c+1), nil);
}
// chanrecv1(hchan *chan any) (elem any);
#pragma textflag 7
void
-runtime·chanrecv1(Hchan* c, ...)
+runtime·chanrecv1(ChanType *t, Hchan* c, ...)
{
- int32 o;
- byte *ae;
-
- o = runtime·rnd(sizeof(c), Structrnd);
- ae = (byte*)&c + o;
-
- runtime·chanrecv(c, ae, nil, nil);
+ runtime·chanrecv(t, c, (byte*)(&c+1), nil, nil);
}
// chanrecv2(hchan *chan any) (elem any, received bool);
#pragma textflag 7
void
-runtime·chanrecv2(Hchan* c, ...)
+runtime·chanrecv2(ChanType *t, Hchan* c, ...)
{
- int32 o;
- byte *ae, *ac;
-
- if(c == nil)
- runtime·panicstring("receive from nil channel");
-
- o = runtime·rnd(sizeof(c), Structrnd);
- ae = (byte*)&c + o;
- o += c->elemsize;
- ac = (byte*)&c + o;
+ byte *ae, *ap;
- runtime·chanrecv(c, ae, nil, ac);
+ ae = (byte*)(&c+1);
+ ap = ae + t->elem->size;
+ runtime·chanrecv(t, c, ae, nil, ap);
}
// func selectnbsend(c chan any, elem any) bool
@@ -444,7 +442,7 @@ runtime·chanrecv2(Hchan* c, ...)
//
// as
//
-// if c != nil && selectnbsend(c, v) {
+// if selectnbsend(c, v) {
// ... foo
// } else {
// ... bar
@@ -452,17 +450,13 @@ runtime·chanrecv2(Hchan* c, ...)
//
#pragma textflag 7
void
-runtime·selectnbsend(Hchan *c, ...)
+runtime·selectnbsend(ChanType *t, Hchan *c, ...)
{
- int32 o;
byte *ae, *ap;
- o = runtime·rnd(sizeof(c), c->elemalign);
- ae = (byte*)&c + o;
- o = runtime·rnd(o+c->elemsize, Structrnd);
- ap = (byte*)&c + o;
-
- runtime·chansend(c, ae, ap);
+ ae = (byte*)(&c + 1);
+ ap = ae + runtime·rnd(t->elem->size, Structrnd);
+ runtime·chansend(t, c, ae, ap);
}
// func selectnbrecv(elem *any, c chan any) bool
@@ -478,7 +472,7 @@ runtime·selectnbsend(Hchan *c, ...)
//
// as
//
-// if c != nil && selectnbrecv(&v, c) {
+// if selectnbrecv(&v, c) {
// ... foo
// } else {
// ... bar
@@ -486,9 +480,9 @@ runtime·selectnbsend(Hchan *c, ...)
//
#pragma textflag 7
void
-runtime·selectnbrecv(byte *v, Hchan *c, bool selected)
+runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
{
- runtime·chanrecv(c, v, &selected, nil);
+ runtime·chanrecv(t, c, v, &selected, nil);
}
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
@@ -512,9 +506,9 @@ runtime·selectnbrecv(byte *v, Hchan *c, bool selected)
//
#pragma textflag 7
void
-runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected)
+runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
{
- runtime·chanrecv(c, v, &selected, received);
+ runtime·chanrecv(t, c, v, &selected, received);
}
// For reflect:
@@ -525,14 +519,11 @@ runtime·selectnbrecv2(byte *v, bool *received, Hchan *c, bool selected)
// The "uintptr selected" is really "bool selected" but saying
// uintptr gets us the right alignment for the output parameter block.
void
-reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
+reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
{
bool *sp;
byte *vp;
- if(c == nil)
- runtime·panicstring("send to nil channel");
-
if(nb) {
selected = false;
sp = (bool*)&selected;
@@ -541,11 +532,11 @@ reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
FLUSH(&selected);
sp = nil;
}
- if(c->elemsize <= sizeof(val))
+ if(t->elem->size <= sizeof(val))
vp = (byte*)&val;
else
vp = (byte*)val;
- runtime·chansend(c, vp, sp);
+ runtime·chansend(t, c, vp, sp);
}
// For reflect:
@@ -553,13 +544,10 @@ reflect·chansend(Hchan *c, uintptr val, bool nb, uintptr selected)
// where an iword is the same word an interface value would use:
// the actual data if it fits, or else a pointer to the data.
void
-reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received)
+reflect·chanrecv(ChanType *t, Hchan *c, bool nb, uintptr val, bool selected, bool received)
{
byte *vp;
bool *sp;
-
- if(c == nil)
- runtime·panicstring("receive from nil channel");
if(nb) {
selected = false;
@@ -571,15 +559,15 @@ reflect·chanrecv(Hchan *c, bool nb, uintptr val, bool selected, bool received)
}
received = false;
FLUSH(&received);
- if(c->elemsize <= sizeof(val)) {
+ if(t->elem->size <= sizeof(val)) {
val = 0;
vp = (byte*)&val;
} else {
- vp = runtime·mal(c->elemsize);
+ vp = runtime·mal(t->elem->size);
val = (uintptr)vp;
FLUSH(&val);
}
- runtime·chanrecv(c, vp, sp, &received);
+ runtime·chanrecv(t, c, vp, sp, &received);
}
static void newselect(int32, Select**);
@@ -904,7 +892,8 @@ loop:
// pass 2 - enqueue on all chans
for(i=0; i<sel->ncase; i++) {
- cas = &sel->scase[i];
+ o = sel->pollorder[i];
+ cas = &sel->scase[o];
c = cas->chan;
sg = &cas->sg;
sg->g = g;