Blob


1 #include "threadimpl.h"
3 Rgrp _threadrgrp;
4 static int isdirty;
5 int _threadhighnrendez;
6 int _threadnrendez;
7 static int nrendez;
9 static ulong
10 finish(Thread *t, ulong val)
11 {
12 ulong ret;
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 }
27 ulong
28 _threadrendezvous(ulong tag, ulong val)
29 {
30 ulong ret;
31 Thread *t, **l;
33 lock(&_threadrgrp.lock);
34 _threadnrendez++;
35 l = &_threadrgrp.hash[tag%nelem(_threadrgrp.hash)];
36 for(t=*l; t; l=&t->rendhash, t=*l){
37 if(t->rendtag==tag){
38 _threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id);
39 *l = t->rendhash;
40 ret = finish(t, val);
41 --nrendez;
42 unlock(&_threadrgrp.lock);
43 return ret;
44 }
45 }
47 /* Going to sleep here. */
48 t = _threadgetproc()->thread;
49 t->rendbreak = 0;
50 t->inrendez = 1;
51 t->rendtag = tag;
52 t->rendval = val;
53 t->rendhash = *l;
54 *l = t;
55 t->nextstate = Rendezvous;
56 ++nrendez;
57 if(nrendez > _threadhighnrendez)
58 _threadhighnrendez = nrendez;
59 _threaddebug(DBGREND, "Rendezvous for tag %lud", t->rendtag);
60 unlock(&_threadrgrp.lock);
61 _sched();
62 t->inrendez = 0;
63 _threaddebug(DBGREND, "Woke after rendezvous; val is %lud", t->rendval);
64 return t->rendval;
65 }
67 /*
68 * This is called while holding _threadpq.lock and p->lock,
69 * so we can't lock _threadrgrp.lock. Instead our caller has
70 * to call _threadbreakrendez after dropping those locks.
71 */
72 void
73 _threadflagrendez(Thread *t)
74 {
75 t->rendbreak = 1;
76 isdirty = 1;
77 }
79 void
80 _threadbreakrendez(void)
81 {
82 int i;
83 Thread *t, **l;
85 if(isdirty == 0)
86 return;
87 lock(&_threadrgrp.lock);
88 if(isdirty == 0){
89 unlock(&_threadrgrp.lock);
90 return;
91 }
92 isdirty = 0;
93 for(i=0; i<nelem(_threadrgrp.hash); i++){
94 l = &_threadrgrp.hash[i];
95 for(t=*l; t; t=*l){
96 if(t->rendbreak){
97 *l = t->rendhash;
98 finish(t, ~0);
99 }else
100 l=&t->rendhash;
103 unlock(&_threadrgrp.lock);