123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #include <u.h>
- #include <libc.h>
- #include <thread.h>
- #include "threadimpl.h"
- static Thread *runthread(Proc*);
- static char *_psstate[] = {
- "Moribund",
- "Dead",
- "Exec",
- "Fork",
- "Running",
- "Ready",
- "Rendezvous",
- };
- static char*
- psstate(int s)
- {
- if(s < 0 || s >= nelem(_psstate))
- return "unknown";
- return _psstate[s];
- }
- void
- _schedinit(void *arg)
- {
- Proc *p;
- Thread *t, **l;
- p = arg;
- _threadsetproc(p);
- p->pid = getpid();
- while(setjmp(p->sched))
- ;
- _threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
- if(_threadexitsallstatus)
- exits(_threadexitsallstatus);
- lock(&p->lock);
- if((t=p->thread) != nil){
- p->thread = nil;
- if(t->moribund){
- t->state = Dead;
- for(l=&p->threads.head; *l; l=&(*l)->nextt)
- if(*l == t){
- *l = t->nextt;
- if(*l==nil)
- p->threads.tail = l;
- p->nthreads--;
- break;
- }
- unlock(&p->lock);
- if(t->inrendez){
- _threadflagrendez(t);
- _threadbreakrendez();
- }
- free(t->stk);
- free(t->cmdname);
- free(t); /* XXX how do we know there are no references? */
- t = nil;
- _sched();
- }
- if(p->needexec){
- t->ret = _schedexec(&p->exec);
- p->needexec = 0;
- }
- if(p->newproc){
- t->ret = _schedfork(p->newproc);
- p->newproc = nil;
- }
- t->state = t->nextstate;
- if(t->state == Ready)
- _threadready(t);
- }
- unlock(&p->lock);
- _sched();
- }
- void
- needstack(int n)
- {
- int x;
- Proc *p;
- Thread *t;
-
- p = _threadgetproc();
- t = p->thread;
-
- if((uchar*)&x - n < (uchar*)t->stk){
- fprint(2, "%s %d: &x=%p n=%d t->stk=%p\n",
- argv0, getpid(), &x, n, t->stk);
- fprint(2, "%s %d: stack overflow\n", argv0, getpid());
- abort();
- }
- }
- void
- _sched(void)
- {
- Proc *p;
- Thread *t;
- Resched:
- p = _threadgetproc();
- if((t = p->thread) != nil){
- needstack(128);
- _threaddebug(DBGSCHED, "pausing, state=%s", psstate(t->state));
- if(setjmp(t->sched)==0)
- longjmp(p->sched, 1);
- return;
- }else{
- t = runthread(p);
- if(t == nil){
- _threaddebug(DBGSCHED, "all threads gone; exiting");
- _schedexit(p);
- }
- _threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id);
- p->thread = t;
- if(t->moribund){
- _threaddebug(DBGSCHED, "%d.%d marked to die");
- goto Resched;
- }
- t->state = Running;
- t->nextstate = Ready;
- longjmp(t->sched, 1);
- }
- }
- 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)
- {
- Tqueue *q;
- assert(t->state == Ready);
- _threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id);
- q = &t->proc->ready;
- lock(&t->proc->readylock);
- t->next = nil;
- if(q->head==nil)
- q->head = t;
- else
- *q->tail = t;
- q->tail = &t->next;
- if(q->asleep){
- q->asleep = 0;
- /* lock passes to runthread */
- _threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
- while(rendezvous(q, 0) == (void*)~0){
- if(_threadexitsallstatus)
- exits(_threadexitsallstatus);
- }
- }else
- unlock(&t->proc->readylock);
- }
- void
- yield(void)
- {
- _sched();
- }
|