9 #include "threadimpl.h"
17 extern int _tas(int*);
20 _threadunlock(Lock *l, ulong pc)
28 _threadlock(Lock *l, int block, ulong pc)
40 /* a thousand times pretty fast */
41 for(i=0; i<1000; i++){
46 /* now nice and slow */
47 for(i=0; i<1000; i++){
67 static void /*__attribute__((constructor))*/
72 memset(&sa, 0, sizeof sa);
74 sigemptyset(&sa.sa_mask);
75 sigaddset(&sa.sa_mask, SIGUSR1);
77 sa.sa_flags = SA_RESTART;
78 sigaction(SIGUSR1, &sa, nil);
82 _procsleep(_Procrendez *r)
89 * Block USR1, set the handler to interrupt system calls,
90 * unlock the vouslock so our waker can wake us,
97 sigprocmask(SIG_SETMASK, nil, &mask);
98 sigaddset(&mask, SIGUSR1);
99 sigprocmask(SIG_SETMASK, &mask, nil);
102 sigdelset(&mask, SIGUSR1);
106 * We're awake. Make USR1 not interrupt system calls.
110 if(r->asleep && r->pid == getpid()){
111 /* Didn't really wake up - signal from something else */
117 _procwakeup(_Procrendez *r)
122 kill(r->pid, SIGUSR1);
127 * process creation and exit
129 typedef struct Stackfree Stackfree;
135 static Lock stacklock;
136 static Stackfree *stackfree;
139 delayfreestack(uchar *stk)
143 sf = (Stackfree*)stk;
146 sf->next = stackfree;
154 Stackfree *sf, *last, *next;
156 if(stackfree==nil || !canlock(&stacklock))
159 for(last=nil,sf=stackfree; sf; last=sf,sf=next){
161 if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
186 p->osprocid = getpid();
196 * indirect through here so that parent need not wait for child zombie
198 * slight race - if child exits and then another process starts before we
199 * manage to exit, we'll be running on a freed stack.
207 *(int*)a[3] = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a);
213 _procstart(Proc *p, void (*fn)(Proc*))
217 int pid, kidpid, status;
220 a = malloc(4*sizeof a[0]);
222 sysfatal("_procstart malloc: %r");
225 sysfatal("_procstart malloc stack: %r");
233 pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a);
235 if(wait4(pid, &status, __WALL, 0) < 0)
236 fprint(2, "ffork wait4: %r\n");
237 if(pid < 0 || kidpid < 0){
238 fprint(2, "_procstart clone: %r\n");
243 static char *threadexitsmsg;
245 sigusr2handler(int s)
247 /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
249 _exits(threadexitsmsg);
253 threadexitsall(char *msg)
255 static int pid[1024];
262 lock(&_threadprocslock);
263 threadexitsmsg = msg;
265 for(p=_threadprocs; p; p=p->next)
266 if(p->osprocid != mypid && p->osprocid >= 1)
267 pid[npid++] = p->osprocid;
268 for(i=0; i<npid; i++)
269 kill(pid[i], SIGUSR2);
270 unlock(&_threadprocslock);
275 * per-process data, indexed by pid
277 * could use modify_ldt and a segment register
278 * to avoid the many calls to getpid(), but i don't
279 * care -- this is compatibility code. linux 2.6 with
280 * nptl is a good enough pthreads to avoid this whole file.
282 typedef struct Perproc Perproc;
290 static Perproc perproc[1024];
291 #define P ((Proc*)-1)
300 h = pid%nelem(perproc);
301 for(i=0; i<nelem(perproc); i++){
302 p = &perproc[(i+h)%nelem(perproc)];
306 print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
310 fprint(2, "myperproc %d: cannot find self\n", pid);
323 h = pid%nelem(perproc);
324 for(i=0; i<nelem(perproc); i++){
325 p = &perproc[(i+h)%nelem(perproc)];
326 if(p->pid == pid || p->pid == -1 || p->pid == 0){
332 fprint(2, "newperproc %d: out of procs\n", pid);
340 return myperproc()->proc;
344 _threadsetproc(Proc *p)
349 p->osprocid = getpid();
359 signal(SIGUSR2, sigusr2handler);