xref: /plan9/sys/src/libthread/exit.c (revision d1be6b086622eecc0da76db1fbd64349a5e85293)
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "threadimpl.h"
5 #include <tos.h>
6 
7 char *_threadexitsallstatus;
8 Channel *_threadwaitchan;
9 
10 void
threadexits(char * exitstr)11 threadexits(char *exitstr)
12 {
13 	Proc *p;
14 	Thread *t;
15 
16 	p = _threadgetproc();
17 	t = p->thread;
18 	t->moribund = 1;
19 	if(exitstr==nil)
20 		exitstr="";
21 	utfecpy(p->exitstr, p->exitstr+ERRMAX, exitstr);
22 	_sched();
23 }
24 
25 void
threadexitsall(char * exitstr)26 threadexitsall(char *exitstr)
27 {
28 	Proc *p;
29 	int pid[64];
30 	int i, npid, mypid;
31 
32 	if(exitstr == nil)
33 		exitstr = "";
34 	_threadexitsallstatus = exitstr;
35 	_threaddebug(DBGSCHED, "_threadexitsallstatus set to %p", _threadexitsallstatus);
36 	mypid = _tos->pid; //getpid();
37 
38 	/*
39 	 * signal others.
40 	 * copying all the pids first avoids other threads
41 	 * teardown procedures getting in the way.
42 	 *
43 	 * avoid mallocs since malloc can post a note which can
44 	 * call threadexitsall...
45 	 */
46 	for(;;){
47 		lock(&_threadpq.lock);
48 		npid = 0;
49 		for(p = _threadpq.head; p && npid < nelem(pid); p=p->next){
50 			if(p->threadint == 0 && p->pid != mypid){
51 				pid[npid++] = p->pid;
52 				p->threadint = 1;
53 			}
54 		}
55 		unlock(&_threadpq.lock);
56 		if(npid == 0)
57 			break;
58 		for(i=0; i<npid; i++)
59 			postnote(PNPROC, pid[i], "threadint");
60 	}
61 
62 	/* leave */
63 	exits(exitstr);
64 }
65 
66 Channel*
threadwaitchan(void)67 threadwaitchan(void)
68 {
69 	if(_threadwaitchan==nil)
70 		_threadwaitchan = chancreate(sizeof(Waitmsg*), 16);
71 	return _threadwaitchan;
72 }
73