diff options
author | rsc <devnull@localhost> | 2003-12-06 18:05:27 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-12-06 18:05:27 +0000 |
commit | e97ceade5e1bba5787e39429384336fa37797906 (patch) | |
tree | 1353f5aa99b04e9c030ecc89cd7b526cb814090d /src/libthread | |
parent | c715a6127a46b8090591972b5c4bb04dfabbca8b (diff) | |
download | plan9port-e97ceade5e1bba5787e39429384336fa37797906.tar.gz plan9port-e97ceade5e1bba5787e39429384336fa37797906.tar.bz2 plan9port-e97ceade5e1bba5787e39429384336fa37797906.zip |
various tweaks.
Diffstat (limited to 'src/libthread')
-rw-r--r-- | src/libthread/create.c | 24 | ||||
-rw-r--r-- | src/libthread/exit.c | 2 | ||||
-rw-r--r-- | src/libthread/sched.c | 33 | ||||
-rw-r--r-- | src/libthread/threadimpl.h | 3 |
4 files changed, 61 insertions, 1 deletions
diff --git a/src/libthread/create.c b/src/libthread/create.c index 6a44c243..55f6c60c 100644 --- a/src/libthread/create.c +++ b/src/libthread/create.c @@ -2,6 +2,8 @@ Pqueue _threadpq; +int _threadmultiproc; + static int nextID(void); /* @@ -81,6 +83,14 @@ procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag) int proccreate(void (*f)(void*), void *arg, uint stacksize) { + Proc *p; + + p = _threadgetproc(); + if(p->idle){ + werrstr("cannot create procs once there is an idle thread"); + return -1; + } + _threadmultiproc = 1; return procrfork(f, arg, stacksize, 0); } @@ -110,6 +120,20 @@ threadcreate(void (*f)(void *arg), void *arg, uint stacksize) return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp()); } +int +threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize) +{ + int id; + + if(_threadmultiproc){ + werrstr("cannot have idle thread in multi-proc program"); + return -1; + } + id = newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp()); + _threadidle(); + return id; +} + /* * Create and initialize a new Proc structure with a single Thread * running inside it. Add the Proc to the global process list. diff --git a/src/libthread/exit.c b/src/libthread/exit.c index 511e5bca..4cda307e 100644 --- a/src/libthread/exit.c +++ b/src/libthread/exit.c @@ -12,6 +12,8 @@ threadexits(char *exitstr) p = _threadgetproc(); t = p->thread; + if(t == p->idle) + p->idle = nil; t->moribund = 1; _threaddebug(DBGSCHED, "threadexits %s", exitstr); if(exitstr==nil) diff --git a/src/libthread/sched.c b/src/libthread/sched.c index 293e3306..d6af1c7c 100644 --- a/src/libthread/sched.c +++ b/src/libthread/sched.c @@ -93,12 +93,21 @@ runthread(Proc *p) Thread *t; Tqueue *q; - if(p->nthreads==0) + if(p->nthreads==0 || (p->nthreads==1 && p->idle)) return nil; q = &p->ready; lock(&p->readylock); if(q->head == nil){ q->asleep = 1; + if(p->idle){ + if(p->idle->state != Ready){ + fprint(2, "everyone is asleep\n"); + exits("everyone is asleep"); + } + unlock(&p->readylock); + return p->idle; + } + _threaddebug(DBGSCHED, "sleeping for more work (%d threads)", p->nthreads); unlock(&p->readylock); while(rendezvous((ulong)q, 0) == ~0){ @@ -167,6 +176,9 @@ _threadready(Thread *t) { Tqueue *q; + if(t == t->proc->idle) + return; + assert(t->state == Ready); _threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id); q = &t->proc->ready; @@ -191,6 +203,25 @@ _threadready(Thread *t) } void +_threadidle(void) +{ + Tqueue *q; + Thread *t; + Proc *p; + + p = _threadgetproc(); + q = &p->ready; + lock(&p->readylock); + assert(q->head); + t = q->head; + q->head = t->next; + if(q->tail == t) + q->tail = nil; + p->idle = t; + unlock(&p->readylock); +} + +void yield(void) { _sched(); diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index d9b22403..aa69845c 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -115,6 +115,7 @@ struct Proc int pid; /* process id */ int splhi; /* delay notes */ Thread *thread; /* running thread */ + Thread *idle; /* idle thread */ int needexec; Execargs exec; /* exec argument */ @@ -185,6 +186,7 @@ void _threadinitstack(Thread*, void(*)(void*), void*); void* _threadmalloc(long, int); void _threadnote(void*, char*); void _threadready(Thread*); +void _threadidle(void); ulong _threadrendezvous(ulong, ulong); void _threadsignal(void); void _threadsysfatal(char*, va_list); @@ -192,6 +194,7 @@ long _xdec(long*); void _xinc(long*); void _threadremove(Proc*, Thread*); +extern int _threadmultiproc; extern int _threaddebuglevel; extern char* _threadexitsallstatus; extern Pqueue _threadpq; |