3 a46395ec 2003-10-01 devnull rendezvous - user level process synchronization
6 a46395ec 2003-10-01 devnull ulong rendezvous(ulong tag, ulong value)
8 a46395ec 2003-10-01 devnull DESCRIPTION
9 a46395ec 2003-10-01 devnull The rendezvous system call allows two processes to synchro-
10 a46395ec 2003-10-01 devnull nize and exchange a value. In conjunction with the shared
11 a46395ec 2003-10-01 devnull memory system calls (see segattach(2) and fork(2)), it
12 a46395ec 2003-10-01 devnull enables parallel programs to control their scheduling.
14 a46395ec 2003-10-01 devnull Two processes wishing to synchronize call rendezvous with a
15 a46395ec 2003-10-01 devnull common tag, typically an address in memory they share. One
16 a46395ec 2003-10-01 devnull process will arrive at the rendezvous first; it suspends
17 a46395ec 2003-10-01 devnull execution until a second arrives. When a second process
18 a46395ec 2003-10-01 devnull meets the rendezvous the value arguments are exchanged
19 a46395ec 2003-10-01 devnull between the processes and returned as the result of the
20 a46395ec 2003-10-01 devnull respective rendezvous system calls. Both processes are
21 a46395ec 2003-10-01 devnull awakened when the rendezvous succeeds.
23 a46395ec 2003-10-01 devnull The set of tag values which two processes may use to
24 a46395ec 2003-10-01 devnull rendezvous-their tag space-is inherited when a process
25 a46395ec 2003-10-01 devnull forks, unless RFREND is set in the argument to rfork; see
28 a46395ec 2003-10-01 devnull If a rendezvous is interrupted the return value is ~0, so
29 a46395ec 2003-10-01 devnull that value should not be used in normal communication.
31 a46395ec 2003-10-01 devnull * This assumes we're using pthreads and simulates rendezvous using
32 a46395ec 2003-10-01 devnull * shared memory and mutexes.
35 8ad51794 2004-03-25 devnull #include <u.h>
36 a46395ec 2003-10-01 devnull #include <pthread.h>
37 fd04aace 2003-11-23 devnull #include <signal.h>
38 8ad51794 2004-03-25 devnull #include <libc.h>
42 a46395ec 2003-10-01 devnull VOUSHASH = 257,
45 a46395ec 2003-10-01 devnull typedef struct Vous Vous;
46 a46395ec 2003-10-01 devnull struct Vous
48 a46395ec 2003-10-01 devnull Vous *link;
50 a46395ec 2003-10-01 devnull ulong val;
51 a46395ec 2003-10-01 devnull ulong tag;
52 a46395ec 2003-10-01 devnull pthread_mutex_t mutex;
55 a46395ec 2003-10-01 devnull static void
56 a46395ec 2003-10-01 devnull ign(int x)
61 a46395ec 2003-10-01 devnull void /*__attribute__((constructor))*/
62 a46395ec 2003-10-01 devnull ignusr1(void)
64 a46395ec 2003-10-01 devnull signal(SIGUSR1, ign);
67 a46395ec 2003-10-01 devnull static Vous vouspool[2048];
68 a46395ec 2003-10-01 devnull static int nvousused;
69 a46395ec 2003-10-01 devnull static Vous *vousfree;
70 a46395ec 2003-10-01 devnull static Vous *voushash[VOUSHASH];
71 a46395ec 2003-10-01 devnull static Lock vouslock;
73 a46395ec 2003-10-01 devnull static Vous*
74 a46395ec 2003-10-01 devnull getvous(void)
78 a46395ec 2003-10-01 devnull if(vousfree){
79 a46395ec 2003-10-01 devnull v = vousfree;
80 a46395ec 2003-10-01 devnull vousfree = v->link;
81 a46395ec 2003-10-01 devnull }else if(nvousused < nelem(vouspool)){
82 a46395ec 2003-10-01 devnull v = &vouspool[nvousused++];
83 a46395ec 2003-10-01 devnull pthread_mutex_init(&v->mutex, NULL);
86 a46395ec 2003-10-01 devnull return v;
89 a46395ec 2003-10-01 devnull static void
90 a46395ec 2003-10-01 devnull putvous(Vous *v)
92 a46395ec 2003-10-01 devnull lock(&vouslock);
93 a46395ec 2003-10-01 devnull v->link = vousfree;
94 a46395ec 2003-10-01 devnull vousfree = v;
95 a46395ec 2003-10-01 devnull unlock(&vouslock);
98 a46395ec 2003-10-01 devnull static Vous*
99 a46395ec 2003-10-01 devnull findvous(ulong tag, ulong val, int *found)
102 a46395ec 2003-10-01 devnull Vous *v, **l;
104 a46395ec 2003-10-01 devnull lock(&vouslock);
105 a46395ec 2003-10-01 devnull h = tag%VOUSHASH;
106 a46395ec 2003-10-01 devnull for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
107 a46395ec 2003-10-01 devnull if(v->tag == tag){
108 a46395ec 2003-10-01 devnull *l = v->link;
109 a46395ec 2003-10-01 devnull *found = 1;
110 a46395ec 2003-10-01 devnull unlock(&vouslock);
111 a46395ec 2003-10-01 devnull return v;
114 a46395ec 2003-10-01 devnull v = getvous();
115 a46395ec 2003-10-01 devnull v->link = voushash[h];
116 a46395ec 2003-10-01 devnull v->val = val;
117 a46395ec 2003-10-01 devnull v->tag = tag;
118 a46395ec 2003-10-01 devnull lock(&v->lk);
119 a46395ec 2003-10-01 devnull voushash[h] = v;
120 a46395ec 2003-10-01 devnull unlock(&vouslock);
121 a46395ec 2003-10-01 devnull *found = 0;
122 a46395ec 2003-10-01 devnull return v;
125 a46395ec 2003-10-01 devnull #define DBG 0
127 a46395ec 2003-10-01 devnull rendezvous(ulong tag, ulong val)
129 a46395ec 2003-10-01 devnull int found;
130 a46395ec 2003-10-01 devnull ulong rval;
131 a46395ec 2003-10-01 devnull Vous *v;
133 a46395ec 2003-10-01 devnull v = findvous(tag, val, &found);
134 a46395ec 2003-10-01 devnull if(!found){
135 a46395ec 2003-10-01 devnull if(DBG)fprint(2, "tag %lux, sleeping on %p\n", tag, v);
137 a46395ec 2003-10-01 devnull * No rendezvous partner was found; the next guy
138 a46395ec 2003-10-01 devnull * through will find v and wake us, so we must go
139 a46395ec 2003-10-01 devnull * to sleep. Do this by locking the mutex (it is
140 a46395ec 2003-10-01 devnull * unlocked) and then locking it again (our waker will
141 a46395ec 2003-10-01 devnull * unlock it for us).
143 a46395ec 2003-10-01 devnull if(pthread_mutex_lock(&v->mutex) != 0)
144 a46395ec 2003-10-01 devnull abort();
145 a46395ec 2003-10-01 devnull unlock(&v->lk);
146 a46395ec 2003-10-01 devnull if(pthread_mutex_lock(&v->mutex) != 0)
147 a46395ec 2003-10-01 devnull abort();
148 a46395ec 2003-10-01 devnull rval = v->val;
149 a46395ec 2003-10-01 devnull pthread_mutex_unlock(&v->mutex);
150 a46395ec 2003-10-01 devnull if(DBG)fprint(2, " awake on %p\n", v);
151 a46395ec 2003-10-01 devnull unlock(&v->lk);
152 a46395ec 2003-10-01 devnull putvous(v);
155 a46395ec 2003-10-01 devnull * Found someone to meet. Wake him:
157 a46395ec 2003-10-01 devnull * A. lock v->lk (waits for him to lock the mutex once.
158 a46395ec 2003-10-01 devnull * B. unlock the mutex (wakes him up)
160 a46395ec 2003-10-01 devnull if(DBG)fprint(2, "found tag %lux on %p, waking\n", tag, v);
161 a46395ec 2003-10-01 devnull lock(&v->lk);
162 a46395ec 2003-10-01 devnull rval = v->val;
163 a46395ec 2003-10-01 devnull v->val = val;
164 a46395ec 2003-10-01 devnull if(pthread_mutex_unlock(&v->mutex) != 0)
165 a46395ec 2003-10-01 devnull abort();
166 a46395ec 2003-10-01 devnull /* lock passes to him */
168 a46395ec 2003-10-01 devnull return rval;