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