]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libthread/rendez.c
pc64: preserve reserved bits in CR0/CR4 for amd64 in mtrr setstate()
[plan9front.git] / sys / src / libthread / rendez.c
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 }