aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libthread/sched.c')
-rw-r--r--src/libthread/sched.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/src/libthread/sched.c b/src/libthread/sched.c
index 7e430193..ac982da8 100644
--- a/src/libthread/sched.c
+++ b/src/libthread/sched.c
@@ -18,13 +18,12 @@ _threadscheduler(void *arg)
p = arg;
_threadlinkmain();
- _threadinitproc(p);
+ _threadsetproc(p);
for(;;){
/*
* Clean up zombie children.
*/
- _threadwaitkids(p);
/*
* Find next thread to run.
@@ -154,6 +153,7 @@ runthread(Proc *p)
if(p->nthreads==0 || (p->nthreads==1 && p->idle))
return nil;
+ _threadschednote();
lock(&p->readylock);
q = &p->ready;
if(q->head == nil){
@@ -180,7 +180,10 @@ runthread(Proc *p)
*/
q->asleep = 1;
p->rend.l = &p->readylock;
- _procsleep(&p->rend);
+ while(q->asleep){
+ _procsleep(&p->rend);
+ _threadschednote();
+ }
/*
* Maybe we were awakened to exit?
@@ -284,6 +287,25 @@ _threadsetidle(int id)
unlock(&p->readylock);
}
+/*
+ * Mark proc as internal so that if all but internal procs exit, we exit.
+ */
+void
+_threadinternalproc(void)
+{
+ Proc *p;
+
+ p = _threadgetproc();
+ if(p->internal)
+ return;
+ lock(&_threadpq.lock);
+ if(p->internal == 0){
+ p->internal = 1;
+ --_threadnprocs;
+ }
+ unlock(&_threadpq.lock);
+}
+
static void
schedexit(Proc *p)
{
@@ -301,7 +323,10 @@ schedexit(Proc *p)
break;
}
}
- n = --_threadnprocs;
+ if(p->internal)
+ n = _threadnprocs;
+ else
+ n = --_threadnprocs;
unlock(&_threadpq.lock);
strncpy(ex, p->exitstr, sizeof ex);
@@ -309,10 +334,10 @@ schedexit(Proc *p)
free(p);
if(n == 0){
_threaddebug(DBGSCHED, "procexit; no more procs");
- _threadexitallproc(ex);
+ _kthreadexitallproc(ex);
}else{
_threaddebug(DBGSCHED, "procexit");
- _threadexitproc(ex);
+ _kthreadexitproc(ex);
}
}