Blame


1 1a8f27c3 2004-05-14 devnull /*
2 1a8f27c3 2004-05-14 devnull NAME
3 1a8f27c3 2004-05-14 devnull rendezvous - user level process synchronization
4 1a8f27c3 2004-05-14 devnull
5 1a8f27c3 2004-05-14 devnull SYNOPSIS
6 1a8f27c3 2004-05-14 devnull ulong rendezvous(ulong tag, ulong value)
7 1a8f27c3 2004-05-14 devnull
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.
13 1a8f27c3 2004-05-14 devnull
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.
22 1a8f27c3 2004-05-14 devnull
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
26 1a8f27c3 2004-05-14 devnull fork(2).
27 1a8f27c3 2004-05-14 devnull
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.
30 1a8f27c3 2004-05-14 devnull
31 1a8f27c3 2004-05-14 devnull * This simulates rendezvous with shared memory, pause, and SIGUSR1.
32 1a8f27c3 2004-05-14 devnull */
33 1a8f27c3 2004-05-14 devnull
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>
42 1a8f27c3 2004-05-14 devnull
43 1a8f27c3 2004-05-14 devnull enum
44 1a8f27c3 2004-05-14 devnull {
45 1a8f27c3 2004-05-14 devnull VOUSHASH = 257,
46 1a8f27c3 2004-05-14 devnull };
47 1a8f27c3 2004-05-14 devnull
48 1a8f27c3 2004-05-14 devnull typedef struct Vous Vous;
49 1a8f27c3 2004-05-14 devnull struct Vous
50 1a8f27c3 2004-05-14 devnull {
51 1a8f27c3 2004-05-14 devnull Vous *link;
52 1a8f27c3 2004-05-14 devnull Lock lk;
53 1a8f27c3 2004-05-14 devnull int pid;
54 1a8f27c3 2004-05-14 devnull ulong val;
55 1a8f27c3 2004-05-14 devnull ulong tag;
56 1a8f27c3 2004-05-14 devnull };
57 1a8f27c3 2004-05-14 devnull
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;
63 1a8f27c3 2004-05-14 devnull
64 1a8f27c3 2004-05-14 devnull static Vous*
65 1a8f27c3 2004-05-14 devnull getvous(void)
66 1a8f27c3 2004-05-14 devnull {
67 1a8f27c3 2004-05-14 devnull Vous *v;
68 1a8f27c3 2004-05-14 devnull
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++];
74 1a8f27c3 2004-05-14 devnull else
75 1a8f27c3 2004-05-14 devnull abort();
76 1a8f27c3 2004-05-14 devnull return v;
77 1a8f27c3 2004-05-14 devnull }
78 1a8f27c3 2004-05-14 devnull
79 1a8f27c3 2004-05-14 devnull static void
80 1a8f27c3 2004-05-14 devnull putvous(Vous *v)
81 1a8f27c3 2004-05-14 devnull {
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);
86 1a8f27c3 2004-05-14 devnull }
87 1a8f27c3 2004-05-14 devnull
88 1a8f27c3 2004-05-14 devnull static Vous*
89 1a8f27c3 2004-05-14 devnull findvous(ulong tag, ulong val, int pid)
90 1a8f27c3 2004-05-14 devnull {
91 1a8f27c3 2004-05-14 devnull int h;
92 1a8f27c3 2004-05-14 devnull Vous *v, **l;
93 1a8f27c3 2004-05-14 devnull
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;
101 1a8f27c3 2004-05-14 devnull }
102 1a8f27c3 2004-05-14 devnull }
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;
112 1a8f27c3 2004-05-14 devnull }
113 1a8f27c3 2004-05-14 devnull
114 1a8f27c3 2004-05-14 devnull #define DBG 0
115 1a8f27c3 2004-05-14 devnull ulong
116 1a8f27c3 2004-05-14 devnull rendezvous(ulong tag, ulong val)
117 1a8f27c3 2004-05-14 devnull {
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;
121 1a8f27c3 2004-05-14 devnull
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);
126 1a8f27c3 2004-05-14 devnull /*
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.
130 1a8f27c3 2004-05-14 devnull *
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.
135 1a8f27c3 2004-05-14 devnull *
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.
138 1a8f27c3 2004-05-14 devnull */
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)
142 1a8f27c3 2004-05-14 devnull ;
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);
146 1a8f27c3 2004-05-14 devnull }else{
147 1a8f27c3 2004-05-14 devnull /*
148 1a8f27c3 2004-05-14 devnull * Found someone to meet. Wake him:
149 1a8f27c3 2004-05-14 devnull *
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
152 1a8f27c3 2004-05-14 devnull *
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).
156 1a8f27c3 2004-05-14 devnull */
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);
164 1a8f27c3 2004-05-14 devnull }
165 1a8f27c3 2004-05-14 devnull return rval;
166 1a8f27c3 2004-05-14 devnull }
167 1a8f27c3 2004-05-14 devnull