1 #include "threadimpl.h"
6 static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
7 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
11 tm = *localtime(time(0));
12 return fmtprint(fmt, "%s %2d %02d:%02d:%02d.%03d",
13 mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec,
14 (int)(ns%1000000000)/1000000);
20 extern int _tas(int*);
23 _threadunlock(Lock *l, ulong pc)
31 _threadlock(Lock *l, int block, ulong pc)
35 if(first) {first=0; fmtinstall('\001', timefmt);}
45 /* a thousand times pretty fast */
46 for(i=0; i<1000; i++){
51 /* now increasingly slow */
57 fprint(2, "%\001 %s: lock loop1 %p from %lux\n", argv0, l, pc);
63 fprint(2, "%\001 %s: lock loop2 %p from %lux\n", argv0, l, pc);
69 fprint(2, "%\001 %s: lock loop3 %p from %lux\n", argv0, l, pc);
75 fprint(2, "%\001 %s: lock loop4 %p from %lux\n", argv0, l, pc);
81 fprint(2, "%\001 %s: lock loop5 %p from %lux\n", argv0, l, pc);
82 for(i=0; i<1000; i++){
87 fprint(2, "%\001 %s: lock loop6 %p from %lux\n", argv0, l, pc);
103 static void /*__attribute__((constructor))*/
108 memset(&sa, 0, sizeof sa);
110 sigemptyset(&sa.sa_mask);
111 sigaddset(&sa.sa_mask, SIGUSR1);
113 sa.sa_flags = SA_RESTART;
114 sigaction(SIGUSR1, &sa, nil);
118 _procsleep(_Procrendez *r)
125 * Block USR1, set the handler to interrupt system calls,
126 * unlock the vouslock so our waker can wake us,
133 sigprocmask(SIG_SETMASK, nil, &mask);
134 sigaddset(&mask, SIGUSR1);
135 sigprocmask(SIG_SETMASK, &mask, nil);
138 sigdelset(&mask, SIGUSR1);
142 * We're awake. Make USR1 not interrupt system calls.
146 if(r->asleep && r->pid == getpid()){
147 /* Didn't really wake up - signal from something else */
153 _procwakeupandunlock(_Procrendez *r)
170 * process creation and exit
172 typedef struct Stackfree Stackfree;
179 static Lock stacklock;
180 static Stackfree *stackfree;
183 delayfreestack(uchar *stk, int pid, int pid1)
187 sf = (Stackfree*)stk;
191 sf->next = stackfree;
199 Stackfree *sf, *last, *next;
201 if(stackfree==nil || !canlock(&stacklock))
204 for(last=nil,sf=stackfree; sf; last=sf,sf=next){
206 if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH)
207 if(sf->pid1 >= 1 && kill(sf->pid1, 0) < 0 && errno == ESRCH){
239 delayfreestack(stk, pid0, pid1);
245 * indirect through here so that parent need not wait for child zombie
247 * slight race - if child exits and then another process starts before we
248 * manage to exit, we'll be running on a freed stack.
258 a[4] = (void*)getpid();
259 *kidpid = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a);
265 _procstart(Proc *p, void (*fn)(Proc*))
269 int pid, kidpid, status;
272 a = malloc(5*sizeof a[0]);
274 sysfatal("_procstart malloc: %r");
277 sysfatal("_procstart malloc stack: %r");
285 pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a);
287 if(wait4(pid, &status, __WALL, 0) < 0)
288 fprint(2, "ffork wait4: %r\n");
289 if(pid < 0 || kidpid < 0){
290 fprint(2, "_procstart clone: %r\n");
295 static char *threadexitsmsg;
297 sigusr2handler(int s)
299 /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
301 _exits(threadexitsmsg);
305 threadexitsall(char *msg)
307 static int pid[1024];
314 lock(&_threadprocslock);
315 threadexitsmsg = msg;
317 for(p=_threadprocs; p; p=p->next)
318 if(p->osprocid != mypid && p->osprocid >= 1)
319 pid[npid++] = p->osprocid;
320 for(i=0; i<npid; i++)
321 kill(pid[i], SIGUSR2);
322 unlock(&_threadprocslock);
327 * per-process data, indexed by pid
329 * could use modify_ldt and a segment register
330 * to avoid the many calls to getpid(), but i don't
331 * care -- this is compatibility code. linux 2.6 with
332 * nptl is a good enough pthreads to avoid this whole file.
334 typedef struct Perproc Perproc;
342 static Perproc perproc[1024];
343 #define P ((Proc*)-1)
352 h = pid%nelem(perproc);
353 for(i=0; i<nelem(perproc); i++){
354 p = &perproc[(i+h)%nelem(perproc)];
358 print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
362 fprint(2, "myperproc %d: cannot find self\n", pid);
375 h = pid%nelem(perproc);
376 for(i=0; i<nelem(perproc); i++){
377 p = &perproc[(i+h)%nelem(perproc)];
378 if(p->pid == pid || p->pid == -1 || p->pid == 0){
384 fprint(2, "newperproc %d: out of procs\n", pid);
392 return myperproc()->proc;
396 _threadsetproc(Proc *p)
401 p->osprocid = getpid();
411 signal(SIGUSR2, sigusr2handler);