diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2021-10-12 00:49:12 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2021-10-12 00:49:12 +0000 |
commit | 07608c768faadfe960872d492d960be3112b7999 (patch) | |
tree | dd98f9f231519dcc6a5f2b78164af83a50f851e6 /sys/src/libthread/sched.c | |
parent | 24bd67f990fde5f25783293f57f651c93ce19125 (diff) |
libthread: deal with _schedfork() and _schedexec() returning -1
The current behaviour of the kernel to deadlock itself
instead of returning an error on fork.
This might change in the future, so prepare libthread
to handle this case.
For _schedfork(), we'r going to just retry forking
on every switch, while for _schedexec(), the exec
will fail and send ~0 down the pid channel.
Diffstat (limited to 'sys/src/libthread/sched.c')
-rw-r--r-- | sys/src/libthread/sched.c | 95 |
1 files changed, 57 insertions, 38 deletions
diff --git a/sys/src/libthread/sched.c b/sys/src/libthread/sched.c index 50603a3c4..888d64cc2 100644 --- a/sys/src/libthread/sched.c +++ b/sys/src/libthread/sched.c @@ -2,15 +2,9 @@ #include <libc.h> #include <thread.h> #include "threadimpl.h" -#include <tos.h> - -static Thread *runthread(Proc*); static char *_psstate[] = { - "Moribund", "Dead", - "Exec", - "Fork", "Running", "Ready", "Rendezvous", @@ -24,6 +18,23 @@ psstate(int s) return _psstate[s]; } +static void +unlinkproc(Proc *p) +{ + Proc **l; + + lock(&_threadpq.lock); + for(l=&_threadpq.head; *l; l=&(*l)->next){ + if(*l == p){ + *l = p->next; + if(*l == nil) + _threadpq.tail = l; + break; + } + } + unlock(&_threadpq.lock); +} + void _schedinit(void *arg) { @@ -31,8 +42,8 @@ _schedinit(void *arg) Thread *t, **l; p = arg; + p->pid = getpid(); _threadsetproc(p); - p->pid = _tos->pid; //getpid(); while(setjmp(p->sched)) ; _threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus); @@ -67,8 +78,15 @@ _schedinit(void *arg) p->needexec = 0; } if(p->newproc){ - t->ret = _schedfork(p->newproc); - p->newproc = nil; + Thread *x = p->newproc->threads.head; + if(x->moribund){ + x->proc = p; + _threadready(x); + unlinkproc(p->newproc); + free(p->newproc); + p->newproc = nil; + } else if(_schedfork(p->newproc) != -1) + p->newproc = nil; } t->state = t->nextstate; if(t->state == Ready) @@ -90,12 +108,38 @@ needstack(int n) if((uchar*)&x - n < (uchar*)t->stk){ fprint(2, "%s %lud: &x=%p n=%d t->stk=%p\n", - argv0, _tos->pid, &x, n, t->stk); - fprint(2, "%s %lud: stack overflow\n", argv0, _tos->pid); + argv0, (ulong)p->pid, &x, n, t->stk); + fprint(2, "%s %lud: stack overflow\n", argv0, (ulong)p->pid); abort(); } } +static Thread* +runthread(Proc *p) +{ + Thread *t; + Tqueue *q; + + if(p->nthreads==0) + return nil; + q = &p->ready; + lock(&p->readylock); + if(q->head == nil){ + q->asleep = 1; + _threaddebug(DBGSCHED, "sleeping for more work"); + unlock(&p->readylock); + while(rendezvous(q, 0) == (void*)~0){ + if(_threadexitsallstatus) + exits(_threadexitsallstatus); + } + /* lock picked up from _threadready */ + } + t = q->head; + q->head = t->next; + unlock(&p->readylock); + return t; +} + void _sched(void) { @@ -114,7 +158,8 @@ Resched: t = runthread(p); if(t == nil){ _threaddebug(DBGSCHED, "all threads gone; exiting"); - _schedexit(p); + unlinkproc(p); + _schedexit(p); /* frees proc */ } _threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id); p->thread = t; @@ -128,32 +173,6 @@ Resched: } } -static Thread* -runthread(Proc *p) -{ - Thread *t; - Tqueue *q; - - if(p->nthreads==0) - return nil; - q = &p->ready; - lock(&p->readylock); - if(q->head == nil){ - q->asleep = 1; - _threaddebug(DBGSCHED, "sleeping for more work"); - unlock(&p->readylock); - while(rendezvous(q, 0) == (void*)~0){ - if(_threadexitsallstatus) - exits(_threadexitsallstatus); - } - /* lock picked up from _threadready */ - } - t = q->head; - q->head = t->next; - unlock(&p->readylock); - return t; -} - void _threadready(Thread *t) { |