summaryrefslogtreecommitdiff
path: root/sys/src/libthread
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2021-10-12 00:49:12 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2021-10-12 00:49:12 +0000
commit07608c768faadfe960872d492d960be3112b7999 (patch)
treedd98f9f231519dcc6a5f2b78164af83a50f851e6 /sys/src/libthread
parent24bd67f990fde5f25783293f57f651c93ce19125 (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.c3
-rw-r--r--sys/src/libthread/exec.c6
-rw-r--r--sys/src/libthread/exit.c5
-rw-r--r--sys/src/libthread/id.c1
-rw-r--r--sys/src/libthread/main.c15
-rw-r--r--sys/src/libthread/sched.c95
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)
{