Blame


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