summaryrefslogtreecommitdiff
path: root/sys/src/libthread/sched.c
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/sched.c
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/sched.c')
-rw-r--r--sys/src/libthread/sched.c95
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)
{