1 8d82ccef 2020-01-20 rsc #include "threadimpl.h"
7 8d82ccef 2020-01-20 rsc timefmt(Fmt *fmt)
9 8d82ccef 2020-01-20 rsc static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
10 8d82ccef 2020-01-20 rsc "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
14 8d82ccef 2020-01-20 rsc tm = *localtime(time(0));
15 8d82ccef 2020-01-20 rsc return fmtprint(fmt, "%s %2d %02d:%02d:%02d.%03d",
16 8d82ccef 2020-01-20 rsc mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec,
17 8d82ccef 2020-01-20 rsc (int)(ns%1000000000)/1000000);
23 8d82ccef 2020-01-20 rsc extern int _tas(int*);
26 8d82ccef 2020-01-20 rsc _threadunlock(Lock *l, ulong pc)
34 8d82ccef 2020-01-20 rsc _threadlock(Lock *l, int block, ulong pc)
37 8d82ccef 2020-01-20 rsc static int first=1;
38 8d82ccef 2020-01-20 rsc if(first) {first=0; fmtinstall('\001', timefmt);}
42 8d82ccef 2020-01-20 rsc /* once fast */
43 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
48 8d82ccef 2020-01-20 rsc /* a thousand times pretty fast */
49 8d82ccef 2020-01-20 rsc for(i=0; i<1000; i++){
50 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
52 8d82ccef 2020-01-20 rsc sched_yield();
54 8d82ccef 2020-01-20 rsc /* now increasingly slow */
55 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
56 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
60 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop1 %p from %lux\n", argv0, l, pc);
61 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
62 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
66 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop2 %p from %lux\n", argv0, l, pc);
67 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
68 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
72 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop3 %p from %lux\n", argv0, l, pc);
73 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
74 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
76 8d82ccef 2020-01-20 rsc usleep(1000);
78 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop4 %p from %lux\n", argv0, l, pc);
79 8d82ccef 2020-01-20 rsc for(i=0; i<10; i++){
80 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
82 8d82ccef 2020-01-20 rsc usleep(10*1000);
84 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop5 %p from %lux\n", argv0, l, pc);
85 8d82ccef 2020-01-20 rsc for(i=0; i<1000; i++){
86 8d82ccef 2020-01-20 rsc if(!_tas(&l->held))
88 8d82ccef 2020-01-20 rsc usleep(100*1000);
90 8d82ccef 2020-01-20 rsc fprint(2, "%\001 %s: lock loop6 %p from %lux\n", argv0, l, pc);
91 8d82ccef 2020-01-20 rsc /* take your time */
92 8d82ccef 2020-01-20 rsc while(_tas(&l->held))
93 8d82ccef 2020-01-20 rsc usleep(1000*1000);
98 8d82ccef 2020-01-20 rsc * sleep and wakeup
106 8d82ccef 2020-01-20 rsc static void /*__attribute__((constructor))*/
107 8d82ccef 2020-01-20 rsc ignusr1(int restart)
109 8d82ccef 2020-01-20 rsc struct sigaction sa;
111 8d82ccef 2020-01-20 rsc memset(&sa, 0, sizeof sa);
112 8d82ccef 2020-01-20 rsc sa.sa_handler = ign;
113 8d82ccef 2020-01-20 rsc sigemptyset(&sa.sa_mask);
114 8d82ccef 2020-01-20 rsc sigaddset(&sa.sa_mask, SIGUSR1);
116 8d82ccef 2020-01-20 rsc sa.sa_flags = SA_RESTART;
117 8d82ccef 2020-01-20 rsc sigaction(SIGUSR1, &sa, nil);
121 8d82ccef 2020-01-20 rsc _procsleep(_Procrendez *r)
123 8d82ccef 2020-01-20 rsc sigset_t mask;
126 8d82ccef 2020-01-20 rsc * Go to sleep.
128 8d82ccef 2020-01-20 rsc * Block USR1, set the handler to interrupt system calls,
129 8d82ccef 2020-01-20 rsc * unlock the vouslock so our waker can wake us,
130 8d82ccef 2020-01-20 rsc * and then suspend.
133 8d82ccef 2020-01-20 rsc r->asleep = 1;
134 8d82ccef 2020-01-20 rsc r->pid = getpid();
136 8d82ccef 2020-01-20 rsc sigprocmask(SIG_SETMASK, nil, &mask);
137 8d82ccef 2020-01-20 rsc sigaddset(&mask, SIGUSR1);
138 8d82ccef 2020-01-20 rsc sigprocmask(SIG_SETMASK, &mask, nil);
140 8d82ccef 2020-01-20 rsc unlock(r->l);
141 8d82ccef 2020-01-20 rsc sigdelset(&mask, SIGUSR1);
142 8d82ccef 2020-01-20 rsc sigsuspend(&mask);
145 8d82ccef 2020-01-20 rsc * We're awake. Make USR1 not interrupt system calls.
149 8d82ccef 2020-01-20 rsc if(r->asleep && r->pid == getpid()){
150 8d82ccef 2020-01-20 rsc /* Didn't really wake up - signal from something else */
156 8d82ccef 2020-01-20 rsc _procwakeupandunlock(_Procrendez *r)
161 8d82ccef 2020-01-20 rsc if(r->asleep){
162 8d82ccef 2020-01-20 rsc r->asleep = 0;
163 8d82ccef 2020-01-20 rsc assert(r->pid >= 1);
164 8d82ccef 2020-01-20 rsc pid = r->pid;
166 8d82ccef 2020-01-20 rsc assert(r->l);
167 8d82ccef 2020-01-20 rsc unlock(r->l);
169 8d82ccef 2020-01-20 rsc kill(pid, SIGUSR1);
173 8d82ccef 2020-01-20 rsc * process creation and exit
175 8d82ccef 2020-01-20 rsc typedef struct Stackfree Stackfree;
176 8d82ccef 2020-01-20 rsc struct Stackfree
178 8d82ccef 2020-01-20 rsc Stackfree *next;
182 8d82ccef 2020-01-20 rsc static Lock stacklock;
183 8d82ccef 2020-01-20 rsc static Stackfree *stackfree;
186 8d82ccef 2020-01-20 rsc delayfreestack(uchar *stk, int pid, int pid1)
188 8d82ccef 2020-01-20 rsc Stackfree *sf;
190 8d82ccef 2020-01-20 rsc sf = (Stackfree*)stk;
191 8d82ccef 2020-01-20 rsc sf->pid = pid;
192 8d82ccef 2020-01-20 rsc sf->pid1 = pid1;
193 8d82ccef 2020-01-20 rsc lock(&stacklock);
194 8d82ccef 2020-01-20 rsc sf->next = stackfree;
195 8d82ccef 2020-01-20 rsc stackfree = sf;
196 8d82ccef 2020-01-20 rsc unlock(&stacklock);
200 8d82ccef 2020-01-20 rsc dofreestacks(void)
202 8d82ccef 2020-01-20 rsc Stackfree *sf, *last, *next;
204 8d82ccef 2020-01-20 rsc if(stackfree==nil || !canlock(&stacklock))
207 8d82ccef 2020-01-20 rsc for(last=nil,sf=stackfree; sf; last=sf,sf=next){
208 8d82ccef 2020-01-20 rsc next = sf->next;
209 8d82ccef 2020-01-20 rsc if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH)
210 8d82ccef 2020-01-20 rsc if(sf->pid1 >= 1 && kill(sf->pid1, 0) < 0 && errno == ESRCH){
213 8d82ccef 2020-01-20 rsc last->next = next;
215 8d82ccef 2020-01-20 rsc stackfree = next;
219 8d82ccef 2020-01-20 rsc unlock(&stacklock);
223 8d82ccef 2020-01-20 rsc startprocfn(void *v)
227 8d82ccef 2020-01-20 rsc void (*fn)(void*);
229 8d82ccef 2020-01-20 rsc int pid0, pid1;
231 8d82ccef 2020-01-20 rsc a = (void**)v;
235 8d82ccef 2020-01-20 rsc pid0 = (int)a[4];
236 8d82ccef 2020-01-20 rsc pid1 = getpid();
238 8d82ccef 2020-01-20 rsc p->osprocid = pid1;
242 8d82ccef 2020-01-20 rsc delayfreestack(stk, pid0, pid1);
248 8d82ccef 2020-01-20 rsc * indirect through here so that parent need not wait for child zombie
250 8d82ccef 2020-01-20 rsc * slight race - if child exits and then another process starts before we
251 8d82ccef 2020-01-20 rsc * manage to exit, we'll be running on a freed stack.
254 8d82ccef 2020-01-20 rsc trampnowait(void *v)
257 8d82ccef 2020-01-20 rsc int *kidpid;
259 8d82ccef 2020-01-20 rsc a = (void*)v;
260 8d82ccef 2020-01-20 rsc kidpid = a[3];
261 8d82ccef 2020-01-20 rsc a[4] = (void*)getpid();
262 8d82ccef 2020-01-20 rsc *kidpid = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a);
268 8d82ccef 2020-01-20 rsc _procstart(Proc *p, void (*fn)(Proc*))
272 8d82ccef 2020-01-20 rsc int pid, kidpid, status;
274 8d82ccef 2020-01-20 rsc dofreestacks();
275 8d82ccef 2020-01-20 rsc a = malloc(5*sizeof a[0]);
276 8d82ccef 2020-01-20 rsc if(a == nil)
277 8d82ccef 2020-01-20 rsc sysfatal("_procstart malloc: %r");
278 8d82ccef 2020-01-20 rsc stk = malloc(65536);
279 8d82ccef 2020-01-20 rsc if(stk == nil)
280 8d82ccef 2020-01-20 rsc sysfatal("_procstart malloc stack: %r");
285 8d82ccef 2020-01-20 rsc a[3] = &kidpid;
286 8d82ccef 2020-01-20 rsc kidpid = -1;
288 8d82ccef 2020-01-20 rsc pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a);
290 8d82ccef 2020-01-20 rsc if(wait4(pid, &status, __WALL, 0) < 0)
291 8d82ccef 2020-01-20 rsc fprint(2, "ffork wait4: %r\n");
292 8d82ccef 2020-01-20 rsc if(pid < 0 || kidpid < 0){
293 8d82ccef 2020-01-20 rsc fprint(2, "_procstart clone: %r\n");
298 8d82ccef 2020-01-20 rsc static char *threadexitsmsg;
300 8d82ccef 2020-01-20 rsc sigusr2handler(int s)
302 8d82ccef 2020-01-20 rsc /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
303 8d82ccef 2020-01-20 rsc if(threadexitsmsg)
304 8d82ccef 2020-01-20 rsc _exits(threadexitsmsg);
308 8d82ccef 2020-01-20 rsc threadexitsall(char *msg)
310 8d82ccef 2020-01-20 rsc static int pid[1024];
311 8d82ccef 2020-01-20 rsc int i, npid, mypid;
314 8d82ccef 2020-01-20 rsc if(msg == nil)
318 8d82ccef 2020-01-20 rsc * Only one guy, ever, gets to run this.
319 8d82ccef 2020-01-20 rsc * If two guys do it, inevitably they end up
320 8d82ccef 2020-01-20 rsc * tripping over each other in the underlying
321 8d82ccef 2020-01-20 rsc * C library exit() implementation, which is
322 8d82ccef 2020-01-20 rsc * trying to run the atexit handlers and apparently
323 8d82ccef 2020-01-20 rsc * not thread safe. This has been observed on
324 8d82ccef 2020-01-20 rsc * both Linux and OpenBSD. Sigh.
327 8d82ccef 2020-01-20 rsc static Lock onelock;
328 8d82ccef 2020-01-20 rsc if(!canlock(&onelock))
329 8d82ccef 2020-01-20 rsc _exits(threadexitsmsg);
330 8d82ccef 2020-01-20 rsc threadexitsmsg = msg;
333 8d82ccef 2020-01-20 rsc mypid = getpid();
334 8d82ccef 2020-01-20 rsc lock(&_threadprocslock);
336 8d82ccef 2020-01-20 rsc for(p=_threadprocs; p; p=p->next)
337 8d82ccef 2020-01-20 rsc if(p->osprocid != mypid && p->osprocid >= 1)
338 8d82ccef 2020-01-20 rsc pid[npid++] = p->osprocid;
339 8d82ccef 2020-01-20 rsc for(i=0; i<npid; i++)
340 8d82ccef 2020-01-20 rsc kill(pid[i], SIGUSR2);
341 8d82ccef 2020-01-20 rsc unlock(&_threadprocslock);
346 8d82ccef 2020-01-20 rsc * per-process data, indexed by pid
348 8d82ccef 2020-01-20 rsc * could use modify_ldt and a segment register
349 8d82ccef 2020-01-20 rsc * to avoid the many calls to getpid(), but i don't
350 8d82ccef 2020-01-20 rsc * care -- this is compatibility code. linux 2.6 with
351 8d82ccef 2020-01-20 rsc * nptl is a good enough pthreads to avoid this whole file.
353 8d82ccef 2020-01-20 rsc typedef struct Perproc Perproc;
354 8d82ccef 2020-01-20 rsc struct Perproc
360 8d82ccef 2020-01-20 rsc static Lock perlock;
361 8d82ccef 2020-01-20 rsc static Perproc perproc[1024];
362 8d82ccef 2020-01-20 rsc #define P ((Proc*)-1)
364 8d82ccef 2020-01-20 rsc static Perproc*
365 8d82ccef 2020-01-20 rsc myperproc(void)
367 8d82ccef 2020-01-20 rsc int i, pid, h;
370 8d82ccef 2020-01-20 rsc pid = getpid();
371 8d82ccef 2020-01-20 rsc h = pid%nelem(perproc);
372 8d82ccef 2020-01-20 rsc for(i=0; i<nelem(perproc); i++){
373 8d82ccef 2020-01-20 rsc p = &perproc[(i+h)%nelem(perproc)];
374 8d82ccef 2020-01-20 rsc if(p->pid == pid)
376 8d82ccef 2020-01-20 rsc if(p->pid == 0){
377 8d82ccef 2020-01-20 rsc print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
381 8d82ccef 2020-01-20 rsc fprint(2, "myperproc %d (%s): cannot find self\n", pid, argv0);
386 8d82ccef 2020-01-20 rsc static Perproc*
387 8d82ccef 2020-01-20 rsc newperproc(void)
389 8d82ccef 2020-01-20 rsc int i, pid, h;
392 8d82ccef 2020-01-20 rsc lock(&perlock);
393 8d82ccef 2020-01-20 rsc pid = getpid();
394 8d82ccef 2020-01-20 rsc h = pid%nelem(perproc);
395 8d82ccef 2020-01-20 rsc for(i=0; i<nelem(perproc); i++){
396 8d82ccef 2020-01-20 rsc p = &perproc[(i+h)%nelem(perproc)];
397 8d82ccef 2020-01-20 rsc if(p->pid == pid || p->pid == -1 || p->pid == 0){
398 8d82ccef 2020-01-20 rsc p->pid = pid;
399 8d82ccef 2020-01-20 rsc unlock(&perlock);
403 8d82ccef 2020-01-20 rsc fprint(2, "newperproc %d: out of procs\n", pid);
409 8d82ccef 2020-01-20 rsc _threadproc(void)
411 8d82ccef 2020-01-20 rsc return myperproc()->proc;
415 8d82ccef 2020-01-20 rsc _threadsetproc(Proc *p)
417 8d82ccef 2020-01-20 rsc Perproc *pp;
420 8d82ccef 2020-01-20 rsc p->osprocid = getpid();
421 8d82ccef 2020-01-20 rsc pp = newperproc();
422 8d82ccef 2020-01-20 rsc pp->proc = p;
423 8d82ccef 2020-01-20 rsc if(p == nil)
424 8d82ccef 2020-01-20 rsc pp->pid = -1;
428 8d82ccef 2020-01-20 rsc _pthreadinit(void)
430 8d82ccef 2020-01-20 rsc signal(SIGUSR2, sigusr2handler);
434 8d82ccef 2020-01-20 rsc _threadpexit(void)