xref: /plan9/sys/src/libthread/exit.c (revision dc5a79c1208f0704eeb474acc990728f8b4854f5)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <thread.h>
49a747e4fSDavid du Colombier #include "threadimpl.h"
59a747e4fSDavid du Colombier 
69a747e4fSDavid du Colombier char *_threadexitsallstatus;
79a747e4fSDavid du Colombier Channel *_threadwaitchan;
89a747e4fSDavid du Colombier 
99a747e4fSDavid du Colombier void
109a747e4fSDavid du Colombier threadexits(char *exitstr)
119a747e4fSDavid du Colombier {
129a747e4fSDavid du Colombier 	Proc *p;
139a747e4fSDavid du Colombier 	Thread *t;
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier 	p = _threadgetproc();
169a747e4fSDavid du Colombier 	t = p->thread;
179a747e4fSDavid du Colombier 	t->moribund = 1;
189a747e4fSDavid du Colombier 	if(exitstr==nil)
199a747e4fSDavid du Colombier 		exitstr="";
209a747e4fSDavid du Colombier 	utfecpy(p->exitstr, p->exitstr+ERRMAX, exitstr);
219a747e4fSDavid du Colombier 	_sched();
229a747e4fSDavid du Colombier }
239a747e4fSDavid du Colombier 
249a747e4fSDavid du Colombier void
259a747e4fSDavid du Colombier threadexitsall(char *exitstr)
269a747e4fSDavid du Colombier {
279a747e4fSDavid du Colombier 	Proc *p;
28*dc5a79c1SDavid du Colombier 	int pid[64];
299a747e4fSDavid du Colombier 	int i, npid, mypid;
309a747e4fSDavid du Colombier 
319a747e4fSDavid du Colombier 	if(exitstr == nil)
329a747e4fSDavid du Colombier 		exitstr = "";
339a747e4fSDavid du Colombier 	_threadexitsallstatus = exitstr;
349a747e4fSDavid du Colombier 	_threaddebug(DBGSCHED, "_threadexitsallstatus set to %p", _threadexitsallstatus);
359a747e4fSDavid du Colombier 	mypid = getpid();
369a747e4fSDavid du Colombier 
379a747e4fSDavid du Colombier 	/*
389a747e4fSDavid du Colombier 	 * signal others.
399a747e4fSDavid du Colombier 	 * copying all the pids first avoids other threads
409a747e4fSDavid du Colombier 	 * teardown procedures getting in the way.
41*dc5a79c1SDavid du Colombier 	 *
42*dc5a79c1SDavid du Colombier 	 * avoid mallocs since malloc can post a note which can
43*dc5a79c1SDavid du Colombier 	 * call threadexitsall...
449a747e4fSDavid du Colombier 	 */
45*dc5a79c1SDavid du Colombier 	for(;;){
469a747e4fSDavid du Colombier 		lock(&_threadpq.lock);
479a747e4fSDavid du Colombier 		npid = 0;
48*dc5a79c1SDavid du Colombier 		for(p = _threadpq.head; p && npid < nelem(pid); p=p->next){
49*dc5a79c1SDavid du Colombier 			if(p->threadint == 0 && p->pid != mypid){
509a747e4fSDavid du Colombier 				pid[npid++] = p->pid;
51*dc5a79c1SDavid du Colombier 				p->threadint = 1;
52*dc5a79c1SDavid du Colombier 			}
53*dc5a79c1SDavid du Colombier 		}
549a747e4fSDavid du Colombier 		unlock(&_threadpq.lock);
55*dc5a79c1SDavid du Colombier 		if(npid == 0)
56*dc5a79c1SDavid du Colombier 			break;
579a747e4fSDavid du Colombier 		for(i=0; i<npid; i++)
589a747e4fSDavid du Colombier 			postnote(PNPROC, pid[i], "threadint");
59*dc5a79c1SDavid du Colombier 	}
609a747e4fSDavid du Colombier 
619a747e4fSDavid du Colombier 	/* leave */
629a747e4fSDavid du Colombier 	exits(exitstr);
639a747e4fSDavid du Colombier }
649a747e4fSDavid du Colombier 
659a747e4fSDavid du Colombier Channel*
669a747e4fSDavid du Colombier threadwaitchan(void)
679a747e4fSDavid du Colombier {
689a747e4fSDavid du Colombier 	if(_threadwaitchan==nil)
699a747e4fSDavid du Colombier 		_threadwaitchan = chancreate(sizeof(Waitmsg*), 16);
709a747e4fSDavid du Colombier 	return _threadwaitchan;
719a747e4fSDavid du Colombier }
72