Blame


1 cea10000 2005-05-01 devnull #undef exits
2 cea10000 2005-05-01 devnull #undef _exits
3 cea10000 2005-05-01 devnull
4 cea10000 2005-05-01 devnull extern int __isthreaded;
5 cea10000 2005-05-01 devnull
6 cea10000 2005-05-01 devnull /*
7 cea10000 2005-05-01 devnull * spin locks
8 cea10000 2005-05-01 devnull */
9 cea10000 2005-05-01 devnull extern int _tas(int*);
10 cea10000 2005-05-01 devnull
11 cea10000 2005-05-01 devnull void
12 cea10000 2005-05-01 devnull _threadunlock(Lock *l, ulong pc)
13 cea10000 2005-05-01 devnull {
14 cea10000 2005-05-01 devnull USED(pc);
15 cea10000 2005-05-01 devnull
16 cea10000 2005-05-01 devnull l->held = 0;
17 cea10000 2005-05-01 devnull }
18 cea10000 2005-05-01 devnull
19 cea10000 2005-05-01 devnull int
20 cea10000 2005-05-01 devnull _threadlock(Lock *l, int block, ulong pc)
21 cea10000 2005-05-01 devnull {
22 cea10000 2005-05-01 devnull int i;
23 cea10000 2005-05-01 devnull
24 cea10000 2005-05-01 devnull USED(pc);
25 cea10000 2005-05-01 devnull
26 cea10000 2005-05-01 devnull /* once fast */
27 cea10000 2005-05-01 devnull if(!_tas(&l->held))
28 cea10000 2005-05-01 devnull return 1;
29 cea10000 2005-05-01 devnull if(!block)
30 cea10000 2005-05-01 devnull return 0;
31 cea10000 2005-05-01 devnull
32 cea10000 2005-05-01 devnull /* a thousand times pretty fast */
33 cea10000 2005-05-01 devnull for(i=0; i<1000; i++){
34 cea10000 2005-05-01 devnull if(!_tas(&l->held))
35 cea10000 2005-05-01 devnull return 1;
36 c54b8b69 2006-01-27 devnull sleep(0);
37 cea10000 2005-05-01 devnull }
38 cea10000 2005-05-01 devnull /* increasingly slow */
39 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
40 cea10000 2005-05-01 devnull if(!_tas(&l->held))
41 cea10000 2005-05-01 devnull return 1;
42 cea10000 2005-05-01 devnull usleep(1);
43 cea10000 2005-05-01 devnull }
44 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
45 cea10000 2005-05-01 devnull if(!_tas(&l->held))
46 cea10000 2005-05-01 devnull return 1;
47 cea10000 2005-05-01 devnull usleep(10);
48 cea10000 2005-05-01 devnull }
49 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
50 cea10000 2005-05-01 devnull if(!_tas(&l->held))
51 cea10000 2005-05-01 devnull return 1;
52 cea10000 2005-05-01 devnull usleep(100);
53 cea10000 2005-05-01 devnull }
54 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
55 cea10000 2005-05-01 devnull if(!_tas(&l->held))
56 cea10000 2005-05-01 devnull return 1;
57 cea10000 2005-05-01 devnull usleep(1000);
58 cea10000 2005-05-01 devnull }
59 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
60 cea10000 2005-05-01 devnull if(!_tas(&l->held))
61 cea10000 2005-05-01 devnull return 1;
62 cea10000 2005-05-01 devnull usleep(10*1000);
63 cea10000 2005-05-01 devnull }
64 cea10000 2005-05-01 devnull /* now nice and slow */
65 cea10000 2005-05-01 devnull for(i=0; i<1000; i++){
66 cea10000 2005-05-01 devnull if(!_tas(&l->held))
67 cea10000 2005-05-01 devnull return 1;
68 cea10000 2005-05-01 devnull usleep(100*1000);
69 cea10000 2005-05-01 devnull }
70 cea10000 2005-05-01 devnull /* take your time */
71 cea10000 2005-05-01 devnull while(_tas(&l->held))
72 cea10000 2005-05-01 devnull usleep(1000*1000);
73 cea10000 2005-05-01 devnull return 1;
74 cea10000 2005-05-01 devnull }
75 cea10000 2005-05-01 devnull
76 cea10000 2005-05-01 devnull /*
77 cea10000 2005-05-01 devnull * For libc.
78 cea10000 2005-05-01 devnull */
79 cea10000 2005-05-01 devnull
80 cea10000 2005-05-01 devnull typedef struct {
81 cea10000 2005-05-01 devnull volatile long access_lock;
82 cea10000 2005-05-01 devnull volatile long lock_owner;
83 cea10000 2005-05-01 devnull volatile char *fname;
84 cea10000 2005-05-01 devnull volatile int lineno;
85 cea10000 2005-05-01 devnull } spinlock_t;
86 cea10000 2005-05-01 devnull
87 cea10000 2005-05-01 devnull void
88 cea10000 2005-05-01 devnull _spinlock(spinlock_t *lk)
89 cea10000 2005-05-01 devnull {
90 cea10000 2005-05-01 devnull lock((Lock*)&lk->access_lock);
91 fe8c925e 2005-07-21 devnull }
92 fe8c925e 2005-07-21 devnull
93 fe8c925e 2005-07-21 devnull void
94 fe8c925e 2005-07-21 devnull _spinunlock(spinlock_t *lk)
95 fe8c925e 2005-07-21 devnull {
96 fe8c925e 2005-07-21 devnull unlock((Lock*)&lk->access_lock);
97 cea10000 2005-05-01 devnull }
98 cea10000 2005-05-01 devnull
99 fe8c925e 2005-07-21 devnull
100 fe8c925e 2005-07-21 devnull
101 cea10000 2005-05-01 devnull /*
102 cea10000 2005-05-01 devnull * sleep and wakeup
103 cea10000 2005-05-01 devnull */
104 cea10000 2005-05-01 devnull static void
105 cea10000 2005-05-01 devnull ign(int x)
106 cea10000 2005-05-01 devnull {
107 cea10000 2005-05-01 devnull USED(x);
108 cea10000 2005-05-01 devnull }
109 cea10000 2005-05-01 devnull
110 cea10000 2005-05-01 devnull static void /*__attribute__((constructor))*/
111 cea10000 2005-05-01 devnull ignusr1(int restart)
112 cea10000 2005-05-01 devnull {
113 cea10000 2005-05-01 devnull struct sigaction sa;
114 cea10000 2005-05-01 devnull
115 cea10000 2005-05-01 devnull memset(&sa, 0, sizeof sa);
116 cea10000 2005-05-01 devnull sa.sa_handler = ign;
117 cea10000 2005-05-01 devnull sigemptyset(&sa.sa_mask);
118 cea10000 2005-05-01 devnull sigaddset(&sa.sa_mask, SIGUSR1);
119 cea10000 2005-05-01 devnull if(restart)
120 cea10000 2005-05-01 devnull sa.sa_flags = SA_RESTART;
121 cea10000 2005-05-01 devnull sigaction(SIGUSR1, &sa, nil);
122 cea10000 2005-05-01 devnull }
123 cea10000 2005-05-01 devnull
124 cea10000 2005-05-01 devnull void
125 cea10000 2005-05-01 devnull _procsleep(_Procrendez *r)
126 cea10000 2005-05-01 devnull {
127 cea10000 2005-05-01 devnull sigset_t mask;
128 cea10000 2005-05-01 devnull
129 cea10000 2005-05-01 devnull /*
130 cea10000 2005-05-01 devnull * Go to sleep.
131 cea10000 2005-05-01 devnull *
132 cea10000 2005-05-01 devnull * Block USR1, set the handler to interrupt system calls,
133 cea10000 2005-05-01 devnull * unlock the vouslock so our waker can wake us,
134 cea10000 2005-05-01 devnull * and then suspend.
135 cea10000 2005-05-01 devnull */
136 cea10000 2005-05-01 devnull again:
137 cea10000 2005-05-01 devnull r->asleep = 1;
138 cea10000 2005-05-01 devnull r->pid = getpid();
139 cea10000 2005-05-01 devnull
140 cea10000 2005-05-01 devnull sigprocmask(SIG_SETMASK, nil, &mask);
141 cea10000 2005-05-01 devnull sigaddset(&mask, SIGUSR1);
142 cea10000 2005-05-01 devnull sigprocmask(SIG_SETMASK, &mask, nil);
143 cea10000 2005-05-01 devnull ignusr1(0);
144 cea10000 2005-05-01 devnull unlock(r->l);
145 cea10000 2005-05-01 devnull sigdelset(&mask, SIGUSR1);
146 cea10000 2005-05-01 devnull sigsuspend(&mask);
147 cea10000 2005-05-01 devnull
148 cea10000 2005-05-01 devnull /*
149 cea10000 2005-05-01 devnull * We're awake. Make USR1 not interrupt system calls.
150 cea10000 2005-05-01 devnull */
151 cea10000 2005-05-01 devnull lock(r->l);
152 cea10000 2005-05-01 devnull ignusr1(1);
153 cea10000 2005-05-01 devnull if(r->asleep && r->pid == getpid()){
154 cea10000 2005-05-01 devnull /* Didn't really wake up - signal from something else */
155 cea10000 2005-05-01 devnull goto again;
156 cea10000 2005-05-01 devnull }
157 cea10000 2005-05-01 devnull }
158 cea10000 2005-05-01 devnull
159 cea10000 2005-05-01 devnull void
160 cea10000 2005-05-01 devnull _procwakeup(_Procrendez *r)
161 cea10000 2005-05-01 devnull {
162 cea10000 2005-05-01 devnull if(r->asleep){
163 cea10000 2005-05-01 devnull r->asleep = 0;
164 cea10000 2005-05-01 devnull assert(r->pid >= 1);
165 cea10000 2005-05-01 devnull kill(r->pid, SIGUSR1);
166 cea10000 2005-05-01 devnull }
167 cea10000 2005-05-01 devnull }
168 cea10000 2005-05-01 devnull
169 cea10000 2005-05-01 devnull void
170 cea10000 2005-05-01 devnull _procwakeupandunlock(_Procrendez *r)
171 cea10000 2005-05-01 devnull {
172 cea10000 2005-05-01 devnull _procwakeup(r);
173 cea10000 2005-05-01 devnull unlock(r->l);
174 cea10000 2005-05-01 devnull }
175 cea10000 2005-05-01 devnull
176 cea10000 2005-05-01 devnull
177 cea10000 2005-05-01 devnull /*
178 cea10000 2005-05-01 devnull * process creation and exit
179 cea10000 2005-05-01 devnull */
180 cea10000 2005-05-01 devnull typedef struct Stackfree Stackfree;
181 cea10000 2005-05-01 devnull struct Stackfree
182 cea10000 2005-05-01 devnull {
183 cea10000 2005-05-01 devnull Stackfree *next;
184 cea10000 2005-05-01 devnull int pid;
185 cea10000 2005-05-01 devnull };
186 cea10000 2005-05-01 devnull static Lock stacklock;
187 cea10000 2005-05-01 devnull static Stackfree *stackfree;
188 cea10000 2005-05-01 devnull
189 cea10000 2005-05-01 devnull static void
190 cea10000 2005-05-01 devnull delayfreestack(uchar *stk)
191 cea10000 2005-05-01 devnull {
192 cea10000 2005-05-01 devnull Stackfree *sf;
193 cea10000 2005-05-01 devnull
194 cea10000 2005-05-01 devnull sf = (Stackfree*)stk;
195 cea10000 2005-05-01 devnull sf->pid = getpid();
196 cea10000 2005-05-01 devnull lock(&stacklock);
197 cea10000 2005-05-01 devnull sf->next = stackfree;
198 cea10000 2005-05-01 devnull stackfree = sf;
199 cea10000 2005-05-01 devnull unlock(&stacklock);
200 cea10000 2005-05-01 devnull }
201 cea10000 2005-05-01 devnull
202 cea10000 2005-05-01 devnull static void
203 cea10000 2005-05-01 devnull dofreestacks(void)
204 cea10000 2005-05-01 devnull {
205 cea10000 2005-05-01 devnull Stackfree *sf, *last, *next;
206 cea10000 2005-05-01 devnull
207 cea10000 2005-05-01 devnull if(stackfree==nil || !canlock(&stacklock))
208 cea10000 2005-05-01 devnull return;
209 cea10000 2005-05-01 devnull
210 cea10000 2005-05-01 devnull for(last=nil,sf=stackfree; sf; last=sf,sf=next){
211 cea10000 2005-05-01 devnull next = sf->next;
212 cea10000 2005-05-01 devnull if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
213 cea10000 2005-05-01 devnull free(sf);
214 cea10000 2005-05-01 devnull if(last)
215 cea10000 2005-05-01 devnull last->next = next;
216 cea10000 2005-05-01 devnull else
217 cea10000 2005-05-01 devnull stackfree = next;
218 cea10000 2005-05-01 devnull sf = last;
219 cea10000 2005-05-01 devnull }
220 cea10000 2005-05-01 devnull }
221 cea10000 2005-05-01 devnull unlock(&stacklock);
222 cea10000 2005-05-01 devnull }
223 cea10000 2005-05-01 devnull
224 cea10000 2005-05-01 devnull static int
225 cea10000 2005-05-01 devnull startprocfn(void *v)
226 cea10000 2005-05-01 devnull {
227 cea10000 2005-05-01 devnull void **a;
228 cea10000 2005-05-01 devnull uchar *stk;
229 cea10000 2005-05-01 devnull void (*fn)(void*);
230 cea10000 2005-05-01 devnull Proc *p;
231 cea10000 2005-05-01 devnull
232 cea10000 2005-05-01 devnull a = (void**)v;
233 cea10000 2005-05-01 devnull fn = a[0];
234 cea10000 2005-05-01 devnull p = a[1];
235 cea10000 2005-05-01 devnull stk = a[2];
236 cea10000 2005-05-01 devnull free(a);
237 cea10000 2005-05-01 devnull p->osprocid = getpid();
238 cea10000 2005-05-01 devnull
239 cea10000 2005-05-01 devnull (*fn)(p);
240 cea10000 2005-05-01 devnull
241 cea10000 2005-05-01 devnull delayfreestack(stk);
242 cea10000 2005-05-01 devnull _exit(0);
243 cea10000 2005-05-01 devnull return 0;
244 cea10000 2005-05-01 devnull }
245 cea10000 2005-05-01 devnull
246 cea10000 2005-05-01 devnull void
247 cea10000 2005-05-01 devnull _procstart(Proc *p, void (*fn)(Proc*))
248 cea10000 2005-05-01 devnull {
249 cea10000 2005-05-01 devnull void **a;
250 cea10000 2005-05-01 devnull uchar *stk;
251 cea10000 2005-05-01 devnull int pid;
252 cea10000 2005-05-01 devnull
253 cea10000 2005-05-01 devnull dofreestacks();
254 cea10000 2005-05-01 devnull a = malloc(3*sizeof a[0]);
255 cea10000 2005-05-01 devnull if(a == nil)
256 cea10000 2005-05-01 devnull sysfatal("_procstart malloc: %r");
257 cea10000 2005-05-01 devnull stk = malloc(65536);
258 cea10000 2005-05-01 devnull if(stk == nil)
259 cea10000 2005-05-01 devnull sysfatal("_procstart malloc stack: %r");
260 cea10000 2005-05-01 devnull
261 cea10000 2005-05-01 devnull a[0] = fn;
262 cea10000 2005-05-01 devnull a[1] = p;
263 cea10000 2005-05-01 devnull a[2] = stk;
264 cea10000 2005-05-01 devnull
265 cea10000 2005-05-01 devnull pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a);
266 cea10000 2005-05-01 devnull if(pid < 0){
267 cea10000 2005-05-01 devnull fprint(2, "_procstart rfork_thread: %r\n");
268 cea10000 2005-05-01 devnull abort();
269 cea10000 2005-05-01 devnull }
270 cea10000 2005-05-01 devnull }
271 cea10000 2005-05-01 devnull
272 cea10000 2005-05-01 devnull static char *threadexitsmsg;
273 cea10000 2005-05-01 devnull void
274 cea10000 2005-05-01 devnull sigusr2handler(int s)
275 cea10000 2005-05-01 devnull {
276 cea10000 2005-05-01 devnull /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
277 cea10000 2005-05-01 devnull if(threadexitsmsg)
278 cea10000 2005-05-01 devnull _exits(threadexitsmsg);
279 cea10000 2005-05-01 devnull }
280 cea10000 2005-05-01 devnull
281 cea10000 2005-05-01 devnull void
282 cea10000 2005-05-01 devnull threadexitsall(char *msg)
283 cea10000 2005-05-01 devnull {
284 cea10000 2005-05-01 devnull static int pid[1024];
285 cea10000 2005-05-01 devnull int i, npid, mypid;
286 cea10000 2005-05-01 devnull Proc *p;
287 9689b580 2005-07-27 devnull
288 f19d5682 2005-07-28 devnull if(msg == nil)
289 f19d5682 2005-07-28 devnull msg = "";
290 f19d5682 2005-07-28 devnull
291 9689b580 2005-07-27 devnull /*
292 9689b580 2005-07-27 devnull * Only one guy, ever, gets to run this.
293 9689b580 2005-07-27 devnull * If two guys do it, inevitably they end up
294 9689b580 2005-07-27 devnull * tripping over each other in the underlying
295 9689b580 2005-07-27 devnull * C library exit() implementation, which is
296 9689b580 2005-07-27 devnull * trying to run the atexit handlers and apparently
297 9689b580 2005-07-27 devnull * not thread safe. This has been observed on
298 9689b580 2005-07-27 devnull * both Linux and OpenBSD. Sigh.
299 9689b580 2005-07-27 devnull */
300 9689b580 2005-07-27 devnull {
301 9689b580 2005-07-27 devnull static Lock onelock;
302 f19d5682 2005-07-28 devnull if(!canlock(&onelock))
303 f19d5682 2005-07-28 devnull _exits(threadexitsmsg);
304 f19d5682 2005-07-28 devnull threadexitsmsg = msg;
305 9689b580 2005-07-27 devnull }
306 cea10000 2005-05-01 devnull
307 cea10000 2005-05-01 devnull if(msg == nil)
308 cea10000 2005-05-01 devnull msg = "";
309 cea10000 2005-05-01 devnull mypid = getpid();
310 cea10000 2005-05-01 devnull lock(&_threadprocslock);
311 cea10000 2005-05-01 devnull threadexitsmsg = msg;
312 cea10000 2005-05-01 devnull npid = 0;
313 cea10000 2005-05-01 devnull for(p=_threadprocs; p; p=p->next)
314 cea10000 2005-05-01 devnull if(p->osprocid != mypid && p->osprocid >= 1)
315 cea10000 2005-05-01 devnull pid[npid++] = p->osprocid;
316 cea10000 2005-05-01 devnull for(i=0; i<npid; i++)
317 cea10000 2005-05-01 devnull kill(pid[i], SIGUSR2);
318 cea10000 2005-05-01 devnull unlock(&_threadprocslock);
319 cea10000 2005-05-01 devnull exits(msg);
320 cea10000 2005-05-01 devnull }
321 cea10000 2005-05-01 devnull
322 cea10000 2005-05-01 devnull /*
323 cea10000 2005-05-01 devnull * per-process data, indexed by pid
324 cea10000 2005-05-01 devnull */
325 cea10000 2005-05-01 devnull typedef struct Perproc Perproc;
326 cea10000 2005-05-01 devnull struct Perproc
327 cea10000 2005-05-01 devnull {
328 cea10000 2005-05-01 devnull int pid;
329 cea10000 2005-05-01 devnull Proc *proc;
330 cea10000 2005-05-01 devnull };
331 cea10000 2005-05-01 devnull
332 cea10000 2005-05-01 devnull static Lock perlock;
333 cea10000 2005-05-01 devnull static Perproc perproc[1024];
334 cea10000 2005-05-01 devnull #define P ((Proc*)-1)
335 cea10000 2005-05-01 devnull
336 cea10000 2005-05-01 devnull static Perproc*
337 cea10000 2005-05-01 devnull myperproc(void)
338 cea10000 2005-05-01 devnull {
339 cea10000 2005-05-01 devnull int i, pid, h;
340 cea10000 2005-05-01 devnull Perproc *p;
341 cea10000 2005-05-01 devnull
342 cea10000 2005-05-01 devnull pid = getpid();
343 cea10000 2005-05-01 devnull h = pid%nelem(perproc);
344 cea10000 2005-05-01 devnull for(i=0; i<nelem(perproc); i++){
345 cea10000 2005-05-01 devnull p = &perproc[(i+h)%nelem(perproc)];
346 cea10000 2005-05-01 devnull if(p->pid == pid)
347 cea10000 2005-05-01 devnull return p;
348 cea10000 2005-05-01 devnull if(p->pid == 0){
349 cea10000 2005-05-01 devnull print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
350 cea10000 2005-05-01 devnull break;
351 cea10000 2005-05-01 devnull }
352 cea10000 2005-05-01 devnull }
353 cea10000 2005-05-01 devnull fprint(2, "myperproc %d: cannot find self\n", pid);
354 cea10000 2005-05-01 devnull abort();
355 cea10000 2005-05-01 devnull return nil;
356 cea10000 2005-05-01 devnull }
357 cea10000 2005-05-01 devnull
358 cea10000 2005-05-01 devnull static Perproc*
359 cea10000 2005-05-01 devnull newperproc(void)
360 cea10000 2005-05-01 devnull {
361 cea10000 2005-05-01 devnull int i, pid, h;
362 cea10000 2005-05-01 devnull Perproc *p;
363 cea10000 2005-05-01 devnull
364 cea10000 2005-05-01 devnull lock(&perlock);
365 cea10000 2005-05-01 devnull pid = getpid();
366 cea10000 2005-05-01 devnull h = pid%nelem(perproc);
367 cea10000 2005-05-01 devnull for(i=0; i<nelem(perproc); i++){
368 cea10000 2005-05-01 devnull p = &perproc[(i+h)%nelem(perproc)];
369 cea10000 2005-05-01 devnull if(p->pid == pid || p->pid == -1 || p->pid == 0){
370 cea10000 2005-05-01 devnull p->pid = pid;
371 cea10000 2005-05-01 devnull unlock(&perlock);
372 cea10000 2005-05-01 devnull return p;
373 cea10000 2005-05-01 devnull }
374 cea10000 2005-05-01 devnull }
375 cea10000 2005-05-01 devnull fprint(2, "newperproc %d: out of procs\n", pid);
376 cea10000 2005-05-01 devnull abort();
377 cea10000 2005-05-01 devnull return nil;
378 cea10000 2005-05-01 devnull }
379 cea10000 2005-05-01 devnull
380 cea10000 2005-05-01 devnull Proc*
381 cea10000 2005-05-01 devnull _threadproc(void)
382 cea10000 2005-05-01 devnull {
383 cea10000 2005-05-01 devnull return myperproc()->proc;
384 cea10000 2005-05-01 devnull }
385 cea10000 2005-05-01 devnull
386 cea10000 2005-05-01 devnull void
387 cea10000 2005-05-01 devnull _threadsetproc(Proc *p)
388 cea10000 2005-05-01 devnull {
389 cea10000 2005-05-01 devnull Perproc *pp;
390 cea10000 2005-05-01 devnull
391 cea10000 2005-05-01 devnull if(p)
392 cea10000 2005-05-01 devnull p->osprocid = getpid();
393 cea10000 2005-05-01 devnull pp = newperproc();
394 cea10000 2005-05-01 devnull pp->proc = p;
395 cea10000 2005-05-01 devnull if(p == nil)
396 cea10000 2005-05-01 devnull pp->pid = -1;
397 cea10000 2005-05-01 devnull }
398 cea10000 2005-05-01 devnull
399 cea10000 2005-05-01 devnull void
400 cea10000 2005-05-01 devnull _threadpexit(void)
401 cea10000 2005-05-01 devnull {
402 cea10000 2005-05-01 devnull _exit(0);
403 cea10000 2005-05-01 devnull }
404 cea10000 2005-05-01 devnull