1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 #include "threadimpl.h" 5 6 Rgrp _threadrgrp; 7 static int isdirty; 8 9 static void* 10 finish(Thread *t, void *val) 11 { 12 void *ret; 13 14 ret = t->rendval; 15 t->rendval = val; 16 while(t->state == Running) 17 sleep(0); 18 lock(&t->proc->lock); 19 if(t->state == Rendezvous){ /* not always true: might be Dead */ 20 t->state = Ready; 21 _threadready(t); 22 } 23 unlock(&t->proc->lock); 24 return ret; 25 } 26 27 void* 28 _threadrendezvous(void *tag, void *val) 29 { 30 void *ret; 31 Thread *t, **l; 32 33 lock(&_threadrgrp.lock); 34 l = &_threadrgrp.hash[((uintptr)tag)%nelem(_threadrgrp.hash)]; 35 for(t=*l; t; l=&t->rendhash, t=*l){ 36 if(t->rendtag==tag){ 37 _threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id); 38 *l = t->rendhash; 39 ret = finish(t, val); 40 unlock(&_threadrgrp.lock); 41 return ret; 42 } 43 } 44 45 /* Going to sleep here. */ 46 t = _threadgetproc()->thread; 47 t->rendbreak = 0; 48 t->inrendez = 1; 49 t->rendtag = tag; 50 t->rendval = val; 51 t->rendhash = *l; 52 *l = t; 53 t->nextstate = Rendezvous; 54 _threaddebug(DBGREND, "Rendezvous for tag %p", t->rendtag); 55 unlock(&_threadrgrp.lock); 56 _sched(); 57 t->inrendez = 0; 58 _threaddebug(DBGREND, "Woke after rendezvous; val is %p", t->rendval); 59 return t->rendval; 60 } 61 62 /* 63 * This is called while holding _threadpq.lock and p->lock, 64 * so we can't lock _threadrgrp.lock. Instead our caller has 65 * to call _threadbreakrendez after dropping those locks. 66 */ 67 void 68 _threadflagrendez(Thread *t) 69 { 70 t->rendbreak = 1; 71 isdirty = 1; 72 } 73 74 void 75 _threadbreakrendez(void) 76 { 77 int i; 78 Thread *t, **l; 79 80 if(isdirty == 0) 81 return; 82 lock(&_threadrgrp.lock); 83 if(isdirty == 0){ 84 unlock(&_threadrgrp.lock); 85 return; 86 } 87 isdirty = 0; 88 for(i=0; i<nelem(_threadrgrp.hash); i++){ 89 l = &_threadrgrp.hash[i]; 90 for(t=*l; t; t=*l){ 91 if(t->rendbreak){ 92 *l = t->rendhash; 93 finish(t, (void*)~0); 94 }else 95 l=&t->rendhash; 96 } 97 } 98 unlock(&_threadrgrp.lock); 99 } 100