1 cea10000 2005-05-01 devnull #undef exits
2 cea10000 2005-05-01 devnull #undef _exits
4 cea10000 2005-05-01 devnull extern int __isthreaded;
7 cea10000 2005-05-01 devnull * spin locks
9 cea10000 2005-05-01 devnull extern int _tas(int*);
12 cea10000 2005-05-01 devnull _threadunlock(Lock *l, ulong pc)
14 cea10000 2005-05-01 devnull USED(pc);
16 cea10000 2005-05-01 devnull l->held = 0;
20 cea10000 2005-05-01 devnull _threadlock(Lock *l, int block, ulong pc)
24 cea10000 2005-05-01 devnull USED(pc);
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;
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);
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);
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);
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);
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);
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);
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);
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;
77 cea10000 2005-05-01 devnull * For libc.
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;
88 cea10000 2005-05-01 devnull _spinlock(spinlock_t *lk)
90 cea10000 2005-05-01 devnull lock((Lock*)&lk->access_lock);
94 fe8c925e 2005-07-21 devnull _spinunlock(spinlock_t *lk)
96 fe8c925e 2005-07-21 devnull unlock((Lock*)&lk->access_lock);
102 cea10000 2005-05-01 devnull * sleep and wakeup
104 cea10000 2005-05-01 devnull static void
105 cea10000 2005-05-01 devnull ign(int x)
107 cea10000 2005-05-01 devnull USED(x);
110 cea10000 2005-05-01 devnull static void /*__attribute__((constructor))*/
111 cea10000 2005-05-01 devnull ignusr1(int restart)
113 cea10000 2005-05-01 devnull struct sigaction sa;
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);
125 cea10000 2005-05-01 devnull _procsleep(_Procrendez *r)
127 cea10000 2005-05-01 devnull sigset_t mask;
130 cea10000 2005-05-01 devnull * Go to sleep.
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.
137 cea10000 2005-05-01 devnull r->asleep = 1;
138 cea10000 2005-05-01 devnull r->pid = getpid();
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);
149 cea10000 2005-05-01 devnull * We're awake. Make USR1 not interrupt system calls.
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;
160 cea10000 2005-05-01 devnull _procwakeup(_Procrendez *r)
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);
170 cea10000 2005-05-01 devnull _procwakeupandunlock(_Procrendez *r)
172 cea10000 2005-05-01 devnull _procwakeup(r);
173 cea10000 2005-05-01 devnull unlock(r->l);
178 cea10000 2005-05-01 devnull * process creation and exit
180 cea10000 2005-05-01 devnull typedef struct Stackfree Stackfree;
181 cea10000 2005-05-01 devnull struct Stackfree
183 cea10000 2005-05-01 devnull Stackfree *next;
184 cea10000 2005-05-01 devnull int pid;
186 cea10000 2005-05-01 devnull static Lock stacklock;
187 cea10000 2005-05-01 devnull static Stackfree *stackfree;
189 cea10000 2005-05-01 devnull static void
190 cea10000 2005-05-01 devnull delayfreestack(uchar *stk)
192 cea10000 2005-05-01 devnull Stackfree *sf;
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);
202 cea10000 2005-05-01 devnull static void
203 cea10000 2005-05-01 devnull dofreestacks(void)
205 cea10000 2005-05-01 devnull Stackfree *sf, *last, *next;
207 cea10000 2005-05-01 devnull if(stackfree==nil || !canlock(&stacklock))
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;
217 cea10000 2005-05-01 devnull stackfree = next;
218 cea10000 2005-05-01 devnull sf = last;
221 cea10000 2005-05-01 devnull unlock(&stacklock);
224 cea10000 2005-05-01 devnull static int
225 cea10000 2005-05-01 devnull startprocfn(void *v)
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;
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();
239 cea10000 2005-05-01 devnull (*fn)(p);
241 cea10000 2005-05-01 devnull delayfreestack(stk);
242 cea10000 2005-05-01 devnull _exit(0);
243 cea10000 2005-05-01 devnull return 0;
247 cea10000 2005-05-01 devnull _procstart(Proc *p, void (*fn)(Proc*))
249 cea10000 2005-05-01 devnull void **a;
250 cea10000 2005-05-01 devnull uchar *stk;
251 cea10000 2005-05-01 devnull int pid;
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");
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;
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();
272 cea10000 2005-05-01 devnull static char *threadexitsmsg;
274 cea10000 2005-05-01 devnull sigusr2handler(int s)
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);
282 cea10000 2005-05-01 devnull threadexitsall(char *msg)
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;
288 f19d5682 2005-07-28 devnull if(msg == nil)
289 f19d5682 2005-07-28 devnull msg = "";
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.
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;
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);
323 cea10000 2005-05-01 devnull * per-process data, indexed by pid
325 cea10000 2005-05-01 devnull typedef struct Perproc Perproc;
326 cea10000 2005-05-01 devnull struct Perproc
328 cea10000 2005-05-01 devnull int pid;
329 cea10000 2005-05-01 devnull Proc *proc;
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)
336 cea10000 2005-05-01 devnull static Perproc*
337 cea10000 2005-05-01 devnull myperproc(void)
339 cea10000 2005-05-01 devnull int i, pid, h;
340 cea10000 2005-05-01 devnull Perproc *p;
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);
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;
358 cea10000 2005-05-01 devnull static Perproc*
359 cea10000 2005-05-01 devnull newperproc(void)
361 cea10000 2005-05-01 devnull int i, pid, h;
362 cea10000 2005-05-01 devnull Perproc *p;
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;
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;
381 cea10000 2005-05-01 devnull _threadproc(void)
383 cea10000 2005-05-01 devnull return myperproc()->proc;
387 cea10000 2005-05-01 devnull _threadsetproc(Proc *p)
389 cea10000 2005-05-01 devnull Perproc *pp;
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;
400 cea10000 2005-05-01 devnull _threadpexit(void)
402 cea10000 2005-05-01 devnull _exit(0);