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 | |
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')
-rw-r--r-- | sys/src/libthread/create.c | 3 | ||||
-rw-r--r-- | sys/src/libthread/exec.c | 6 | ||||
-rw-r--r-- | sys/src/libthread/exit.c | 5 | ||||
-rw-r--r-- | sys/src/libthread/id.c | 1 | ||||
-rw-r--r-- | sys/src/libthread/main.c | 15 | ||||
-rw-r--r-- | sys/src/libthread/sched.c | 95 |
6 files changed, 67 insertions, 58 deletions
diff --git a/sys/src/libthread/create.c b/sys/src/libthread/create.c index 41a373c99..c58e6a837 100644 --- a/sys/src/libthread/create.c +++ b/sys/src/libthread/create.c @@ -97,7 +97,8 @@ procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag) int id; p = _threadgetproc(); - assert(p->newproc == nil); + while(p->newproc) + _sched(); p->newproc = _newproc(f, arg, stacksize, nil, p->thread->grp, rforkflag); id = p->newproc->threads.head->id; _sched(); diff --git a/sys/src/libthread/exec.c b/sys/src/libthread/exec.c index 3bfbda3c6..b3ac6c213 100644 --- a/sys/src/libthread/exec.c +++ b/sys/src/libthread/exec.c @@ -45,8 +45,10 @@ procexec(Channel *pidc, char *prog, char *args[]) close(p->exec.fd[1]); p->exec.fd[1] = n; + while(p->needexec || p->newproc) + _sched(); + /* exec in parallel via the scheduler */ - assert(p->needexec==0); p->exec.prog = prog; p->exec.args = args; p->needexec = 1; @@ -61,6 +63,8 @@ procexec(Channel *pidc, char *prog, char *args[]) } close(p->exec.fd[0]); + if(t->ret == -1) + goto Bad; if(pidc) sendul(pidc, t->ret); diff --git a/sys/src/libthread/exit.c b/sys/src/libthread/exit.c index d36e11af4..a6ee207b2 100644 --- a/sys/src/libthread/exit.c +++ b/sys/src/libthread/exit.c @@ -2,7 +2,6 @@ #include <libc.h> #include <thread.h> #include "threadimpl.h" -#include <tos.h> char *_threadexitsallstatus; Channel *_threadwaitchan; @@ -33,7 +32,7 @@ threadexitsall(char *exitstr) exitstr = ""; _threadexitsallstatus = exitstr; _threaddebug(DBGSCHED, "_threadexitsallstatus set to %p", _threadexitsallstatus); - mypid = _tos->pid; //getpid(); + mypid = getpid(); /* * signal others. @@ -47,7 +46,7 @@ threadexitsall(char *exitstr) lock(&_threadpq.lock); npid = 0; for(p = _threadpq.head; p && npid < nelem(pid); p=p->next){ - if(p->threadint == 0 && p->pid != mypid){ + if(p->threadint == 0 && p->pid != mypid && p->pid != -1){ pid[npid++] = p->pid; p->threadint = 1; } diff --git a/sys/src/libthread/id.c b/sys/src/libthread/id.c index 289dc8698..778bdcd5c 100644 --- a/sys/src/libthread/id.c +++ b/sys/src/libthread/id.c @@ -2,7 +2,6 @@ #include <libc.h> #include <thread.h> #include "threadimpl.h" -#include <tos.h> int threadid(void) diff --git a/sys/src/libthread/main.c b/sys/src/libthread/main.c index a2a2eb0af..48a8acd52 100644 --- a/sys/src/libthread/main.c +++ b/sys/src/libthread/main.c @@ -28,8 +28,6 @@ main(int argc, char **argv) rfork(RFREND); mainp = &p; - if(setjmp(_mainjmp)) - _schedinit(p); //_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0; _systhreadinit(); @@ -45,6 +43,7 @@ main(int argc, char **argv) a->argv = argv; p = _newproc(mainlauncher, a, mainstacksize, "threadmain", 0, 0); + setjmp(_mainjmp); _schedinit(p); abort(); /* not reached */ } @@ -117,18 +116,6 @@ void _schedexit(Proc *p) { char ex[ERRMAX]; - 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); utfecpy(ex, ex+sizeof ex, p->exitstr); free(p); 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) { |