1 #include "threadimpl.h"
6 extern int __isthreaded;
11 extern int _tas(int*);
14 _threadunlock(Lock *l, ulong pc)
22 _threadlock(Lock *l, int block, ulong pc)
34 /* a thousand times pretty fast */
35 for(i=0; i<1000; i++){
40 /* now nice and slow */
41 for(i=0; i<1000; i++){
57 volatile long access_lock;
58 volatile long lock_owner;
64 _spinlock(spinlock_t *lk)
66 lock((Lock*)&lk->access_lock);
78 static void /*__attribute__((constructor))*/
83 memset(&sa, 0, sizeof sa);
85 sigemptyset(&sa.sa_mask);
86 sigaddset(&sa.sa_mask, SIGUSR1);
88 sa.sa_flags = SA_RESTART;
89 sigaction(SIGUSR1, &sa, nil);
93 _procsleep(_Procrendez *r)
100 * Block USR1, set the handler to interrupt system calls,
101 * unlock the vouslock so our waker can wake us,
108 sigprocmask(SIG_SETMASK, nil, &mask);
109 sigaddset(&mask, SIGUSR1);
110 sigprocmask(SIG_SETMASK, &mask, nil);
113 sigdelset(&mask, SIGUSR1);
117 * We're awake. Make USR1 not interrupt system calls.
121 if(r->asleep && r->pid == getpid()){
122 /* Didn't really wake up - signal from something else */
128 _procwakeup(_Procrendez *r)
133 kill(r->pid, SIGUSR1);
138 _procwakeupandunlock(_Procrendez *r)
146 * process creation and exit
148 typedef struct Stackfree Stackfree;
154 static Lock stacklock;
155 static Stackfree *stackfree;
158 delayfreestack(uchar *stk)
162 sf = (Stackfree*)stk;
165 sf->next = stackfree;
173 Stackfree *sf, *last, *next;
175 if(stackfree==nil || !canlock(&stacklock))
178 for(last=nil,sf=stackfree; sf; last=sf,sf=next){
180 if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
205 p->osprocid = getpid();
215 _procstart(Proc *p, void (*fn)(Proc*))
222 a = malloc(3*sizeof a[0]);
224 sysfatal("_procstart malloc: %r");
227 sysfatal("_procstart malloc stack: %r");
233 pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a);
235 fprint(2, "_procstart rfork_thread: %r\n");
240 static char *threadexitsmsg;
242 sigusr2handler(int s)
244 /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
246 _exits(threadexitsmsg);
250 threadexitsall(char *msg)
252 static int pid[1024];
259 lock(&_threadprocslock);
260 threadexitsmsg = msg;
262 for(p=_threadprocs; p; p=p->next)
263 if(p->osprocid != mypid && p->osprocid >= 1)
264 pid[npid++] = p->osprocid;
265 for(i=0; i<npid; i++)
266 kill(pid[i], SIGUSR2);
267 unlock(&_threadprocslock);
272 * per-process data, indexed by pid
274 * could use modify_ldt and a segment register
275 * to avoid the many calls to getpid(), but i don't
276 * care -- this is compatibility code. linux 2.6 with
277 * nptl is a good enough pthreads to avoid this whole file.
279 typedef struct Perproc Perproc;
287 static Perproc perproc[1024];
288 #define P ((Proc*)-1)
297 h = pid%nelem(perproc);
298 for(i=0; i<nelem(perproc); i++){
299 p = &perproc[(i+h)%nelem(perproc)];
303 print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
307 fprint(2, "myperproc %d: cannot find self\n", pid);
320 h = pid%nelem(perproc);
321 for(i=0; i<nelem(perproc); i++){
322 p = &perproc[(i+h)%nelem(perproc)];
323 if(p->pid == pid || p->pid == -1 || p->pid == 0){
329 fprint(2, "newperproc %d: out of procs\n", pid);
337 return myperproc()->proc;
341 _threadsetproc(Proc *p)
346 p->osprocid = getpid();
357 signal(SIGUSR2, sigusr2handler);
368 * FreeBSD 4 and earlier needs the context functions.
371 makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
375 sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4;
377 memmove(sp, &argc+1, argc*sizeof(int));
378 *--sp = 0; /* return address */
379 ucp->uc_mcontext.mc_eip = (long)func;
380 ucp->uc_mcontext.mc_esp = (int)sp;
383 extern int getmcontext(mcontext_t*);
384 extern int setmcontext(mcontext_t*);
387 getcontext(ucontext_t *uc)
389 return getmcontext(&uc->uc_mcontext);
393 setcontext(ucontext_t *uc)
395 setmcontext(&uc->uc_mcontext);
399 swapcontext(ucontext_t *oucp, ucontext_t *ucp)
401 if(getcontext(oucp) == 0)