3 1a8f27c3 2004-05-14 devnull rendezvous - user level process synchronization
6 1a8f27c3 2004-05-14 devnull ulong rendezvous(ulong tag, ulong value)
8 1a8f27c3 2004-05-14 devnull DESCRIPTION
9 1a8f27c3 2004-05-14 devnull The rendezvous system call allows two processes to synchro-
10 1a8f27c3 2004-05-14 devnull nize and exchange a value. In conjunction with the shared
11 1a8f27c3 2004-05-14 devnull memory system calls (see segattach(2) and fork(2)), it
12 1a8f27c3 2004-05-14 devnull enables parallel programs to control their scheduling.
14 1a8f27c3 2004-05-14 devnull Two processes wishing to synchronize call rendezvous with a
15 1a8f27c3 2004-05-14 devnull common tag, typically an address in memory they share. One
16 1a8f27c3 2004-05-14 devnull process will arrive at the rendezvous first; it suspends
17 1a8f27c3 2004-05-14 devnull execution until a second arrives. When a second process
18 1a8f27c3 2004-05-14 devnull meets the rendezvous the value arguments are exchanged
19 1a8f27c3 2004-05-14 devnull between the processes and returned as the result of the
20 1a8f27c3 2004-05-14 devnull respective rendezvous system calls. Both processes are
21 1a8f27c3 2004-05-14 devnull awakened when the rendezvous succeeds.
23 1a8f27c3 2004-05-14 devnull The set of tag values which two processes may use to
24 1a8f27c3 2004-05-14 devnull rendezvous-their tag space-is inherited when a process
25 1a8f27c3 2004-05-14 devnull forks, unless RFREND is set in the argument to rfork; see
28 1a8f27c3 2004-05-14 devnull If a rendezvous is interrupted the return value is ~0, so
29 1a8f27c3 2004-05-14 devnull that value should not be used in normal communication.
31 1a8f27c3 2004-05-14 devnull * This simulates rendezvous with shared memory, pause, and SIGUSR1.
34 1a8f27c3 2004-05-14 devnull #include <u.h>
35 1a8f27c3 2004-05-14 devnull typedef u32int u32;
36 1a8f27c3 2004-05-14 devnull #include <errno.h>
37 1a8f27c3 2004-05-14 devnull #include <sys/time.h>
38 1a8f27c3 2004-05-14 devnull #define __user
39 1a8f27c3 2004-05-14 devnull #include <linux/linkage.h>
40 1a8f27c3 2004-05-14 devnull #include <linux/futex.h>
41 1a8f27c3 2004-05-14 devnull #include <libc.h>
45 1a8f27c3 2004-05-14 devnull VOUSHASH = 257,
48 1a8f27c3 2004-05-14 devnull typedef struct Vous Vous;
49 1a8f27c3 2004-05-14 devnull struct Vous
51 1a8f27c3 2004-05-14 devnull Vous *link;
54 1a8f27c3 2004-05-14 devnull ulong val;
55 1a8f27c3 2004-05-14 devnull ulong tag;
58 1a8f27c3 2004-05-14 devnull static Vous vouspool[2048];
59 1a8f27c3 2004-05-14 devnull static int nvousused;
60 1a8f27c3 2004-05-14 devnull static Vous *vousfree;
61 1a8f27c3 2004-05-14 devnull static Vous *voushash[VOUSHASH];
62 1a8f27c3 2004-05-14 devnull static Lock vouslock;
64 1a8f27c3 2004-05-14 devnull static Vous*
65 1a8f27c3 2004-05-14 devnull getvous(void)
69 1a8f27c3 2004-05-14 devnull if(vousfree){
70 1a8f27c3 2004-05-14 devnull v = vousfree;
71 1a8f27c3 2004-05-14 devnull vousfree = v->link;
72 1a8f27c3 2004-05-14 devnull }else if(nvousused < nelem(vouspool))
73 1a8f27c3 2004-05-14 devnull v = &vouspool[nvousused++];
76 1a8f27c3 2004-05-14 devnull return v;
79 1a8f27c3 2004-05-14 devnull static void
80 1a8f27c3 2004-05-14 devnull putvous(Vous *v)
82 1a8f27c3 2004-05-14 devnull lock(&vouslock);
83 1a8f27c3 2004-05-14 devnull v->link = vousfree;
84 1a8f27c3 2004-05-14 devnull vousfree = v;
85 1a8f27c3 2004-05-14 devnull unlock(&vouslock);
88 1a8f27c3 2004-05-14 devnull static Vous*
89 1a8f27c3 2004-05-14 devnull findvous(ulong tag, ulong val, int pid)
92 1a8f27c3 2004-05-14 devnull Vous *v, **l;
94 1a8f27c3 2004-05-14 devnull lock(&vouslock);
95 1a8f27c3 2004-05-14 devnull h = tag%VOUSHASH;
96 1a8f27c3 2004-05-14 devnull for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
97 1a8f27c3 2004-05-14 devnull if(v->tag == tag){
98 1a8f27c3 2004-05-14 devnull *l = v->link;
99 1a8f27c3 2004-05-14 devnull unlock(&vouslock);
100 1a8f27c3 2004-05-14 devnull return v;
103 1a8f27c3 2004-05-14 devnull v = getvous();
104 1a8f27c3 2004-05-14 devnull v->pid = pid;
105 1a8f27c3 2004-05-14 devnull v->link = voushash[h];
106 1a8f27c3 2004-05-14 devnull v->val = val;
107 1a8f27c3 2004-05-14 devnull v->tag = tag;
108 1a8f27c3 2004-05-14 devnull lock(&v->lk);
109 1a8f27c3 2004-05-14 devnull voushash[h] = v;
110 1a8f27c3 2004-05-14 devnull unlock(&vouslock);
111 1a8f27c3 2004-05-14 devnull return v;
114 1a8f27c3 2004-05-14 devnull #define DBG 0
116 1a8f27c3 2004-05-14 devnull rendezvous(ulong tag, ulong val)
118 1a8f27c3 2004-05-14 devnull int me, vpid;
119 1a8f27c3 2004-05-14 devnull ulong rval;
120 1a8f27c3 2004-05-14 devnull Vous *v;
122 1a8f27c3 2004-05-14 devnull me = getpid();
123 1a8f27c3 2004-05-14 devnull v = findvous(tag, val, me);
124 1a8f27c3 2004-05-14 devnull if(v->pid == me){
125 1a8f27c3 2004-05-14 devnull if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
127 1a8f27c3 2004-05-14 devnull * No rendezvous partner was found; the next guy
128 1a8f27c3 2004-05-14 devnull * through will find v and wake us, so we must go
129 1a8f27c3 2004-05-14 devnull * to sleep.
131 1a8f27c3 2004-05-14 devnull * To go to sleep:
132 1a8f27c3 2004-05-14 devnull * 1. disable USR1 signals.
133 1a8f27c3 2004-05-14 devnull * 2. unlock v->lk (tells waker okay to signal us).
134 1a8f27c3 2004-05-14 devnull * 3. atomically suspend and enable USR1 signals.
136 1a8f27c3 2004-05-14 devnull * The call to ignusr1() could be done once at
137 1a8f27c3 2004-05-14 devnull * process creation instead of every time through rendezvous.
139 1a8f27c3 2004-05-14 devnull v->val = val;
140 1a8f27c3 2004-05-14 devnull unlock(&v->lk);
141 1a8f27c3 2004-05-14 devnull while(sys_futex((u32int*)&v->tag, FUTEX_WAIT, tag, nil, nil) < 0 && errno==EINTR)
143 1a8f27c3 2004-05-14 devnull rval = v->val;
144 1a8f27c3 2004-05-14 devnull if(DBG)fprint(2, "pid is %d, awake\n", me);
145 1a8f27c3 2004-05-14 devnull putvous(v);
148 1a8f27c3 2004-05-14 devnull * Found someone to meet. Wake him:
150 1a8f27c3 2004-05-14 devnull * A. lock v->lk (waits for him to get to his step 2)
151 1a8f27c3 2004-05-14 devnull * B. send a USR1
153 1a8f27c3 2004-05-14 devnull * He won't get the USR1 until he suspends, which
154 1a8f27c3 2004-05-14 devnull * means it must wake him up (it can't get delivered
155 1a8f27c3 2004-05-14 devnull * before he sleeps).
157 1a8f27c3 2004-05-14 devnull vpid = v->pid;
158 1a8f27c3 2004-05-14 devnull lock(&v->lk);
159 1a8f27c3 2004-05-14 devnull rval = v->val;
160 1a8f27c3 2004-05-14 devnull v->val = val;
161 1a8f27c3 2004-05-14 devnull v->tag++;
162 1a8f27c3 2004-05-14 devnull unlock(&v->lk);
163 1a8f27c3 2004-05-14 devnull sys_futex((u32int*)&v->tag, FUTEX_WAKE, 1, nil, nil);
165 1a8f27c3 2004-05-14 devnull return rval;