123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <thread.h>
- #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; i<nelem(_threadrgrp.hash); i++){
- l = &_threadrgrp.hash[i];
- for(t=*l; t; t=*l){
- if(t->rendbreak){
- *l = t->rendhash;
- finish(t, (void*)~0);
- }else
- l=&t->rendhash;
- }
- }
- unlock(&_threadrgrp.lock);
- }
|