summaryrefslogtreecommitdiffstats
path: root/src/libthread/sched.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-12-25 21:56:33 +0000
committerrsc <devnull@localhost>2004-12-25 21:56:33 +0000
commit1544f90960275dc9211bde30329c3258e0e1bf38 (patch)
treef55e7a73c03aaa24daa7cc2ad02822b921c477f9 /src/libthread/sched.c
parent7788fd54094693384ef5c92c475656dba8819feb (diff)
downloadplan9port-1544f90960275dc9211bde30329c3258e0e1bf38.tar.gz
plan9port-1544f90960275dc9211bde30329c3258e0e1bf38.zip
New thread library
Diffstat (limited to 'src/libthread/sched.c')
-rw-r--r--src/libthread/sched.c343
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);
- }
-}
-