3 #include "threadimpl.h"
6 * Basic kernel thread management.
8 static pthread_key_t key;
13 pthread_key_create(&key, 0);
17 _kthreadsetproc(Proc *p)
21 p->pthreadid = pthread_self();
23 pthread_sigmask(SIG_SETMASK, &all, nil);
24 pthread_setspecific(key, p);
30 return pthread_getspecific(key);
34 _kthreadstartproc(Proc *p)
42 pthread_sigmask(SIG_SETMASK, &all, nil);
43 if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler,
45 sysfatal("pthread_create: %r");
50 _kthreadexitproc(char *exitstr)
52 _threaddebug(DBGSCHED, "_pthreadexit");
57 _kthreadexitallproc(char *exitstr)
59 _threaddebug(DBGSCHED, "_threadexitallproc");
64 * Exec. Pthreads does the hard work of making it possible
65 * for any thread to do the waiting, so this is pretty easy.
66 * We create a separate proc whose job is to wait for children
67 * and deliver wait messages.
69 static Channel *_threadexecwaitchan;
72 _threadwaitproc(void *v)
77 _threadinternalproc();
84 if(errno == ECHILD) /* wait for more */
85 recvul(_threadexecwaitchan);
88 if((c = _threadwaitchan) != nil)
93 fprint(2, "_threadwaitproc exits\n"); /* not reached */
98 * Call _threadexec in the right conditions.
101 _kthreadexec(Channel *c, int fd[3], char *prog, char *args[], int freeargs)
106 if(!_threadexecwaitchan){
108 if(!_threadexecwaitchan){
109 _threadexecwaitchan = chancreate(sizeof(ulong), 1);
110 proccreate(_threadwaitproc, nil, 32*1024);
114 rv = _threadexec(c, fd, prog, args, freeargs);
115 nbsendul(_threadexecwaitchan, 1);
120 * Some threaded applications want to run in the background.
121 * Calling fork() and exiting in the parent will result in a child
122 * with a single pthread (if we are using pthreads), and will screw
123 * up our internal process info if we are using clone/rfork.
124 * Instead, apps should call threadbackground(), which takes
127 * _threadbackgroundinit is called from main.
130 static int mainpid, passerpid;
133 passer(void *x, char *msg)
138 if(strcmp(msg, "sys: usr2") == 0)
139 _exit(0); /* daemonize */
140 else if(strcmp(msg, "sys: child") == 0){
141 /* child exited => so should we */
147 postnote(PNGROUP, mainpid, msg);
151 _threadbackgroundinit(void)
157 pthread_sigmask(SIG_BLOCK, &mask, 0);
161 passerpid = getpid();
162 switch(pid = fork()){
164 sysfatal("fork: %r");
176 notifyon("sys: child");
177 notifyon("sys: usr2"); /* should already be on */
184 threadbackground(void)
188 postnote(PNPROC, passerpid, "sys: usr2");
194 Channel *_threadnotechan;
196 static Lock _threadnotelk;
197 static void _threadnoteproc(void*);
198 extern int _p9strsig(char*);
199 extern char *_p9sigstr(int);
204 if(_threadnotechan == nil){
205 lock(&_threadnotelk);
206 if(_threadnotechan == nil){
207 _threadnotechan = chancreate(sizeof(char*), 1);
208 proccreate(_threadnoteproc, nil, 32*1024);
210 unlock(&_threadnotelk);
212 return _threadnotechan;
216 _threadnote(void *x, char *msg)
220 if(_threadexitsallstatus)
221 _kthreadexitproc(_threadexitsallstatus);
223 if(strcmp(msg, "sys: usr2") == 0)
226 if(_threadnotechan == nil)
229 sigs |= 1<<_p9strsig(msg);
234 _threadnoteproc(void *x)
240 _threadinternalproc();
242 pthread_sigmask(SIG_SETMASK, &none, 0);
249 if((sigs&(1<<i)) == 0)
254 sendp(c, _p9sigstr(i));
260 _threadschednote(void)
270 pthread_sigmask(SIG_SETMASK, &all, 0);