sched.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "threadimpl.h"
  5. static Thread *runthread(Proc*);
  6. static char *_psstate[] = {
  7. "Moribund",
  8. "Dead",
  9. "Exec",
  10. "Fork",
  11. "Running",
  12. "Ready",
  13. "Rendezvous",
  14. };
  15. static char*
  16. psstate(int s)
  17. {
  18. if(s < 0 || s >= nelem(_psstate))
  19. return "unknown";
  20. return _psstate[s];
  21. }
  22. void
  23. _schedinit(void *arg)
  24. {
  25. Proc *p;
  26. Thread *t, **l;
  27. p = arg;
  28. _threadsetproc(p);
  29. p->pid = getpid();
  30. while(setjmp(p->sched))
  31. ;
  32. _threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
  33. if(_threadexitsallstatus)
  34. exits(_threadexitsallstatus);
  35. lock(&p->lock);
  36. if((t=p->thread) != nil){
  37. p->thread = nil;
  38. if(t->moribund){
  39. t->state = Dead;
  40. for(l=&p->threads.head; *l; l=&(*l)->nextt)
  41. if(*l == t){
  42. *l = t->nextt;
  43. if(*l==nil)
  44. p->threads.tail = l;
  45. p->nthreads--;
  46. break;
  47. }
  48. unlock(&p->lock);
  49. if(t->inrendez){
  50. _threadflagrendez(t);
  51. _threadbreakrendez();
  52. }
  53. free(t->stk);
  54. free(t->cmdname);
  55. free(t); /* XXX how do we know there are no references? */
  56. t = nil;
  57. _sched();
  58. }
  59. if(p->needexec){
  60. t->ret = _schedexec(&p->exec);
  61. p->needexec = 0;
  62. }
  63. if(p->newproc){
  64. t->ret = _schedfork(p->newproc);
  65. p->newproc = nil;
  66. }
  67. t->state = t->nextstate;
  68. if(t->state == Ready)
  69. _threadready(t);
  70. }
  71. unlock(&p->lock);
  72. _sched();
  73. }
  74. void
  75. _sched(void)
  76. {
  77. Proc *p;
  78. Thread *t;
  79. Resched:
  80. p = _threadgetproc();
  81. if((t = p->thread) != nil){
  82. if((ulong)&p < (ulong)t->stk) /* stack overflow */
  83. abort();
  84. _threaddebug(DBGSCHED, "pausing, state=%s", psstate(t->state));
  85. if(setjmp(t->sched)==0)
  86. longjmp(p->sched, 1);
  87. return;
  88. }else{
  89. t = runthread(p);
  90. if(t == nil){
  91. _threaddebug(DBGSCHED, "all threads gone; exiting");
  92. _schedexit(p);
  93. }
  94. _threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id);
  95. p->thread = t;
  96. if(t->moribund){
  97. _threaddebug(DBGSCHED, "%d.%d marked to die");
  98. goto Resched;
  99. }
  100. t->state = Running;
  101. t->nextstate = Ready;
  102. longjmp(t->sched, 1);
  103. }
  104. }
  105. static Thread*
  106. runthread(Proc *p)
  107. {
  108. Thread *t;
  109. Tqueue *q;
  110. if(p->nthreads==0)
  111. return nil;
  112. q = &p->ready;
  113. lock(&p->readylock);
  114. if(q->head == nil){
  115. q->asleep = 1;
  116. _threaddebug(DBGSCHED, "sleeping for more work");
  117. unlock(&p->readylock);
  118. while(rendezvous((ulong)q, 0) == ~0){
  119. if(_threadexitsallstatus)
  120. exits(_threadexitsallstatus);
  121. }
  122. /* lock picked up from _threadready */
  123. }
  124. t = q->head;
  125. q->head = t->next;
  126. unlock(&p->readylock);
  127. return t;
  128. }
  129. void
  130. _threadready(Thread *t)
  131. {
  132. Tqueue *q;
  133. assert(t->state == Ready);
  134. _threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id);
  135. q = &t->proc->ready;
  136. lock(&t->proc->readylock);
  137. t->next = nil;
  138. if(q->head==nil)
  139. q->head = t;
  140. else
  141. *q->tail = t;
  142. q->tail = &t->next;
  143. if(q->asleep){
  144. q->asleep = 0;
  145. /* lock passes to runthread */
  146. _threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
  147. while(rendezvous((ulong)q, 0) == ~0){
  148. if(_threadexitsallstatus)
  149. exits(_threadexitsallstatus);
  150. }
  151. }else
  152. unlock(&t->proc->readylock);
  153. }
  154. void
  155. yield(void)
  156. {
  157. _sched();
  158. }