1 cea10000 2005-05-01 devnull #undef exits
2 cea10000 2005-05-01 devnull #undef _exits
4 cea10000 2005-05-01 devnull extern int __isthreaded;
7 cea10000 2005-05-01 devnull * spin locks
9 cea10000 2005-05-01 devnull extern int _tas(int*);
12 cea10000 2005-05-01 devnull _threadunlock(Lock *l, ulong pc)
14 cea10000 2005-05-01 devnull USED(pc);
16 cea10000 2005-05-01 devnull l->held = 0;
20 cea10000 2005-05-01 devnull _threadlock(Lock *l, int block, ulong pc)
24 cea10000 2005-05-01 devnull USED(pc);
26 cea10000 2005-05-01 devnull /* once fast */
27 cea10000 2005-05-01 devnull if(!_tas(&l->held))
28 cea10000 2005-05-01 devnull return 1;
29 cea10000 2005-05-01 devnull if(!block)
30 cea10000 2005-05-01 devnull return 0;
32 cea10000 2005-05-01 devnull /* a thousand times pretty fast */
33 cea10000 2005-05-01 devnull for(i=0; i<1000; i++){
34 cea10000 2005-05-01 devnull if(!_tas(&l->held))
35 cea10000 2005-05-01 devnull return 1;
36 cea10000 2005-05-01 devnull sched_yield();
38 cea10000 2005-05-01 devnull /* increasingly slow */
39 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
40 cea10000 2005-05-01 devnull if(!_tas(&l->held))
41 cea10000 2005-05-01 devnull return 1;
42 cea10000 2005-05-01 devnull usleep(1);
44 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
45 cea10000 2005-05-01 devnull if(!_tas(&l->held))
46 cea10000 2005-05-01 devnull return 1;
47 cea10000 2005-05-01 devnull usleep(10);
49 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
50 cea10000 2005-05-01 devnull if(!_tas(&l->held))
51 cea10000 2005-05-01 devnull return 1;
52 cea10000 2005-05-01 devnull usleep(100);
54 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
55 cea10000 2005-05-01 devnull if(!_tas(&l->held))
56 cea10000 2005-05-01 devnull return 1;
57 cea10000 2005-05-01 devnull usleep(1000);
59 cea10000 2005-05-01 devnull for(i=0; i<10; i++){
60 cea10000 2005-05-01 devnull if(!_tas(&l->held))
61 cea10000 2005-05-01 devnull return 1;
62 cea10000 2005-05-01 devnull usleep(10*1000);
64 cea10000 2005-05-01 devnull /* now nice and slow */
65 cea10000 2005-05-01 devnull for(i=0; i<1000; i++){
66 cea10000 2005-05-01 devnull if(!_tas(&l->held))
67 cea10000 2005-05-01 devnull return 1;
68 cea10000 2005-05-01 devnull usleep(100*1000);
70 cea10000 2005-05-01 devnull /* take your time */
71 cea10000 2005-05-01 devnull while(_tas(&l->held))
72 cea10000 2005-05-01 devnull usleep(1000*1000);
73 cea10000 2005-05-01 devnull return 1;
77 cea10000 2005-05-01 devnull * For libc.
80 cea10000 2005-05-01 devnull typedef struct {
81 cea10000 2005-05-01 devnull volatile long access_lock;
82 cea10000 2005-05-01 devnull volatile long lock_owner;
83 cea10000 2005-05-01 devnull volatile char *fname;
84 cea10000 2005-05-01 devnull volatile int lineno;
85 cea10000 2005-05-01 devnull } spinlock_t;
88 cea10000 2005-05-01 devnull _spinlock(spinlock_t *lk)
90 cea10000 2005-05-01 devnull lock((Lock*)&lk->access_lock);
94 cea10000 2005-05-01 devnull * sleep and wakeup
96 cea10000 2005-05-01 devnull static void
97 cea10000 2005-05-01 devnull ign(int x)
102 cea10000 2005-05-01 devnull static void /*__attribute__((constructor))*/
103 cea10000 2005-05-01 devnull ignusr1(int restart)
105 cea10000 2005-05-01 devnull struct sigaction sa;
107 cea10000 2005-05-01 devnull memset(&sa, 0, sizeof sa);
108 cea10000 2005-05-01 devnull sa.sa_handler = ign;
109 cea10000 2005-05-01 devnull sigemptyset(&sa.sa_mask);
110 cea10000 2005-05-01 devnull sigaddset(&sa.sa_mask, SIGUSR1);
111 cea10000 2005-05-01 devnull if(restart)
112 cea10000 2005-05-01 devnull sa.sa_flags = SA_RESTART;
113 cea10000 2005-05-01 devnull sigaction(SIGUSR1, &sa, nil);
117 cea10000 2005-05-01 devnull _procsleep(_Procrendez *r)
119 cea10000 2005-05-01 devnull sigset_t mask;
122 cea10000 2005-05-01 devnull * Go to sleep.
124 cea10000 2005-05-01 devnull * Block USR1, set the handler to interrupt system calls,
125 cea10000 2005-05-01 devnull * unlock the vouslock so our waker can wake us,
126 cea10000 2005-05-01 devnull * and then suspend.
129 cea10000 2005-05-01 devnull r->asleep = 1;
130 cea10000 2005-05-01 devnull r->pid = getpid();
132 cea10000 2005-05-01 devnull sigprocmask(SIG_SETMASK, nil, &mask);
133 cea10000 2005-05-01 devnull sigaddset(&mask, SIGUSR1);
134 cea10000 2005-05-01 devnull sigprocmask(SIG_SETMASK, &mask, nil);
135 cea10000 2005-05-01 devnull ignusr1(0);
136 cea10000 2005-05-01 devnull unlock(r->l);
137 cea10000 2005-05-01 devnull sigdelset(&mask, SIGUSR1);
138 cea10000 2005-05-01 devnull sigsuspend(&mask);
141 cea10000 2005-05-01 devnull * We're awake. Make USR1 not interrupt system calls.
143 cea10000 2005-05-01 devnull lock(r->l);
144 cea10000 2005-05-01 devnull ignusr1(1);
145 cea10000 2005-05-01 devnull if(r->asleep && r->pid == getpid()){
146 cea10000 2005-05-01 devnull /* Didn't really wake up - signal from something else */
147 cea10000 2005-05-01 devnull goto again;
152 cea10000 2005-05-01 devnull _procwakeup(_Procrendez *r)
154 cea10000 2005-05-01 devnull if(r->asleep){
155 cea10000 2005-05-01 devnull r->asleep = 0;
156 cea10000 2005-05-01 devnull assert(r->pid >= 1);
157 cea10000 2005-05-01 devnull kill(r->pid, SIGUSR1);
162 cea10000 2005-05-01 devnull _procwakeupandunlock(_Procrendez *r)
164 cea10000 2005-05-01 devnull _procwakeup(r);
165 cea10000 2005-05-01 devnull unlock(r->l);
170 cea10000 2005-05-01 devnull * process creation and exit
172 cea10000 2005-05-01 devnull typedef struct Stackfree Stackfree;
173 cea10000 2005-05-01 devnull struct Stackfree
175 cea10000 2005-05-01 devnull Stackfree *next;
176 cea10000 2005-05-01 devnull int pid;
178 cea10000 2005-05-01 devnull static Lock stacklock;
179 cea10000 2005-05-01 devnull static Stackfree *stackfree;
181 cea10000 2005-05-01 devnull static void
182 cea10000 2005-05-01 devnull delayfreestack(uchar *stk)
184 cea10000 2005-05-01 devnull Stackfree *sf;
186 cea10000 2005-05-01 devnull sf = (Stackfree*)stk;
187 cea10000 2005-05-01 devnull sf->pid = getpid();
188 cea10000 2005-05-01 devnull lock(&stacklock);
189 cea10000 2005-05-01 devnull sf->next = stackfree;
190 cea10000 2005-05-01 devnull stackfree = sf;
191 cea10000 2005-05-01 devnull unlock(&stacklock);
194 cea10000 2005-05-01 devnull static void
195 cea10000 2005-05-01 devnull dofreestacks(void)
197 cea10000 2005-05-01 devnull Stackfree *sf, *last, *next;
199 cea10000 2005-05-01 devnull if(stackfree==nil || !canlock(&stacklock))
202 cea10000 2005-05-01 devnull for(last=nil,sf=stackfree; sf; last=sf,sf=next){
203 cea10000 2005-05-01 devnull next = sf->next;
204 cea10000 2005-05-01 devnull if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){
205 cea10000 2005-05-01 devnull free(sf);
206 cea10000 2005-05-01 devnull if(last)
207 cea10000 2005-05-01 devnull last->next = next;
209 cea10000 2005-05-01 devnull stackfree = next;
210 cea10000 2005-05-01 devnull sf = last;
213 cea10000 2005-05-01 devnull unlock(&stacklock);
216 cea10000 2005-05-01 devnull static int
217 cea10000 2005-05-01 devnull startprocfn(void *v)
219 cea10000 2005-05-01 devnull void **a;
220 cea10000 2005-05-01 devnull uchar *stk;
221 cea10000 2005-05-01 devnull void (*fn)(void*);
222 cea10000 2005-05-01 devnull Proc *p;
224 cea10000 2005-05-01 devnull a = (void**)v;
225 cea10000 2005-05-01 devnull fn = a[0];
226 cea10000 2005-05-01 devnull p = a[1];
227 cea10000 2005-05-01 devnull stk = a[2];
228 cea10000 2005-05-01 devnull free(a);
229 cea10000 2005-05-01 devnull p->osprocid = getpid();
231 cea10000 2005-05-01 devnull (*fn)(p);
233 cea10000 2005-05-01 devnull delayfreestack(stk);
234 cea10000 2005-05-01 devnull _exit(0);
235 cea10000 2005-05-01 devnull return 0;
239 cea10000 2005-05-01 devnull _procstart(Proc *p, void (*fn)(Proc*))
241 cea10000 2005-05-01 devnull void **a;
242 cea10000 2005-05-01 devnull uchar *stk;
243 cea10000 2005-05-01 devnull int pid;
245 cea10000 2005-05-01 devnull dofreestacks();
246 cea10000 2005-05-01 devnull a = malloc(3*sizeof a[0]);
247 cea10000 2005-05-01 devnull if(a == nil)
248 cea10000 2005-05-01 devnull sysfatal("_procstart malloc: %r");
249 cea10000 2005-05-01 devnull stk = malloc(65536);
250 cea10000 2005-05-01 devnull if(stk == nil)
251 cea10000 2005-05-01 devnull sysfatal("_procstart malloc stack: %r");
253 cea10000 2005-05-01 devnull a[0] = fn;
254 cea10000 2005-05-01 devnull a[1] = p;
255 cea10000 2005-05-01 devnull a[2] = stk;
257 cea10000 2005-05-01 devnull pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a);
258 cea10000 2005-05-01 devnull if(pid < 0){
259 cea10000 2005-05-01 devnull fprint(2, "_procstart rfork_thread: %r\n");
260 cea10000 2005-05-01 devnull abort();
264 cea10000 2005-05-01 devnull static char *threadexitsmsg;
266 cea10000 2005-05-01 devnull sigusr2handler(int s)
268 cea10000 2005-05-01 devnull /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */
269 cea10000 2005-05-01 devnull if(threadexitsmsg)
270 cea10000 2005-05-01 devnull _exits(threadexitsmsg);
274 cea10000 2005-05-01 devnull threadexitsall(char *msg)
276 cea10000 2005-05-01 devnull static int pid[1024];
277 cea10000 2005-05-01 devnull int i, npid, mypid;
278 cea10000 2005-05-01 devnull Proc *p;
280 cea10000 2005-05-01 devnull if(msg == nil)
281 cea10000 2005-05-01 devnull msg = "";
282 cea10000 2005-05-01 devnull mypid = getpid();
283 cea10000 2005-05-01 devnull lock(&_threadprocslock);
284 cea10000 2005-05-01 devnull threadexitsmsg = msg;
285 cea10000 2005-05-01 devnull npid = 0;
286 cea10000 2005-05-01 devnull for(p=_threadprocs; p; p=p->next)
287 cea10000 2005-05-01 devnull if(p->osprocid != mypid && p->osprocid >= 1)
288 cea10000 2005-05-01 devnull pid[npid++] = p->osprocid;
289 cea10000 2005-05-01 devnull for(i=0; i<npid; i++)
290 cea10000 2005-05-01 devnull kill(pid[i], SIGUSR2);
291 cea10000 2005-05-01 devnull unlock(&_threadprocslock);
292 cea10000 2005-05-01 devnull exits(msg);
296 cea10000 2005-05-01 devnull * per-process data, indexed by pid
298 cea10000 2005-05-01 devnull typedef struct Perproc Perproc;
299 cea10000 2005-05-01 devnull struct Perproc
301 cea10000 2005-05-01 devnull int pid;
302 cea10000 2005-05-01 devnull Proc *proc;
305 cea10000 2005-05-01 devnull static Lock perlock;
306 cea10000 2005-05-01 devnull static Perproc perproc[1024];
307 cea10000 2005-05-01 devnull #define P ((Proc*)-1)
309 cea10000 2005-05-01 devnull static Perproc*
310 cea10000 2005-05-01 devnull myperproc(void)
312 cea10000 2005-05-01 devnull int i, pid, h;
313 cea10000 2005-05-01 devnull Perproc *p;
315 cea10000 2005-05-01 devnull pid = getpid();
316 cea10000 2005-05-01 devnull h = pid%nelem(perproc);
317 cea10000 2005-05-01 devnull for(i=0; i<nelem(perproc); i++){
318 cea10000 2005-05-01 devnull p = &perproc[(i+h)%nelem(perproc)];
319 cea10000 2005-05-01 devnull if(p->pid == pid)
320 cea10000 2005-05-01 devnull return p;
321 cea10000 2005-05-01 devnull if(p->pid == 0){
322 cea10000 2005-05-01 devnull print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
326 cea10000 2005-05-01 devnull fprint(2, "myperproc %d: cannot find self\n", pid);
327 cea10000 2005-05-01 devnull abort();
328 cea10000 2005-05-01 devnull return nil;
331 cea10000 2005-05-01 devnull static Perproc*
332 cea10000 2005-05-01 devnull newperproc(void)
334 cea10000 2005-05-01 devnull int i, pid, h;
335 cea10000 2005-05-01 devnull Perproc *p;
337 cea10000 2005-05-01 devnull lock(&perlock);
338 cea10000 2005-05-01 devnull pid = getpid();
339 cea10000 2005-05-01 devnull h = pid%nelem(perproc);
340 cea10000 2005-05-01 devnull for(i=0; i<nelem(perproc); i++){
341 cea10000 2005-05-01 devnull p = &perproc[(i+h)%nelem(perproc)];
342 cea10000 2005-05-01 devnull if(p->pid == pid || p->pid == -1 || p->pid == 0){
343 cea10000 2005-05-01 devnull p->pid = pid;
344 cea10000 2005-05-01 devnull unlock(&perlock);
345 cea10000 2005-05-01 devnull return p;
348 cea10000 2005-05-01 devnull fprint(2, "newperproc %d: out of procs\n", pid);
349 cea10000 2005-05-01 devnull abort();
350 cea10000 2005-05-01 devnull return nil;
354 cea10000 2005-05-01 devnull _threadproc(void)
356 cea10000 2005-05-01 devnull return myperproc()->proc;
360 cea10000 2005-05-01 devnull _threadsetproc(Proc *p)
362 cea10000 2005-05-01 devnull Perproc *pp;
365 cea10000 2005-05-01 devnull p->osprocid = getpid();
366 cea10000 2005-05-01 devnull pp = newperproc();
367 cea10000 2005-05-01 devnull pp->proc = p;
368 cea10000 2005-05-01 devnull if(p == nil)
369 cea10000 2005-05-01 devnull pp->pid = -1;
373 cea10000 2005-05-01 devnull _pthreadinit(void)
375 cea10000 2005-05-01 devnull __isthreaded = 1;
376 cea10000 2005-05-01 devnull signal(SIGUSR2, sigusr2handler);
380 cea10000 2005-05-01 devnull _threadpexit(void)
382 cea10000 2005-05-01 devnull _exit(0);