From e5888a1ffdae813d7575f5fb02275c6bb07e5199 Mon Sep 17 00:00:00 2001 From: Taru Karttunen Date: Wed, 30 Mar 2011 15:46:40 +0300 Subject: Import sources from 2011-03-30 iso image --- sys/src/libthread/rendez.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100755 sys/src/libthread/rendez.c (limited to 'sys/src/libthread/rendez.c') diff --git a/sys/src/libthread/rendez.c b/sys/src/libthread/rendez.c new file mode 100755 index 000000000..8a6d0f8a6 --- /dev/null +++ b/sys/src/libthread/rendez.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include "threadimpl.h" + +Rgrp _threadrgrp; +static int isdirty; + +static void* +finish(Thread *t, void *val) +{ + void *ret; + + ret = t->rendval; + t->rendval = val; + while(t->state == Running) + sleep(0); + lock(&t->proc->lock); + if(t->state == Rendezvous){ /* not always true: might be Dead */ + t->state = Ready; + _threadready(t); + } + unlock(&t->proc->lock); + return ret; +} + +void* +_threadrendezvous(void *tag, void *val) +{ + void *ret; + Thread *t, **l; + + lock(&_threadrgrp.lock); + l = &_threadrgrp.hash[((uintptr)tag)%nelem(_threadrgrp.hash)]; + for(t=*l; t; l=&t->rendhash, t=*l){ + if(t->rendtag==tag){ + _threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id); + *l = t->rendhash; + ret = finish(t, val); + unlock(&_threadrgrp.lock); + return ret; + } + } + + /* Going to sleep here. */ + t = _threadgetproc()->thread; + t->rendbreak = 0; + t->inrendez = 1; + t->rendtag = tag; + t->rendval = val; + t->rendhash = *l; + *l = t; + t->nextstate = Rendezvous; + _threaddebug(DBGREND, "Rendezvous for tag %p", t->rendtag); + unlock(&_threadrgrp.lock); + _sched(); + t->inrendez = 0; + _threaddebug(DBGREND, "Woke after rendezvous; val is %p", t->rendval); + return t->rendval; +} + +/* + * This is called while holding _threadpq.lock and p->lock, + * so we can't lock _threadrgrp.lock. Instead our caller has + * to call _threadbreakrendez after dropping those locks. + */ +void +_threadflagrendez(Thread *t) +{ + t->rendbreak = 1; + isdirty = 1; +} + +void +_threadbreakrendez(void) +{ + int i; + Thread *t, **l; + + if(isdirty == 0) + return; + lock(&_threadrgrp.lock); + if(isdirty == 0){ + unlock(&_threadrgrp.lock); + return; + } + isdirty = 0; + for(i=0; irendbreak){ + *l = t->rendhash; + finish(t, (void*)~0); + }else + l=&t->rendhash; + } + } + unlock(&_threadrgrp.lock); +} -- cgit v1.2.3