1 1544f909 2004-12-25 devnull #include "threadimpl.h"
3 b73633b1 2020-12-30 rsc int _threaddebuglevel = 0;
5 1544f909 2004-12-25 devnull static uint threadnproc;
6 1544f909 2004-12-25 devnull static uint threadnsysproc;
7 1544f909 2004-12-25 devnull static Lock threadnproclock;
8 1544f909 2004-12-25 devnull static Ref threadidref;
9 4dbefdd4 2004-12-27 devnull static Proc *threadmainproc;
11 4dbefdd4 2004-12-27 devnull static void addproc(Proc*);
12 4dbefdd4 2004-12-27 devnull static void delproc(Proc*);
13 1544f909 2004-12-25 devnull static void addthread(_Threadlist*, _Thread*);
14 1544f909 2004-12-25 devnull static void delthread(_Threadlist*, _Thread*);
15 df970459 2006-06-26 devnull static int onlist(_Threadlist*, _Thread*);
16 1544f909 2004-12-25 devnull static void addthreadinproc(Proc*, _Thread*);
17 1544f909 2004-12-25 devnull static void delthreadinproc(Proc*, _Thread*);
18 0158bcee 2020-01-12 rsc static void procmain(Proc*);
19 6dde87f8 2005-09-26 devnull static int threadinfo(void*, char*);
20 b73633b1 2020-12-30 rsc static void pthreadscheduler(Proc *p);
21 b73633b1 2020-12-30 rsc static void pthreadsleepschedlocked(Proc *p, _Thread *t);
22 b73633b1 2020-12-30 rsc static void pthreadwakeupschedlocked(Proc *p, _Thread *self, _Thread *t);
23 b73633b1 2020-12-30 rsc static _Thread* procnext(Proc*, _Thread*);
25 2c87dda8 2004-12-28 devnull static void
26 b73633b1 2020-12-30 rsc _threaddebug(_Thread *t, char *fmt, ...)
28 2c87dda8 2004-12-28 devnull va_list arg;
29 2c87dda8 2004-12-28 devnull char buf[128];
31 af89fc10 2005-01-06 devnull static int fd = -1;
33 5b092791 2005-09-26 devnull if(_threaddebuglevel == 0)
36 af89fc10 2005-01-06 devnull if(fd < 0){
37 af89fc10 2005-01-06 devnull p = strrchr(argv0, '/');
41 af89fc10 2005-01-06 devnull p = argv0;
42 af89fc10 2005-01-06 devnull snprint(buf, sizeof buf, "/tmp/%s.tlog", p);
43 af89fc10 2005-01-06 devnull if((fd = create(buf, OWRITE, 0666)) < 0)
44 af89fc10 2005-01-06 devnull fd = open("/dev/null", OWRITE);
45 d93cc14e 2006-06-12 devnull if(fd >= 0 && fd != 2){
46 d93cc14e 2006-06-12 devnull dup(fd, 2);
47 d93cc14e 2006-06-12 devnull close(fd);
52 2c87dda8 2004-12-28 devnull va_start(arg, fmt);
53 2c87dda8 2004-12-28 devnull vsnprint(buf, sizeof buf, fmt, arg);
54 2c87dda8 2004-12-28 devnull va_end(arg);
56 b73633b1 2020-12-30 rsc t = proc()->thread;
58 162d0d5c 2020-05-18 rsc fprint(fd, "%p %d.%d: %s\n", proc(), getpid(), t->id, buf);
60 162d0d5c 2020-05-18 rsc fprint(fd, "%p %d._: %s\n", proc(), getpid(), buf);
63 1544f909 2004-12-25 devnull static _Thread*
64 1544f909 2004-12-25 devnull getthreadnow(void)
66 1544f909 2004-12-25 devnull return proc()->thread;
68 1544f909 2004-12-25 devnull _Thread *(*threadnow)(void) = getthreadnow;
70 1544f909 2004-12-25 devnull static Proc*
71 1544f909 2004-12-25 devnull procalloc(void)
75 1544f909 2004-12-25 devnull p = malloc(sizeof *p);
76 73722a8b 2004-12-27 devnull if(p == nil)
77 73722a8b 2004-12-27 devnull sysfatal("procalloc malloc: %r");
78 1544f909 2004-12-25 devnull memset(p, 0, sizeof *p);
79 4dbefdd4 2004-12-27 devnull addproc(p);
80 1544f909 2004-12-25 devnull lock(&threadnproclock);
81 1544f909 2004-12-25 devnull threadnproc++;
82 1544f909 2004-12-25 devnull unlock(&threadnproclock);
83 1544f909 2004-12-25 devnull return p;
87 18571208 2020-12-30 rsc _threadcreate(Proc *p, void (*fn)(void*), void *arg, uint stack)
89 1544f909 2004-12-25 devnull _Thread *t;
92 8c573cab 2020-01-14 rsc t = malloc(sizeof *t);
93 73722a8b 2004-12-27 devnull if(t == nil)
94 18571208 2020-12-30 rsc sysfatal("threadcreate malloc: %r");
95 1544f909 2004-12-25 devnull memset(t, 0, sizeof *t);
96 1544f909 2004-12-25 devnull t->id = incref(&threadidref);
97 1544f909 2004-12-25 devnull t->startfn = fn;
98 1544f909 2004-12-25 devnull t->startarg = arg;
99 1544f909 2004-12-25 devnull t->proc = p;
100 18571208 2020-12-30 rsc if(p->nthread != 0)
101 18571208 2020-12-30 rsc _threadpthreadstart(p, t);
103 18571208 2020-12-30 rsc t->mainthread = 1;
104 1544f909 2004-12-25 devnull p->nthread++;
105 baef953d 2020-05-18 rsc addthreadinproc(p, t);
106 1544f909 2004-12-25 devnull _threadready(t);
107 1544f909 2004-12-25 devnull return t;
111 1544f909 2004-12-25 devnull threadcreate(void (*fn)(void*), void *arg, uint stack)
113 1544f909 2004-12-25 devnull _Thread *t;
115 1544f909 2004-12-25 devnull t = _threadcreate(proc(), fn, arg, stack);
116 b73633b1 2020-12-30 rsc _threaddebug(nil, "threadcreate %d", t->id);
117 1544f909 2004-12-25 devnull return t->id;
121 1544f909 2004-12-25 devnull proccreate(void (*fn)(void*), void *arg, uint stack)
124 1544f909 2004-12-25 devnull _Thread *t;
125 1544f909 2004-12-25 devnull Proc *p;
127 1544f909 2004-12-25 devnull p = procalloc();
128 1544f909 2004-12-25 devnull t = _threadcreate(p, fn, arg, stack);
129 803292c6 2005-01-18 devnull id = t->id; /* t might be freed after _procstart */
130 b73633b1 2020-12-30 rsc _threaddebug(t, "proccreate %p", p);
131 0158bcee 2020-01-12 rsc _procstart(p, procmain);
132 803292c6 2005-01-18 devnull return id;
136 1544f909 2004-12-25 devnull _threadswitch(void)
138 1544f909 2004-12-25 devnull Proc *p;
140 c8b6342d 2005-01-13 devnull needstack(0);
141 1544f909 2004-12-25 devnull p = proc();
142 cbeb0b26 2006-04-01 devnull /*print("threadswtch %p\n", p); */
143 18571208 2020-12-30 rsc pthreadscheduler(p);
147 1544f909 2004-12-25 devnull _threadready(_Thread *t)
149 1544f909 2004-12-25 devnull Proc *p;
151 1544f909 2004-12-25 devnull p = t->proc;
152 1544f909 2004-12-25 devnull lock(&p->lock);
153 a0a331aa 2005-01-06 devnull p->runrend.l = &p->lock;
154 1544f909 2004-12-25 devnull addthread(&p->runqueue, t);
155 cbeb0b26 2006-04-01 devnull /*print("%d wake for job %d->%d\n", time(0), getpid(), p->osprocid); */
156 8cbd854a 2004-12-27 devnull if(p != proc())
157 a0a331aa 2005-01-06 devnull _procwakeupandunlock(&p->runrend);
159 a0a331aa 2005-01-06 devnull unlock(&p->lock);
163 615e0f9f 2006-02-07 devnull threadidle(void)
166 615e0f9f 2006-02-07 devnull Proc *p;
168 615e0f9f 2006-02-07 devnull p = proc();
169 615e0f9f 2006-02-07 devnull n = p->nswitch;
170 615e0f9f 2006-02-07 devnull lock(&p->lock);
171 615e0f9f 2006-02-07 devnull p->runrend.l = &p->lock;
172 615e0f9f 2006-02-07 devnull addthread(&p->idlequeue, p->thread);
173 615e0f9f 2006-02-07 devnull unlock(&p->lock);
174 615e0f9f 2006-02-07 devnull _threadswitch();
175 615e0f9f 2006-02-07 devnull return p->nswitch - n;
179 1544f909 2004-12-25 devnull threadyield(void)
182 8cbd854a 2004-12-27 devnull Proc *p;
184 8cbd854a 2004-12-27 devnull p = proc();
185 8cbd854a 2004-12-27 devnull n = p->nswitch;
186 8cbd854a 2004-12-27 devnull _threadready(p->thread);
187 1544f909 2004-12-25 devnull _threadswitch();
188 8cbd854a 2004-12-27 devnull return p->nswitch - n;
192 1544f909 2004-12-25 devnull threadexits(char *msg)
194 1544f909 2004-12-25 devnull Proc *p;
196 1544f909 2004-12-25 devnull p = proc();
197 4dbefdd4 2004-12-27 devnull if(msg == nil)
198 4dbefdd4 2004-12-27 devnull msg = "";
199 1544f909 2004-12-25 devnull utfecpy(p->msg, p->msg+sizeof p->msg, msg);
200 4dbefdd4 2004-12-27 devnull proc()->thread->exiting = 1;
201 4dbefdd4 2004-12-27 devnull _threadswitch();
205 df970459 2006-06-26 devnull threadpin(void)
207 df970459 2006-06-26 devnull Proc *p;
209 df970459 2006-06-26 devnull p = proc();
210 df970459 2006-06-26 devnull if(p->pinthread){
211 df970459 2006-06-26 devnull fprint(2, "already pinning a thread - %p %p\n", p->pinthread, p->thread);
212 df970459 2006-06-26 devnull assert(0);
214 df970459 2006-06-26 devnull p->pinthread = p->thread;
218 df970459 2006-06-26 devnull threadunpin(void)
220 df970459 2006-06-26 devnull Proc *p;
222 df970459 2006-06-26 devnull p = proc();
223 df970459 2006-06-26 devnull if(p->pinthread != p->thread){
224 df970459 2006-06-26 devnull fprint(2, "wrong pinthread - %p %p\n", p->pinthread, p->thread);
225 df970459 2006-06-26 devnull assert(0);
227 df970459 2006-06-26 devnull p->pinthread = nil;
231 d19769ae 2008-10-26 rsc threadsysfatal(char *fmt, va_list arg)
233 69d1259c 2008-07-20 devnull char buf[256];
235 69d1259c 2008-07-20 devnull vseprint(buf, buf+sizeof(buf), fmt, arg);
236 69d1259c 2008-07-20 devnull __fixargv0();
237 69d1259c 2008-07-20 devnull fprint(2, "%s: %s\n", argv0 ? argv0 : "<prog>", buf);
238 69d1259c 2008-07-20 devnull threadexitsall(buf);
241 1544f909 2004-12-25 devnull static void
242 0158bcee 2020-01-12 rsc procmain(Proc *p)
246 0158bcee 2020-01-12 rsc _threadsetproc(p);
248 0158bcee 2020-01-12 rsc /* take out first thread to run on system stack */
249 0158bcee 2020-01-12 rsc t = p->runqueue.head;
250 0158bcee 2020-01-12 rsc delthread(&p->runqueue, t);
252 0158bcee 2020-01-12 rsc /* run it */
253 0158bcee 2020-01-12 rsc p->thread = t;
254 0158bcee 2020-01-12 rsc t->startfn(t->startarg);
255 0158bcee 2020-01-12 rsc if(p->nthread != 0)
256 0158bcee 2020-01-12 rsc threadexits(nil);
260 baef953d 2020-05-18 rsc _threadpthreadmain(Proc *p, _Thread *t)
262 baef953d 2020-05-18 rsc _threadsetproc(p);
263 b73633b1 2020-12-30 rsc lock(&p->lock);
264 b73633b1 2020-12-30 rsc pthreadsleepschedlocked(p, t);
265 b73633b1 2020-12-30 rsc unlock(&p->lock);
266 b73633b1 2020-12-30 rsc _threaddebug(nil, "startfn");
267 baef953d 2020-05-18 rsc t->startfn(t->startarg);
268 baef953d 2020-05-18 rsc threadexits(nil);
272 b73633b1 2020-12-30 rsc pthreadsleepschedlocked(Proc *p, _Thread *t)
274 b73633b1 2020-12-30 rsc _threaddebug(t, "pthreadsleepsched %p %d", p, t->id);;
275 b73633b1 2020-12-30 rsc t->schedrend.l = &p->lock;
276 b73633b1 2020-12-30 rsc while(p->schedthread != t)
277 b73633b1 2020-12-30 rsc _procsleep(&t->schedrend);
281 b73633b1 2020-12-30 rsc pthreadwakeupschedlocked(Proc *p, _Thread *self, _Thread *t)
283 b73633b1 2020-12-30 rsc _threaddebug(self, "pthreadwakeupschedlocked %p %d", p, t->id);;
284 91ececc9 2020-12-30 rsc t->schedrend.l = &p->lock;
285 b73633b1 2020-12-30 rsc p->schedthread = t;
286 b73633b1 2020-12-30 rsc _procwakeup(&t->schedrend);
290 b73633b1 2020-12-30 rsc pthreadscheduler(Proc *p)
292 b73633b1 2020-12-30 rsc _Thread *self, *t;
294 b73633b1 2020-12-30 rsc _threaddebug(nil, "scheduler");
295 b73633b1 2020-12-30 rsc lock(&p->lock);
296 b73633b1 2020-12-30 rsc self = p->thread;
297 b73633b1 2020-12-30 rsc p->thread = nil;
298 b73633b1 2020-12-30 rsc _threaddebug(self, "pausing");
300 b73633b1 2020-12-30 rsc if(self->exiting) {
301 b73633b1 2020-12-30 rsc _threaddebug(self, "exiting");
302 b73633b1 2020-12-30 rsc delthreadinproc(p, self);
303 b73633b1 2020-12-30 rsc p->nthread--;
306 b73633b1 2020-12-30 rsc t = procnext(p, self);
307 b73633b1 2020-12-30 rsc if(t != nil) {
308 b73633b1 2020-12-30 rsc pthreadwakeupschedlocked(p, self, t);
309 b73633b1 2020-12-30 rsc if(!self->exiting) {
310 b73633b1 2020-12-30 rsc pthreadsleepschedlocked(p, self);
311 b73633b1 2020-12-30 rsc _threaddebug(nil, "resume %d", self->id);
312 b73633b1 2020-12-30 rsc unlock(&p->lock);
317 b73633b1 2020-12-30 rsc if(t == nil) {
318 b73633b1 2020-12-30 rsc /* Tear down proc bookkeeping. Wait to free p. */
320 b73633b1 2020-12-30 rsc lock(&threadnproclock);
321 b73633b1 2020-12-30 rsc if(p->sysproc)
322 b73633b1 2020-12-30 rsc --threadnsysproc;
323 b73633b1 2020-12-30 rsc if(--threadnproc == threadnsysproc)
324 b73633b1 2020-12-30 rsc threadexitsall(p->msg);
325 b73633b1 2020-12-30 rsc unlock(&threadnproclock);
328 b73633b1 2020-12-30 rsc /* Tear down pthread. */
329 b73633b1 2020-12-30 rsc if(self->mainthread && p->mainproc) {
330 b73633b1 2020-12-30 rsc _threaddaemonize();
331 b73633b1 2020-12-30 rsc _threaddebug(self, "sleeper");
332 b73633b1 2020-12-30 rsc unlock(&p->lock);
334 b73633b1 2020-12-30 rsc * Avoid bugs with main pthread exiting.
335 b73633b1 2020-12-30 rsc * When all procs are gone, threadexitsall above will happen.
338 b73633b1 2020-12-30 rsc sleep(60*60*1000);
340 b73633b1 2020-12-30 rsc _threadsetproc(nil);
342 b73633b1 2020-12-30 rsc unlock(&p->lock);
343 b73633b1 2020-12-30 rsc if(t == nil)
345 481b596d 2020-01-14 rsc _threadpexit();
348 b73633b1 2020-12-30 rsc static _Thread*
349 b73633b1 2020-12-30 rsc procnext(Proc *p, _Thread *self)
353 b73633b1 2020-12-30 rsc if((t = p->pinthread) != nil){
354 b73633b1 2020-12-30 rsc while(!onlist(&p->runqueue, t)){
355 b73633b1 2020-12-30 rsc p->runrend.l = &p->lock;
356 b73633b1 2020-12-30 rsc _threaddebug(self, "scheduler sleep (pin)");
357 b73633b1 2020-12-30 rsc _procsleep(&p->runrend);
358 b73633b1 2020-12-30 rsc _threaddebug(self, "scheduler wake (pin)");
361 b73633b1 2020-12-30 rsc while((t = p->runqueue.head) == nil){
362 b73633b1 2020-12-30 rsc if(p->nthread == 0)
364 b73633b1 2020-12-30 rsc if((t = p->idlequeue.head) != nil){
366 b73633b1 2020-12-30 rsc * Run all the idling threads once.
368 b73633b1 2020-12-30 rsc while((t = p->idlequeue.head) != nil){
369 b73633b1 2020-12-30 rsc delthread(&p->idlequeue, t);
370 b73633b1 2020-12-30 rsc addthread(&p->runqueue, t);
374 b73633b1 2020-12-30 rsc p->runrend.l = &p->lock;
375 b73633b1 2020-12-30 rsc _threaddebug(self, "scheduler sleep");
376 b73633b1 2020-12-30 rsc _procsleep(&p->runrend);
377 b73633b1 2020-12-30 rsc _threaddebug(self, "scheduler wake");
380 b73633b1 2020-12-30 rsc if(p->pinthread && p->pinthread != t)
381 b73633b1 2020-12-30 rsc fprint(2, "p->pinthread %p t %p\n", p->pinthread, t);
382 b73633b1 2020-12-30 rsc assert(p->pinthread == nil || p->pinthread == t);
383 b73633b1 2020-12-30 rsc delthread(&p->runqueue, t);
385 b73633b1 2020-12-30 rsc p->thread = t;
386 b73633b1 2020-12-30 rsc p->nswitch++;
391 1544f909 2004-12-25 devnull _threadsetsysproc(void)
393 1544f909 2004-12-25 devnull lock(&threadnproclock);
394 1544f909 2004-12-25 devnull if(++threadnsysproc == threadnproc)
395 8ee6ad4d 2005-02-14 devnull threadexitsall(nil);
396 1544f909 2004-12-25 devnull unlock(&threadnproclock);
397 1544f909 2004-12-25 devnull proc()->sysproc = 1;
401 4dbefdd4 2004-12-27 devnull procdata(void)
403 4dbefdd4 2004-12-27 devnull return &proc()->udata;
407 8dd8a81f 2005-03-18 devnull threaddata(void)
409 8dd8a81f 2005-03-18 devnull return &proc()->thread->udata;
412 4dbefdd4 2004-12-27 devnull extern Jmp *(*_notejmpbuf)(void);
413 4dbefdd4 2004-12-27 devnull static Jmp*
414 4dbefdd4 2004-12-27 devnull threadnotejmp(void)
416 4dbefdd4 2004-12-27 devnull return &proc()->sigjmp;
420 1544f909 2004-12-25 devnull * debugging
423 1544f909 2004-12-25 devnull threadsetname(char *fmt, ...)
425 1544f909 2004-12-25 devnull va_list arg;
426 1544f909 2004-12-25 devnull _Thread *t;
428 1544f909 2004-12-25 devnull t = proc()->thread;
429 1544f909 2004-12-25 devnull va_start(arg, fmt);
430 1544f909 2004-12-25 devnull vsnprint(t->name, sizeof t->name, fmt, arg);
431 1544f909 2004-12-25 devnull va_end(arg);
435 515b6e5b 2005-01-18 devnull threadgetname(void)
437 515b6e5b 2005-01-18 devnull return proc()->thread->name;
441 1544f909 2004-12-25 devnull threadsetstate(char *fmt, ...)
443 1544f909 2004-12-25 devnull va_list arg;
444 1544f909 2004-12-25 devnull _Thread *t;
446 1544f909 2004-12-25 devnull t = proc()->thread;
447 1544f909 2004-12-25 devnull va_start(arg, fmt);
448 1544f909 2004-12-25 devnull vsnprint(t->state, sizeof t->name, fmt, arg);
449 1544f909 2004-12-25 devnull va_end(arg);
453 9eda38e5 2006-02-05 devnull threadid(void)
455 9eda38e5 2006-02-05 devnull _Thread *t;
457 9eda38e5 2006-02-05 devnull t = proc()->thread;
458 9eda38e5 2006-02-05 devnull return t->id;
462 c8b6342d 2005-01-13 devnull needstack(int n)
464 c8b6342d 2005-01-13 devnull _Thread *t;
466 c8b6342d 2005-01-13 devnull t = proc()->thread;
467 8c573cab 2020-01-14 rsc if(t->stk == nil)
470 c8b6342d 2005-01-13 devnull if((char*)&t <= (char*)t->stk
471 c8b6342d 2005-01-13 devnull || (char*)&t - (char*)t->stk < 256+n){
472 1fdb4a54 2005-01-23 devnull fprint(2, "thread stack overflow: &t=%p tstk=%p n=%d\n", &t, t->stk, 256+n);
473 c8b6342d 2005-01-13 devnull abort();
478 faf1fb6c 2008-07-09 rsc singlethreaded(void)
480 faf1fb6c 2008-07-09 rsc return threadnproc == 1 && _threadprocs->nthread == 1;
484 1544f909 2004-12-25 devnull * locking
486 1544f909 2004-12-25 devnull static int
487 1544f909 2004-12-25 devnull threadqlock(QLock *l, int block, ulong pc)
489 cbeb0b26 2006-04-01 devnull /*print("threadqlock %p\n", l); */
490 1544f909 2004-12-25 devnull lock(&l->l);
491 1544f909 2004-12-25 devnull if(l->owner == nil){
492 1544f909 2004-12-25 devnull l->owner = (*threadnow)();
493 cbeb0b26 2006-04-01 devnull /*print("qlock %p @%#x by %p\n", l, pc, l->owner); */
494 162d0d5c 2020-05-18 rsc if(l->owner == nil) {
495 162d0d5c 2020-05-18 rsc fprint(2, "%s: qlock uncontended owner=nil oops\n", argv0);
498 1544f909 2004-12-25 devnull unlock(&l->l);
499 1544f909 2004-12-25 devnull return 1;
501 1544f909 2004-12-25 devnull if(!block){
502 1544f909 2004-12-25 devnull unlock(&l->l);
503 1544f909 2004-12-25 devnull return 0;
506 faf1fb6c 2008-07-09 rsc if(singlethreaded()){
507 faf1fb6c 2008-07-09 rsc fprint(2, "qlock deadlock\n");
511 cbeb0b26 2006-04-01 devnull /*print("qsleep %p @%#x by %p\n", l, pc, (*threadnow)()); */
512 1544f909 2004-12-25 devnull addthread(&l->waiting, (*threadnow)());
513 1544f909 2004-12-25 devnull unlock(&l->l);
515 1544f909 2004-12-25 devnull _threadswitch();
517 1544f909 2004-12-25 devnull if(l->owner != (*threadnow)()){
518 15cd8255 2005-01-04 devnull fprint(2, "%s: qlock pc=0x%lux owner=%p self=%p oops\n",
519 15cd8255 2005-01-04 devnull argv0, pc, l->owner, (*threadnow)());
520 1544f909 2004-12-25 devnull abort();
522 162d0d5c 2020-05-18 rsc if(l->owner == nil) {
523 162d0d5c 2020-05-18 rsc fprint(2, "%s: qlock threadswitch owner=nil oops\n", argv0);
527 cbeb0b26 2006-04-01 devnull /*print("qlock wakeup %p @%#x by %p\n", l, pc, (*threadnow)()); */
528 1544f909 2004-12-25 devnull return 1;
531 1544f909 2004-12-25 devnull static void
532 1544f909 2004-12-25 devnull threadqunlock(QLock *l, ulong pc)
534 80b8842f 2005-02-15 devnull _Thread *ready;
536 1544f909 2004-12-25 devnull lock(&l->l);
537 cbeb0b26 2006-04-01 devnull /*print("qlock unlock %p @%#x by %p (owner %p)\n", l, pc, (*threadnow)(), l->owner); */
538 1aa9c533 2005-01-07 devnull if(l->owner == 0){
539 15cd8255 2005-01-04 devnull fprint(2, "%s: qunlock pc=0x%lux owner=%p self=%p oops\n",
540 15cd8255 2005-01-04 devnull argv0, pc, l->owner, (*threadnow)());
541 1aa9c533 2005-01-07 devnull abort();
543 80b8842f 2005-02-15 devnull if((l->owner = ready = l->waiting.head) != nil)
544 1544f909 2004-12-25 devnull delthread(&l->waiting, l->owner);
546 80b8842f 2005-02-15 devnull * N.B. Cannot call _threadready() before unlocking l->l,
547 80b8842f 2005-02-15 devnull * because the thread we are readying might:
548 80b8842f 2005-02-15 devnull * - be in another proc
549 80b8842f 2005-02-15 devnull * - start running immediately
550 80b8842f 2005-02-15 devnull * - and free l before we get a chance to run again
552 1544f909 2004-12-25 devnull unlock(&l->l);
553 80b8842f 2005-02-15 devnull if(ready)
554 80b8842f 2005-02-15 devnull _threadready(l->owner);
557 1544f909 2004-12-25 devnull static int
558 1544f909 2004-12-25 devnull threadrlock(RWLock *l, int block, ulong pc)
560 1544f909 2004-12-25 devnull USED(pc);
562 1544f909 2004-12-25 devnull lock(&l->l);
563 1544f909 2004-12-25 devnull if(l->writer == nil && l->wwaiting.head == nil){
564 1544f909 2004-12-25 devnull l->readers++;
565 1544f909 2004-12-25 devnull unlock(&l->l);
566 1544f909 2004-12-25 devnull return 1;
568 1544f909 2004-12-25 devnull if(!block){
569 1544f909 2004-12-25 devnull unlock(&l->l);
570 1544f909 2004-12-25 devnull return 0;
572 faf1fb6c 2008-07-09 rsc if(singlethreaded()){
573 faf1fb6c 2008-07-09 rsc fprint(2, "rlock deadlock\n");
576 1544f909 2004-12-25 devnull addthread(&l->rwaiting, (*threadnow)());
577 1544f909 2004-12-25 devnull unlock(&l->l);
578 1544f909 2004-12-25 devnull _threadswitch();
582 1544f909 2004-12-25 devnull static int
583 1544f909 2004-12-25 devnull threadwlock(RWLock *l, int block, ulong pc)
585 1544f909 2004-12-25 devnull USED(pc);
587 1544f909 2004-12-25 devnull lock(&l->l);
588 1544f909 2004-12-25 devnull if(l->writer == nil && l->readers == 0){
589 1544f909 2004-12-25 devnull l->writer = (*threadnow)();
590 1544f909 2004-12-25 devnull unlock(&l->l);
591 1544f909 2004-12-25 devnull return 1;
593 1544f909 2004-12-25 devnull if(!block){
594 1544f909 2004-12-25 devnull unlock(&l->l);
595 1544f909 2004-12-25 devnull return 0;
597 faf1fb6c 2008-07-09 rsc if(singlethreaded()){
598 faf1fb6c 2008-07-09 rsc fprint(2, "wlock deadlock\n");
601 1544f909 2004-12-25 devnull addthread(&l->wwaiting, (*threadnow)());
602 1544f909 2004-12-25 devnull unlock(&l->l);
603 1544f909 2004-12-25 devnull _threadswitch();
604 1544f909 2004-12-25 devnull return 1;
607 1544f909 2004-12-25 devnull static void
608 1544f909 2004-12-25 devnull threadrunlock(RWLock *l, ulong pc)
610 1544f909 2004-12-25 devnull _Thread *t;
612 1544f909 2004-12-25 devnull USED(pc);
613 80b8842f 2005-02-15 devnull t = nil;
614 1544f909 2004-12-25 devnull lock(&l->l);
615 1544f909 2004-12-25 devnull --l->readers;
616 1544f909 2004-12-25 devnull if(l->readers == 0 && (t = l->wwaiting.head) != nil){
617 1544f909 2004-12-25 devnull delthread(&l->wwaiting, t);
618 1544f909 2004-12-25 devnull l->writer = t;
620 1544f909 2004-12-25 devnull unlock(&l->l);
622 80b8842f 2005-02-15 devnull _threadready(t);
626 1544f909 2004-12-25 devnull static void
627 1544f909 2004-12-25 devnull threadwunlock(RWLock *l, ulong pc)
629 1544f909 2004-12-25 devnull _Thread *t;
631 1544f909 2004-12-25 devnull USED(pc);
632 1544f909 2004-12-25 devnull lock(&l->l);
633 1544f909 2004-12-25 devnull l->writer = nil;
634 1544f909 2004-12-25 devnull assert(l->readers == 0);
635 1544f909 2004-12-25 devnull while((t = l->rwaiting.head) != nil){
636 1544f909 2004-12-25 devnull delthread(&l->rwaiting, t);
637 1544f909 2004-12-25 devnull l->readers++;
638 1544f909 2004-12-25 devnull _threadready(t);
640 80b8842f 2005-02-15 devnull t = nil;
641 1544f909 2004-12-25 devnull if(l->readers == 0 && (t = l->wwaiting.head) != nil){
642 1544f909 2004-12-25 devnull delthread(&l->wwaiting, t);
643 1544f909 2004-12-25 devnull l->writer = t;
645 1544f909 2004-12-25 devnull unlock(&l->l);
647 80b8842f 2005-02-15 devnull _threadready(t);
651 1544f909 2004-12-25 devnull * sleep and wakeup
653 1544f909 2004-12-25 devnull static void
654 1544f909 2004-12-25 devnull threadrsleep(Rendez *r, ulong pc)
656 faf1fb6c 2008-07-09 rsc if(singlethreaded()){
657 faf1fb6c 2008-07-09 rsc fprint(2, "rsleep deadlock\n");
660 1544f909 2004-12-25 devnull addthread(&r->waiting, proc()->thread);
661 1544f909 2004-12-25 devnull qunlock(r->l);
662 1544f909 2004-12-25 devnull _threadswitch();
663 1544f909 2004-12-25 devnull qlock(r->l);
666 1544f909 2004-12-25 devnull static int
667 1544f909 2004-12-25 devnull threadrwakeup(Rendez *r, int all, ulong pc)
670 1544f909 2004-12-25 devnull _Thread *t;
672 b73633b1 2020-12-30 rsc _threaddebug(nil, "rwakeup %p %d", r, all);
673 1544f909 2004-12-25 devnull for(i=0;; i++){
674 1544f909 2004-12-25 devnull if(i==1 && !all)
676 1544f909 2004-12-25 devnull if((t = r->waiting.head) == nil)
678 b73633b1 2020-12-30 rsc _threaddebug(nil, "rwakeup %p %d -> wake %d", r, all, t->id);
679 1544f909 2004-12-25 devnull delthread(&r->waiting, t);
680 fa325e9b 2020-01-10 cross _threadready(t);
681 b73633b1 2020-12-30 rsc _threaddebug(nil, "rwakeup %p %d -> loop", r, all);
683 b73633b1 2020-12-30 rsc _threaddebug(nil, "rwakeup %p %d -> total %d", r, all, i);
684 1544f909 2004-12-25 devnull return i;
688 4dbefdd4 2004-12-27 devnull * startup
691 4dbefdd4 2004-12-27 devnull static int threadargc;
692 4dbefdd4 2004-12-27 devnull static char **threadargv;
693 4dbefdd4 2004-12-27 devnull int mainstacksize;
694 d93cc14e 2006-06-12 devnull extern int _p9usepwlibrary; /* getgrgid etc. smash the stack - tell _p9dir just say no */
695 4dbefdd4 2004-12-27 devnull static void
696 4dbefdd4 2004-12-27 devnull threadmainstart(void *v)
698 4dbefdd4 2004-12-27 devnull USED(v);
701 0b561695 2005-01-16 devnull * N.B. This call to proc() is a program's first call (indirectly) to a
702 0b561695 2005-01-16 devnull * pthreads function while executing on a non-pthreads-allocated
703 0b561695 2005-01-16 devnull * stack. If the pthreads implementation is using the stack pointer
704 0b561695 2005-01-16 devnull * to locate the per-thread data, then this call will blow up.
705 0b561695 2005-01-16 devnull * This means the pthread implementation is not suitable for
706 0b561695 2005-01-16 devnull * running under libthread. Time to write your own. Sorry.
708 d93cc14e 2006-06-12 devnull _p9usepwlibrary = 0;
709 4dbefdd4 2004-12-27 devnull threadmainproc = proc();
710 4dbefdd4 2004-12-27 devnull threadmain(threadargc, threadargv);
713 d19769ae 2008-10-26 rsc extern void (*_sysfatal)(char*, va_list);
716 4dbefdd4 2004-12-27 devnull main(int argc, char **argv)
718 4dbefdd4 2004-12-27 devnull Proc *p;
722 1d2533d0 2004-12-28 devnull argv0 = argv[0];
724 baef953d 2020-05-18 rsc opts = getenv("LIBTHREAD");
725 baef953d 2020-05-18 rsc if(opts == nil)
728 b3a20a96 2020-12-30 rsc if(threadmaybackground() && strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil)
729 615e0f9f 2006-02-07 devnull _threadsetupdaemonize();
731 4dbefdd4 2004-12-27 devnull threadargc = argc;
732 4dbefdd4 2004-12-27 devnull threadargv = argv;
735 4dbefdd4 2004-12-27 devnull * Install locking routines into C library.
737 4dbefdd4 2004-12-27 devnull _lock = _threadlock;
738 4dbefdd4 2004-12-27 devnull _unlock = _threadunlock;
739 4dbefdd4 2004-12-27 devnull _qlock = threadqlock;
740 4dbefdd4 2004-12-27 devnull _qunlock = threadqunlock;
741 4dbefdd4 2004-12-27 devnull _rlock = threadrlock;
742 4dbefdd4 2004-12-27 devnull _runlock = threadrunlock;
743 4dbefdd4 2004-12-27 devnull _wlock = threadwlock;
744 4dbefdd4 2004-12-27 devnull _wunlock = threadwunlock;
745 4dbefdd4 2004-12-27 devnull _rsleep = threadrsleep;
746 4dbefdd4 2004-12-27 devnull _rwakeup = threadrwakeup;
747 4dbefdd4 2004-12-27 devnull _notejmpbuf = threadnotejmp;
748 df970459 2006-06-26 devnull _pin = threadpin;
749 df970459 2006-06-26 devnull _unpin = threadunpin;
750 69d1259c 2008-07-20 devnull _sysfatal = threadsysfatal;
752 4dbefdd4 2004-12-27 devnull _pthreadinit();
753 4dbefdd4 2004-12-27 devnull p = procalloc();
754 8ee6ad4d 2005-02-14 devnull p->mainproc = 1;
755 4dbefdd4 2004-12-27 devnull _threadsetproc(p);
756 4dbefdd4 2004-12-27 devnull if(mainstacksize == 0)
757 a0e8d02d 2005-01-23 devnull mainstacksize = 256*1024;
758 af6e459f 2006-04-21 devnull atnotify(threadinfo, 1);
759 b73633b1 2020-12-30 rsc t = _threadcreate(p, threadmainstart, nil, mainstacksize);
760 b73633b1 2020-12-30 rsc t->mainthread = 1;
761 0158bcee 2020-01-12 rsc procmain(p);
762 18571208 2020-12-30 rsc sysfatal("procmain returned in libthread");
763 8ee6ad4d 2005-02-14 devnull /* does not return */
764 15cd8255 2005-01-04 devnull return 0;
768 1544f909 2004-12-25 devnull * hooray for linked lists
770 1544f909 2004-12-25 devnull static void
771 1544f909 2004-12-25 devnull addthread(_Threadlist *l, _Thread *t)
773 1544f909 2004-12-25 devnull if(l->tail){
774 1544f909 2004-12-25 devnull l->tail->next = t;
775 1544f909 2004-12-25 devnull t->prev = l->tail;
777 1544f909 2004-12-25 devnull l->head = t;
778 1544f909 2004-12-25 devnull t->prev = nil;
780 1544f909 2004-12-25 devnull l->tail = t;
781 1544f909 2004-12-25 devnull t->next = nil;
784 1544f909 2004-12-25 devnull static void
785 1544f909 2004-12-25 devnull delthread(_Threadlist *l, _Thread *t)
787 1544f909 2004-12-25 devnull if(t->prev)
788 1544f909 2004-12-25 devnull t->prev->next = t->next;
790 1544f909 2004-12-25 devnull l->head = t->next;
791 1544f909 2004-12-25 devnull if(t->next)
792 1544f909 2004-12-25 devnull t->next->prev = t->prev;
794 1544f909 2004-12-25 devnull l->tail = t->prev;
797 df970459 2006-06-26 devnull /* inefficient but rarely used */
798 df970459 2006-06-26 devnull static int
799 df970459 2006-06-26 devnull onlist(_Threadlist *l, _Thread *t)
801 df970459 2006-06-26 devnull _Thread *tt;
803 df970459 2006-06-26 devnull for(tt = l->head; tt; tt=tt->next)
804 df970459 2006-06-26 devnull if(tt == t)
805 df970459 2006-06-26 devnull return 1;
806 df970459 2006-06-26 devnull return 0;
809 1544f909 2004-12-25 devnull static void
810 1544f909 2004-12-25 devnull addthreadinproc(Proc *p, _Thread *t)
812 1544f909 2004-12-25 devnull _Threadlist *l;
814 1544f909 2004-12-25 devnull l = &p->allthreads;
815 1544f909 2004-12-25 devnull if(l->tail){
816 1544f909 2004-12-25 devnull l->tail->allnext = t;
817 1544f909 2004-12-25 devnull t->allprev = l->tail;
819 1544f909 2004-12-25 devnull l->head = t;
820 1544f909 2004-12-25 devnull t->allprev = nil;
822 1544f909 2004-12-25 devnull l->tail = t;
823 1544f909 2004-12-25 devnull t->allnext = nil;
826 1544f909 2004-12-25 devnull static void
827 1544f909 2004-12-25 devnull delthreadinproc(Proc *p, _Thread *t)
829 1544f909 2004-12-25 devnull _Threadlist *l;
831 1544f909 2004-12-25 devnull l = &p->allthreads;
832 1544f909 2004-12-25 devnull if(t->allprev)
833 1544f909 2004-12-25 devnull t->allprev->allnext = t->allnext;
835 1544f909 2004-12-25 devnull l->head = t->allnext;
836 1544f909 2004-12-25 devnull if(t->allnext)
837 1544f909 2004-12-25 devnull t->allnext->allprev = t->allprev;
839 1544f909 2004-12-25 devnull l->tail = t->allprev;
842 4dbefdd4 2004-12-27 devnull Proc *_threadprocs;
843 4dbefdd4 2004-12-27 devnull Lock _threadprocslock;
844 4dbefdd4 2004-12-27 devnull static Proc *_threadprocstail;
846 1544f909 2004-12-25 devnull static void
847 4dbefdd4 2004-12-27 devnull addproc(Proc *p)
849 4dbefdd4 2004-12-27 devnull lock(&_threadprocslock);
850 4dbefdd4 2004-12-27 devnull if(_threadprocstail){
851 4dbefdd4 2004-12-27 devnull _threadprocstail->next = p;
852 4dbefdd4 2004-12-27 devnull p->prev = _threadprocstail;
854 4dbefdd4 2004-12-27 devnull _threadprocs = p;
855 4dbefdd4 2004-12-27 devnull p->prev = nil;
857 4dbefdd4 2004-12-27 devnull _threadprocstail = p;
858 4dbefdd4 2004-12-27 devnull p->next = nil;
859 4dbefdd4 2004-12-27 devnull unlock(&_threadprocslock);
862 4dbefdd4 2004-12-27 devnull static void
863 4dbefdd4 2004-12-27 devnull delproc(Proc *p)
865 4dbefdd4 2004-12-27 devnull lock(&_threadprocslock);
866 4dbefdd4 2004-12-27 devnull if(p->prev)
867 4dbefdd4 2004-12-27 devnull p->prev->next = p->next;
869 4dbefdd4 2004-12-27 devnull _threadprocs = p->next;
870 4dbefdd4 2004-12-27 devnull if(p->next)
871 4dbefdd4 2004-12-27 devnull p->next->prev = p->prev;
873 4dbefdd4 2004-12-27 devnull _threadprocstail = p->prev;
874 4dbefdd4 2004-12-27 devnull unlock(&_threadprocslock);
878 15cd8255 2005-01-04 devnull * notify - for now just use the usual mechanisms
881 15cd8255 2005-01-04 devnull threadnotify(int (*f)(void*, char*), int in)
883 15cd8255 2005-01-04 devnull atnotify(f, in);
886 6dde87f8 2005-09-26 devnull static int
887 6dde87f8 2005-09-26 devnull onrunqueue(Proc *p, _Thread *t)
889 6dde87f8 2005-09-26 devnull _Thread *tt;
891 6dde87f8 2005-09-26 devnull for(tt=p->runqueue.head; tt; tt=tt->next)
892 6dde87f8 2005-09-26 devnull if(tt == t)
893 6dde87f8 2005-09-26 devnull return 1;
894 6dde87f8 2005-09-26 devnull return 0;
898 6dde87f8 2005-09-26 devnull * print state - called from SIGINFO
900 6dde87f8 2005-09-26 devnull static int
901 6dde87f8 2005-09-26 devnull threadinfo(void *v, char *s)
903 6dde87f8 2005-09-26 devnull Proc *p;
904 6dde87f8 2005-09-26 devnull _Thread *t;
906 6dde87f8 2005-09-26 devnull if(strcmp(s, "quit") != 0 && strcmp(s, "sys: status request") != 0)
907 6dde87f8 2005-09-26 devnull return 0;
909 6dde87f8 2005-09-26 devnull for(p=_threadprocs; p; p=p->next){
910 6dde87f8 2005-09-26 devnull fprint(2, "proc %p %s%s\n", (void*)p->osprocid, p->msg,
911 6dde87f8 2005-09-26 devnull p->sysproc ? " (sysproc)": "");
912 6dde87f8 2005-09-26 devnull for(t=p->allthreads.head; t; t=t->allnext){
913 fa325e9b 2020-01-10 cross fprint(2, "\tthread %d %s: %s %s\n",
915 fa325e9b 2020-01-10 cross t == p->thread ? "Running" :
916 6dde87f8 2005-09-26 devnull onrunqueue(p, t) ? "Ready" : "Sleeping",
917 6dde87f8 2005-09-26 devnull t->state, t->name);
920 6dde87f8 2005-09-26 devnull return 1;