diff options
| author | rsc <devnull@localhost> | 2004-12-25 21:56:33 +0000 |
|---|---|---|
| committer | rsc <devnull@localhost> | 2004-12-25 21:56:33 +0000 |
| commit | 1544f90960275dc9211bde30329c3258e0e1bf38 (patch) | |
| tree | f55e7a73c03aaa24daa7cc2ad02822b921c477f9 /src/libthread/sched.c | |
| parent | 7788fd54094693384ef5c92c475656dba8819feb (diff) | |
| download | plan9port-1544f90960275dc9211bde30329c3258e0e1bf38.tar.gz plan9port-1544f90960275dc9211bde30329c3258e0e1bf38.zip | |
New thread library
Diffstat (limited to 'src/libthread/sched.c')
| -rw-r--r-- | src/libthread/sched.c | 343 |
1 files changed, 0 insertions, 343 deletions
diff --git a/src/libthread/sched.c b/src/libthread/sched.c deleted file mode 100644 index ac982da8..00000000 --- a/src/libthread/sched.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Thread scheduler. - */ -#include "threadimpl.h" - -static Thread *runthread(Proc*); -static void schedexit(Proc*); - -/* - * Main scheduling loop. - */ -void -_threadscheduler(void *arg) -{ - Proc *p; - Thread *t; - - p = arg; - - _threadlinkmain(); - _threadsetproc(p); - - for(;;){ - /* - * Clean up zombie children. - */ - - /* - * Find next thread to run. - */ - _threaddebug(DBGSCHED, "runthread"); - t = runthread(p); - if(t == nil) - schedexit(p); - - /* - * If it's ready, run it (might instead be marked to die). - */ - lock(&p->lock); - if(t->state == Ready){ - _threaddebug(DBGSCHED, "running %d.%d", p->id, t->id); - t->state = Running; - t->nextstate = Ready; - p->thread = t; - unlock(&p->lock); - _swaplabel(&p->context, &t->context); - lock(&p->lock); - p->thread = nil; - } - - /* - * If thread needs to die, kill it. - * t->proc == p may not be true if we're - * trying to jump into the exec proc (see exec-unix.c). - */ - if(t->moribund){ - _threaddebug(DBGSCHED, "moribund %d.%d", p->id, t->id); - if(t->moribund != 1) - print("moribund broke %p %d\n", &t->moribund, t->moribund); - assert(t->moribund == 1); - t->state = Dead; - _procdelthread(p, t); - unlock(&p->lock); - _threadfree(t); - t = nil; - continue; - } - - /* - * If the thread has asked to move to another proc, - * let it go (only to be used in *very* special situations). - if(t->nextproc != p) - _procdelthread(p, t); - */ - - unlock(&p->lock); - - /* - * If the thread has asked to move to another proc, - * add it to the new proc. - */ - if(t->nextproc != p){ - // lock(&t->nextproc->lock); - // _procaddthread(t->nextproc, t); - // unlock(&t->nextproc->lock); - t->proc = t->nextproc; - } - - /* - * If there is a request to run a function on the - * scheduling stack, do so. - */ - if(p->schedfn){ - _threaddebug(DBGSCHED, "schedfn"); - p->schedfn(p); - p->schedfn = nil; - _threaddebug(DBGSCHED, "schedfn ended"); - } - - /* - * Move the thread along. - */ - t->state = t->nextstate; - _threaddebug(DBGSCHED, "moveon %d.%d", t->proc->id, t->id); - if(t->state == Ready) - _threadready(t); - } -} - -/* - * Called by thread to give up control of processor to scheduler. - */ -int -_sched(void) -{ - Proc *p; - Thread *t; - - p = _threadgetproc(); - t = p->thread; - assert(t != nil); - _swaplabel(&t->context, &p->context); - return p->nsched++; -} - -/* - * Called by thread to yield the processor to other threads. - * Returns number of other threads run between call and return. - */ -int -yield(void) -{ - Proc *p; - int nsched; - - p = _threadgetproc(); - nsched = p->nsched; - return _sched() - nsched; -} - -/* - * Choose the next thread to run. - */ -static Thread* -runthread(Proc *p) -{ - Thread *t; - Tqueue *q; - - /* - * No threads left? - */ - if(p->nthreads==0 || (p->nthreads==1 && p->idle)) - return nil; - - _threadschednote(); - lock(&p->readylock); - q = &p->ready; - if(q->head == nil){ - /* - * Is this a single-process program with an idle thread? - */ - if(p->idle){ - /* - * The idle thread had better be ready! - */ - if(p->idle->state != Ready) - sysfatal("all threads are asleep"); - - /* - * Run the idle thread. - */ - unlock(&p->readylock); - _threaddebug(DBGSCHED, "running idle thread", p->nthreads); - return p->idle; - } - - /* - * Wait until one of our threads is readied (by another proc!). - */ - q->asleep = 1; - p->rend.l = &p->readylock; - while(q->asleep){ - _procsleep(&p->rend); - _threadschednote(); - } - - /* - * Maybe we were awakened to exit? - */ - if(_threadexitsallstatus){ - _threaddebug(DBGSCHED, "time to exit"); - _exits(_threadexitsallstatus); - } - assert(q->head != nil); - } - - t = q->head; - q->head = t->next; - unlock(&p->readylock); - - return t; -} - -/* - * Add a newly-ready thread to its proc's run queue. - */ -void -_threadready(Thread *t) -{ - Tqueue *q; - - /* - * The idle thread does not go on the run queue. - */ - if(t == t->proc->idle){ - _threaddebug(DBGSCHED, "idle thread is ready"); - return; - } - - assert(t->state == Ready); - _threaddebug(DBGSCHED, "readying %d.%d", t->proc->id, t->id); - - /* - * Add thread to run queue. - */ - q = &t->proc->ready; - lock(&t->proc->readylock); - - t->next = nil; - if(q->head == nil) - q->head = t; - else - q->tail->next = t; - q->tail = t; - - /* - * Wake proc scheduler if it is sleeping. - */ - if(q->asleep){ - assert(q->asleep == 1); - q->asleep = 0; - _procwakeup(&t->proc->rend); - } - unlock(&t->proc->readylock); -} - -/* - * Mark the given thread as the idle thread. - * Since the idle thread was just created, it is sitting - * somewhere on the ready queue. - */ -void -_threadsetidle(int id) -{ - Tqueue *q; - Thread *t, **l, *last; - Proc *p; - - p = _threadgetproc(); - - lock(&p->readylock); - - /* - * Find thread on ready queue. - */ - q = &p->ready; - for(l=&q->head, last=nil; (t=*l) != nil; l=&t->next, last=t) - if(t->id == id) - break; - assert(t != nil); - - /* - * Remove it from ready queue. - */ - *l = t->next; - if(t == q->head) - q->head = t->next; - if(t->next == nil) - q->tail = last; - - /* - * Set as idle thread. - */ - p->idle = t; - _threaddebug(DBGSCHED, "p->idle is %d\n", t->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) -{ - char ex[ERRMAX]; - int n; - Proc **l; - - _threaddebug(DBGSCHED, "exiting proc %d", p->id); - lock(&_threadpq.lock); - for(l=&_threadpq.head; *l; l=&(*l)->next){ - if(*l == p){ - *l = p->next; - if(*l == nil) - _threadpq.tail = l; - break; - } - } - if(p->internal) - n = _threadnprocs; - else - n = --_threadnprocs; - unlock(&_threadpq.lock); - - strncpy(ex, p->exitstr, sizeof ex); - ex[sizeof ex-1] = '\0'; - free(p); - if(n == 0){ - _threaddebug(DBGSCHED, "procexit; no more procs"); - _kthreadexitallproc(ex); - }else{ - _threaddebug(DBGSCHED, "procexit"); - _kthreadexitproc(ex); - } -} - |
