Blame


1 a46395ec 2003-10-01 devnull /*
2 a46395ec 2003-10-01 devnull NAME
3 a46395ec 2003-10-01 devnull rendezvous - user level process synchronization
4 a46395ec 2003-10-01 devnull
5 a46395ec 2003-10-01 devnull SYNOPSIS
6 a46395ec 2003-10-01 devnull ulong rendezvous(ulong tag, ulong value)
7 a46395ec 2003-10-01 devnull
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.
13 a46395ec 2003-10-01 devnull
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.
22 a46395ec 2003-10-01 devnull
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
26 a46395ec 2003-10-01 devnull fork(2).
27 a46395ec 2003-10-01 devnull
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.
30 a46395ec 2003-10-01 devnull
31 a46395ec 2003-10-01 devnull * This simulates rendezvous with shared memory, pause, and SIGUSR1.
32 a46395ec 2003-10-01 devnull */
33 a46395ec 2003-10-01 devnull
34 a46395ec 2003-10-01 devnull #include <signal.h>
35 a46395ec 2003-10-01 devnull #include <lib9.h>
36 a46395ec 2003-10-01 devnull
37 a46395ec 2003-10-01 devnull enum
38 a46395ec 2003-10-01 devnull {
39 a46395ec 2003-10-01 devnull VOUSHASH = 257,
40 a46395ec 2003-10-01 devnull };
41 a46395ec 2003-10-01 devnull
42 a46395ec 2003-10-01 devnull typedef struct Vous Vous;
43 a46395ec 2003-10-01 devnull struct Vous
44 a46395ec 2003-10-01 devnull {
45 a46395ec 2003-10-01 devnull Vous *link;
46 a46395ec 2003-10-01 devnull Lock lk;
47 a46395ec 2003-10-01 devnull int pid;
48 a46395ec 2003-10-01 devnull ulong val;
49 a46395ec 2003-10-01 devnull ulong tag;
50 a46395ec 2003-10-01 devnull };
51 a46395ec 2003-10-01 devnull
52 a46395ec 2003-10-01 devnull static void
53 a46395ec 2003-10-01 devnull ign(int x)
54 a46395ec 2003-10-01 devnull {
55 a46395ec 2003-10-01 devnull USED(x);
56 a46395ec 2003-10-01 devnull }
57 a46395ec 2003-10-01 devnull
58 a46395ec 2003-10-01 devnull void /*__attribute__((constructor))*/
59 a46395ec 2003-10-01 devnull ignusr1(void)
60 a46395ec 2003-10-01 devnull {
61 a46395ec 2003-10-01 devnull signal(SIGUSR1, ign);
62 a46395ec 2003-10-01 devnull }
63 a46395ec 2003-10-01 devnull
64 a46395ec 2003-10-01 devnull static Vous vouspool[2048];
65 a46395ec 2003-10-01 devnull static int nvousused;
66 a46395ec 2003-10-01 devnull static Vous *vousfree;
67 a46395ec 2003-10-01 devnull static Vous *voushash[VOUSHASH];
68 a46395ec 2003-10-01 devnull static Lock vouslock;
69 a46395ec 2003-10-01 devnull
70 a46395ec 2003-10-01 devnull static Vous*
71 a46395ec 2003-10-01 devnull getvous(void)
72 a46395ec 2003-10-01 devnull {
73 a46395ec 2003-10-01 devnull Vous *v;
74 a46395ec 2003-10-01 devnull
75 a46395ec 2003-10-01 devnull if(vousfree){
76 a46395ec 2003-10-01 devnull v = vousfree;
77 a46395ec 2003-10-01 devnull vousfree = v->link;
78 a46395ec 2003-10-01 devnull }else if(nvousused < nelem(vouspool))
79 a46395ec 2003-10-01 devnull v = &vouspool[nvousused++];
80 a46395ec 2003-10-01 devnull else
81 a46395ec 2003-10-01 devnull abort();
82 a46395ec 2003-10-01 devnull return v;
83 a46395ec 2003-10-01 devnull }
84 a46395ec 2003-10-01 devnull
85 a46395ec 2003-10-01 devnull static void
86 a46395ec 2003-10-01 devnull putvous(Vous *v)
87 a46395ec 2003-10-01 devnull {
88 a46395ec 2003-10-01 devnull lock(&vouslock);
89 a46395ec 2003-10-01 devnull v->link = vousfree;
90 a46395ec 2003-10-01 devnull vousfree = v;
91 a46395ec 2003-10-01 devnull unlock(&vouslock);
92 a46395ec 2003-10-01 devnull }
93 a46395ec 2003-10-01 devnull
94 a46395ec 2003-10-01 devnull static Vous*
95 a46395ec 2003-10-01 devnull findvous(ulong tag, ulong val, int pid)
96 a46395ec 2003-10-01 devnull {
97 a46395ec 2003-10-01 devnull int h;
98 a46395ec 2003-10-01 devnull Vous *v, **l;
99 a46395ec 2003-10-01 devnull
100 a46395ec 2003-10-01 devnull lock(&vouslock);
101 a46395ec 2003-10-01 devnull h = tag%VOUSHASH;
102 a46395ec 2003-10-01 devnull for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
103 a46395ec 2003-10-01 devnull if(v->tag == tag){
104 a46395ec 2003-10-01 devnull *l = v->link;
105 a46395ec 2003-10-01 devnull unlock(&vouslock);
106 a46395ec 2003-10-01 devnull return v;
107 a46395ec 2003-10-01 devnull }
108 a46395ec 2003-10-01 devnull }
109 a46395ec 2003-10-01 devnull v = getvous();
110 a46395ec 2003-10-01 devnull v->pid = pid;
111 a46395ec 2003-10-01 devnull v->link = voushash[h];
112 a46395ec 2003-10-01 devnull v->val = val;
113 a46395ec 2003-10-01 devnull v->tag = tag;
114 a46395ec 2003-10-01 devnull lock(&v->lk);
115 a46395ec 2003-10-01 devnull voushash[h] = v;
116 a46395ec 2003-10-01 devnull unlock(&vouslock);
117 a46395ec 2003-10-01 devnull return v;
118 a46395ec 2003-10-01 devnull }
119 a46395ec 2003-10-01 devnull
120 a46395ec 2003-10-01 devnull #define DBG 0
121 a46395ec 2003-10-01 devnull ulong
122 a46395ec 2003-10-01 devnull rendezvous(ulong tag, ulong val)
123 a46395ec 2003-10-01 devnull {
124 a46395ec 2003-10-01 devnull int me, vpid;
125 a46395ec 2003-10-01 devnull ulong rval;
126 a46395ec 2003-10-01 devnull Vous *v;
127 a46395ec 2003-10-01 devnull sigset_t mask;
128 a46395ec 2003-10-01 devnull
129 a46395ec 2003-10-01 devnull me = getpid();
130 a46395ec 2003-10-01 devnull v = findvous(tag, val, me);
131 a46395ec 2003-10-01 devnull if(v->pid == me){
132 a46395ec 2003-10-01 devnull if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
133 a46395ec 2003-10-01 devnull /*
134 a46395ec 2003-10-01 devnull * No rendezvous partner was found; the next guy
135 a46395ec 2003-10-01 devnull * through will find v and wake us, so we must go
136 a46395ec 2003-10-01 devnull * to sleep.
137 a46395ec 2003-10-01 devnull *
138 a46395ec 2003-10-01 devnull * To go to sleep:
139 a46395ec 2003-10-01 devnull * 1. disable USR1 signals.
140 a46395ec 2003-10-01 devnull * 2. unlock v->lk (tells waker okay to signal us).
141 a46395ec 2003-10-01 devnull * 3. atomically suspend and enable USR1 signals.
142 a46395ec 2003-10-01 devnull *
143 a46395ec 2003-10-01 devnull * The call to ignusr1() could be done once at
144 a46395ec 2003-10-01 devnull * process creation instead of every time through rendezvous.
145 a46395ec 2003-10-01 devnull */
146 a46395ec 2003-10-01 devnull v->val = val;
147 a46395ec 2003-10-01 devnull ignusr1();
148 a46395ec 2003-10-01 devnull sigprocmask(SIG_SETMASK, NULL, &mask);
149 a46395ec 2003-10-01 devnull sigaddset(&mask, SIGUSR1);
150 a46395ec 2003-10-01 devnull sigprocmask(SIG_SETMASK, &mask, NULL);
151 a46395ec 2003-10-01 devnull sigdelset(&mask, SIGUSR1);
152 a46395ec 2003-10-01 devnull unlock(&v->lk);
153 a46395ec 2003-10-01 devnull sigsuspend(&mask);
154 a46395ec 2003-10-01 devnull rval = v->val;
155 a46395ec 2003-10-01 devnull if(DBG)fprint(2, "pid is %d, awake\n", me);
156 a46395ec 2003-10-01 devnull putvous(v);
157 a46395ec 2003-10-01 devnull }else{
158 a46395ec 2003-10-01 devnull /*
159 a46395ec 2003-10-01 devnull * Found someone to meet. Wake him:
160 a46395ec 2003-10-01 devnull *
161 a46395ec 2003-10-01 devnull * A. lock v->lk (waits for him to get to his step 2)
162 a46395ec 2003-10-01 devnull * B. send a USR1
163 a46395ec 2003-10-01 devnull *
164 a46395ec 2003-10-01 devnull * He won't get the USR1 until he suspends, which
165 a46395ec 2003-10-01 devnull * means it must wake him up (it can't get delivered
166 a46395ec 2003-10-01 devnull * before he sleeps).
167 a46395ec 2003-10-01 devnull */
168 a46395ec 2003-10-01 devnull vpid = v->pid;
169 a46395ec 2003-10-01 devnull lock(&v->lk);
170 a46395ec 2003-10-01 devnull rval = v->val;
171 a46395ec 2003-10-01 devnull v->val = val;
172 a46395ec 2003-10-01 devnull unlock(&v->lk);
173 a46395ec 2003-10-01 devnull if(kill(vpid, SIGUSR1) < 0){
174 a46395ec 2003-10-01 devnull if(DBG)fprint(2, "pid is %d, kill %d failed: %r\n", me, vpid);
175 a46395ec 2003-10-01 devnull abort();
176 a46395ec 2003-10-01 devnull }
177 a46395ec 2003-10-01 devnull }
178 a46395ec 2003-10-01 devnull return rval;
179 a46395ec 2003-10-01 devnull }
180 a46395ec 2003-10-01 devnull