Blame


1 a0f1e21f 2004-04-20 devnull #include <u.h>
2 76193d7c 2003-09-30 devnull #include <signal.h>
3 5a8e63b2 2004-02-29 devnull #include <errno.h>
4 cd7ddc9b 2003-11-23 devnull #include "threadimpl.h"
5 76193d7c 2003-09-30 devnull
6 76193d7c 2003-09-30 devnull //static Thread *runthread(Proc*);
7 76193d7c 2003-09-30 devnull
8 76193d7c 2003-09-30 devnull static char *_psstate[] = {
9 76193d7c 2003-09-30 devnull "Dead",
10 76193d7c 2003-09-30 devnull "Running",
11 76193d7c 2003-09-30 devnull "Ready",
12 76193d7c 2003-09-30 devnull "Rendezvous",
13 76193d7c 2003-09-30 devnull };
14 76193d7c 2003-09-30 devnull
15 76193d7c 2003-09-30 devnull static char*
16 76193d7c 2003-09-30 devnull psstate(int s)
17 76193d7c 2003-09-30 devnull {
18 76193d7c 2003-09-30 devnull if(s < 0 || s >= nelem(_psstate))
19 76193d7c 2003-09-30 devnull return "unknown";
20 76193d7c 2003-09-30 devnull return _psstate[s];
21 76193d7c 2003-09-30 devnull }
22 76193d7c 2003-09-30 devnull
23 76193d7c 2003-09-30 devnull void
24 76193d7c 2003-09-30 devnull _schedinit(void *arg)
25 76193d7c 2003-09-30 devnull {
26 76193d7c 2003-09-30 devnull Proc *p;
27 76193d7c 2003-09-30 devnull Thread *t;
28 76193d7c 2003-09-30 devnull extern void ignusr1(void), _threaddie(int);
29 76193d7c 2003-09-30 devnull ignusr1();
30 76193d7c 2003-09-30 devnull signal(SIGTERM, _threaddie);
31 76193d7c 2003-09-30 devnull
32 76193d7c 2003-09-30 devnull p = arg;
33 cd7ddc9b 2003-11-23 devnull lock(&p->lock);
34 76193d7c 2003-09-30 devnull p->pid = _threadgetpid();
35 76193d7c 2003-09-30 devnull _threadsetproc(p);
36 cd7ddc9b 2003-11-23 devnull unlock(&p->lock);
37 76193d7c 2003-09-30 devnull while(_setlabel(&p->sched))
38 76193d7c 2003-09-30 devnull ;
39 76193d7c 2003-09-30 devnull _threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
40 76193d7c 2003-09-30 devnull if(_threadexitsallstatus)
41 76193d7c 2003-09-30 devnull exits(_threadexitsallstatus);
42 76193d7c 2003-09-30 devnull lock(&p->lock);
43 76193d7c 2003-09-30 devnull if((t=p->thread) != nil){
44 76193d7c 2003-09-30 devnull p->thread = nil;
45 76193d7c 2003-09-30 devnull if(t->moribund){
46 912fba95 2003-11-24 devnull if(t->moribund != 1)
47 912fba95 2003-11-24 devnull fprint(2, "moribund %d\n", t->moribund);
48 76193d7c 2003-09-30 devnull assert(t->moribund == 1);
49 76193d7c 2003-09-30 devnull t->state = Dead;
50 76193d7c 2003-09-30 devnull if(t->prevt)
51 76193d7c 2003-09-30 devnull t->prevt->nextt = t->nextt;
52 76193d7c 2003-09-30 devnull else
53 76193d7c 2003-09-30 devnull p->threads.head = t->nextt;
54 76193d7c 2003-09-30 devnull if(t->nextt)
55 76193d7c 2003-09-30 devnull t->nextt->prevt = t->prevt;
56 76193d7c 2003-09-30 devnull else
57 76193d7c 2003-09-30 devnull p->threads.tail = t->prevt;
58 76193d7c 2003-09-30 devnull unlock(&p->lock);
59 76193d7c 2003-09-30 devnull if(t->inrendez){
60 76193d7c 2003-09-30 devnull _threadflagrendez(t);
61 76193d7c 2003-09-30 devnull _threadbreakrendez();
62 76193d7c 2003-09-30 devnull }
63 76193d7c 2003-09-30 devnull _stackfree(t->stk);
64 76193d7c 2003-09-30 devnull free(t->cmdname);
65 76193d7c 2003-09-30 devnull free(t); /* XXX how do we know there are no references? */
66 cd7ddc9b 2003-11-23 devnull p->nthreads--;
67 76193d7c 2003-09-30 devnull t = nil;
68 76193d7c 2003-09-30 devnull _sched();
69 76193d7c 2003-09-30 devnull }
70 5a8e63b2 2004-02-29 devnull /*
71 76193d7c 2003-09-30 devnull if(p->needexec){
72 76193d7c 2003-09-30 devnull t->ret = _schedexec(&p->exec);
73 76193d7c 2003-09-30 devnull p->needexec = 0;
74 76193d7c 2003-09-30 devnull }
75 5a8e63b2 2004-02-29 devnull */
76 76193d7c 2003-09-30 devnull if(p->newproc){
77 76193d7c 2003-09-30 devnull t->ret = _schedfork(p->newproc);
78 76193d7c 2003-09-30 devnull if(t->ret < 0){
79 76193d7c 2003-09-30 devnull //fprint(2, "_schedfork: %r\n");
80 76193d7c 2003-09-30 devnull abort();
81 76193d7c 2003-09-30 devnull }
82 76193d7c 2003-09-30 devnull p->newproc = nil;
83 76193d7c 2003-09-30 devnull }
84 76193d7c 2003-09-30 devnull t->state = t->nextstate;
85 76193d7c 2003-09-30 devnull if(t->state == Ready)
86 76193d7c 2003-09-30 devnull _threadready(t);
87 76193d7c 2003-09-30 devnull }
88 76193d7c 2003-09-30 devnull unlock(&p->lock);
89 76193d7c 2003-09-30 devnull _sched();
90 76193d7c 2003-09-30 devnull }
91 76193d7c 2003-09-30 devnull
92 50e628cb 2003-11-23 devnull static Thread*
93 76193d7c 2003-09-30 devnull runthread(Proc *p)
94 76193d7c 2003-09-30 devnull {
95 5a8e63b2 2004-02-29 devnull Channel *c;
96 76193d7c 2003-09-30 devnull Thread *t;
97 76193d7c 2003-09-30 devnull Tqueue *q;
98 5a8e63b2 2004-02-29 devnull Waitmsg *w;
99 5a8e63b2 2004-02-29 devnull int e, sent;
100 76193d7c 2003-09-30 devnull
101 e97ceade 2003-12-06 devnull if(p->nthreads==0 || (p->nthreads==1 && p->idle))
102 76193d7c 2003-09-30 devnull return nil;
103 76193d7c 2003-09-30 devnull q = &p->ready;
104 5a8e63b2 2004-02-29 devnull relock:
105 76193d7c 2003-09-30 devnull lock(&p->readylock);
106 76193d7c 2003-09-30 devnull if(q->head == nil){
107 5a8e63b2 2004-02-29 devnull e = errno;
108 5a8e63b2 2004-02-29 devnull if((c = _threadwaitchan) != nil){
109 5a8e63b2 2004-02-29 devnull if(c->n <= c->s){
110 5a8e63b2 2004-02-29 devnull sent = 0;
111 5a8e63b2 2004-02-29 devnull for(;;){
112 5a8e63b2 2004-02-29 devnull if((w = p->waitmsg) != nil)
113 5a8e63b2 2004-02-29 devnull p->waitmsg = nil;
114 5a8e63b2 2004-02-29 devnull else
115 5a8e63b2 2004-02-29 devnull w = waitnohang();
116 5a8e63b2 2004-02-29 devnull if(w == nil)
117 5a8e63b2 2004-02-29 devnull break;
118 5a8e63b2 2004-02-29 devnull if(sent == 0){
119 5a8e63b2 2004-02-29 devnull unlock(&p->readylock);
120 5a8e63b2 2004-02-29 devnull sent = 1;
121 5a8e63b2 2004-02-29 devnull }
122 5a8e63b2 2004-02-29 devnull if(nbsendp(c, w) != 1)
123 5a8e63b2 2004-02-29 devnull break;
124 5a8e63b2 2004-02-29 devnull }
125 5a8e63b2 2004-02-29 devnull p->waitmsg = w;
126 5a8e63b2 2004-02-29 devnull if(sent)
127 5a8e63b2 2004-02-29 devnull goto relock;
128 5a8e63b2 2004-02-29 devnull }
129 5a8e63b2 2004-02-29 devnull }else{
130 5a8e63b2 2004-02-29 devnull while((w = waitnohang()) != nil)
131 5a8e63b2 2004-02-29 devnull free(w);
132 5a8e63b2 2004-02-29 devnull }
133 5a8e63b2 2004-02-29 devnull errno = e;
134 e97ceade 2003-12-06 devnull if(p->idle){
135 e97ceade 2003-12-06 devnull if(p->idle->state != Ready){
136 e97ceade 2003-12-06 devnull fprint(2, "everyone is asleep\n");
137 e97ceade 2003-12-06 devnull exits("everyone is asleep");
138 e97ceade 2003-12-06 devnull }
139 e97ceade 2003-12-06 devnull unlock(&p->readylock);
140 32f69c36 2003-12-11 devnull _threaddebug(DBGSCHED, "running idle thread", p->nthreads);
141 e97ceade 2003-12-06 devnull return p->idle;
142 e97ceade 2003-12-06 devnull }
143 e97ceade 2003-12-06 devnull
144 cd7ddc9b 2003-11-23 devnull _threaddebug(DBGSCHED, "sleeping for more work (%d threads)", p->nthreads);
145 32f69c36 2003-12-11 devnull q->asleep = 1;
146 76193d7c 2003-09-30 devnull unlock(&p->readylock);
147 76193d7c 2003-09-30 devnull while(rendezvous((ulong)q, 0) == ~0){
148 76193d7c 2003-09-30 devnull if(_threadexitsallstatus)
149 76193d7c 2003-09-30 devnull exits(_threadexitsallstatus);
150 76193d7c 2003-09-30 devnull }
151 76193d7c 2003-09-30 devnull /* lock picked up from _threadready */
152 76193d7c 2003-09-30 devnull }
153 76193d7c 2003-09-30 devnull t = q->head;
154 76193d7c 2003-09-30 devnull q->head = t->next;
155 76193d7c 2003-09-30 devnull unlock(&p->readylock);
156 76193d7c 2003-09-30 devnull return t;
157 fb36ed82 2004-04-21 devnull }
158 fb36ed82 2004-04-21 devnull
159 fb36ed82 2004-04-21 devnull void
160 fb36ed82 2004-04-21 devnull needstack(int howmuch)
161 fb36ed82 2004-04-21 devnull {
162 fb36ed82 2004-04-21 devnull Proc *p;
163 fb36ed82 2004-04-21 devnull Thread *t;
164 fb36ed82 2004-04-21 devnull
165 fb36ed82 2004-04-21 devnull p = _threadgetproc();
166 fb36ed82 2004-04-21 devnull if(p == nil || (t=p->thread) == nil)
167 fb36ed82 2004-04-21 devnull return;
168 fb36ed82 2004-04-21 devnull if((ulong)&howmuch < (ulong)t->stk+howmuch){ /* stack overflow waiting to happen */
169 fb36ed82 2004-04-21 devnull fprint(2, "stack overflow: stack at 0x%lux, limit at 0x%lux, need 0x%lux\n", (ulong)&p, (ulong)t->stk, howmuch);
170 fb36ed82 2004-04-21 devnull abort();
171 fb36ed82 2004-04-21 devnull }
172 76193d7c 2003-09-30 devnull }
173 76193d7c 2003-09-30 devnull
174 76193d7c 2003-09-30 devnull void
175 76193d7c 2003-09-30 devnull _sched(void)
176 76193d7c 2003-09-30 devnull {
177 76193d7c 2003-09-30 devnull Proc *p;
178 76193d7c 2003-09-30 devnull Thread *t;
179 76193d7c 2003-09-30 devnull
180 76193d7c 2003-09-30 devnull Resched:
181 76193d7c 2003-09-30 devnull p = _threadgetproc();
182 76193d7c 2003-09-30 devnull //fprint(2, "p %p\n", p);
183 76193d7c 2003-09-30 devnull if((t = p->thread) != nil){
184 fb36ed82 2004-04-21 devnull needstack(512);
185 76193d7c 2003-09-30 devnull // _threaddebug(DBGSCHED, "pausing, state=%s set %p goto %p",
186 76193d7c 2003-09-30 devnull // psstate(t->state), &t->sched, &p->sched);
187 76193d7c 2003-09-30 devnull if(_setlabel(&t->sched)==0)
188 76193d7c 2003-09-30 devnull _gotolabel(&p->sched);
189 a3785ca2 2004-04-21 devnull _threadstacklimit(t->stk);
190 76193d7c 2003-09-30 devnull return;
191 76193d7c 2003-09-30 devnull }else{
192 76193d7c 2003-09-30 devnull t = runthread(p);
193 76193d7c 2003-09-30 devnull if(t == nil){
194 76193d7c 2003-09-30 devnull _threaddebug(DBGSCHED, "all threads gone; exiting");
195 76193d7c 2003-09-30 devnull _threaddelproc();
196 76193d7c 2003-09-30 devnull _schedexit(p);
197 76193d7c 2003-09-30 devnull }
198 32f69c36 2003-12-11 devnull _threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id);
199 76193d7c 2003-09-30 devnull p->thread = t;
200 76193d7c 2003-09-30 devnull if(t->moribund){
201 76193d7c 2003-09-30 devnull _threaddebug(DBGSCHED, "%d.%d marked to die");
202 76193d7c 2003-09-30 devnull goto Resched;
203 76193d7c 2003-09-30 devnull }
204 76193d7c 2003-09-30 devnull t->state = Running;
205 76193d7c 2003-09-30 devnull t->nextstate = Ready;
206 76193d7c 2003-09-30 devnull _gotolabel(&t->sched);
207 76193d7c 2003-09-30 devnull }
208 76193d7c 2003-09-30 devnull }
209 76193d7c 2003-09-30 devnull
210 76193d7c 2003-09-30 devnull long
211 76193d7c 2003-09-30 devnull threadstack(void)
212 76193d7c 2003-09-30 devnull {
213 76193d7c 2003-09-30 devnull Proc *p;
214 76193d7c 2003-09-30 devnull Thread *t;
215 76193d7c 2003-09-30 devnull
216 76193d7c 2003-09-30 devnull p = _threadgetproc();
217 76193d7c 2003-09-30 devnull t = p->thread;
218 76193d7c 2003-09-30 devnull return (ulong)&p - (ulong)t->stk;
219 76193d7c 2003-09-30 devnull }
220 76193d7c 2003-09-30 devnull
221 76193d7c 2003-09-30 devnull void
222 76193d7c 2003-09-30 devnull _threadready(Thread *t)
223 76193d7c 2003-09-30 devnull {
224 76193d7c 2003-09-30 devnull Tqueue *q;
225 76193d7c 2003-09-30 devnull
226 32f69c36 2003-12-11 devnull if(t == t->proc->idle){
227 32f69c36 2003-12-11 devnull _threaddebug(DBGSCHED, "idle thread is ready");
228 e97ceade 2003-12-06 devnull return;
229 32f69c36 2003-12-11 devnull }
230 e97ceade 2003-12-06 devnull
231 76193d7c 2003-09-30 devnull assert(t->state == Ready);
232 76193d7c 2003-09-30 devnull _threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id);
233 76193d7c 2003-09-30 devnull q = &t->proc->ready;
234 76193d7c 2003-09-30 devnull lock(&t->proc->readylock);
235 76193d7c 2003-09-30 devnull t->next = nil;
236 76193d7c 2003-09-30 devnull if(q->head==nil)
237 76193d7c 2003-09-30 devnull q->head = t;
238 76193d7c 2003-09-30 devnull else
239 76193d7c 2003-09-30 devnull q->tail->next = t;
240 76193d7c 2003-09-30 devnull q->tail = t;
241 76193d7c 2003-09-30 devnull if(q->asleep){
242 cd7ddc9b 2003-11-23 devnull assert(q->asleep == 1);
243 76193d7c 2003-09-30 devnull q->asleep = 0;
244 76193d7c 2003-09-30 devnull /* lock passes to runthread */
245 76193d7c 2003-09-30 devnull _threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
246 76193d7c 2003-09-30 devnull while(rendezvous((ulong)q, 0) == ~0){
247 76193d7c 2003-09-30 devnull if(_threadexitsallstatus)
248 76193d7c 2003-09-30 devnull exits(_threadexitsallstatus);
249 76193d7c 2003-09-30 devnull }
250 76193d7c 2003-09-30 devnull }else
251 76193d7c 2003-09-30 devnull unlock(&t->proc->readylock);
252 76193d7c 2003-09-30 devnull }
253 76193d7c 2003-09-30 devnull
254 76193d7c 2003-09-30 devnull void
255 e97ceade 2003-12-06 devnull _threadidle(void)
256 e97ceade 2003-12-06 devnull {
257 e97ceade 2003-12-06 devnull Tqueue *q;
258 32f69c36 2003-12-11 devnull Thread *t, *idle;
259 e97ceade 2003-12-06 devnull Proc *p;
260 e97ceade 2003-12-06 devnull
261 e97ceade 2003-12-06 devnull p = _threadgetproc();
262 e97ceade 2003-12-06 devnull q = &p->ready;
263 e97ceade 2003-12-06 devnull lock(&p->readylock);
264 32f69c36 2003-12-11 devnull assert(q->tail);
265 32f69c36 2003-12-11 devnull idle = q->tail;
266 32f69c36 2003-12-11 devnull if(q->head == idle){
267 32f69c36 2003-12-11 devnull q->head = nil;
268 e97ceade 2003-12-06 devnull q->tail = nil;
269 32f69c36 2003-12-11 devnull }else{
270 32f69c36 2003-12-11 devnull for(t=q->head; t->next!=q->tail; t=t->next)
271 32f69c36 2003-12-11 devnull ;
272 32f69c36 2003-12-11 devnull t->next = nil;
273 32f69c36 2003-12-11 devnull q->tail = t;
274 32f69c36 2003-12-11 devnull }
275 32f69c36 2003-12-11 devnull p->idle = idle;
276 32f69c36 2003-12-11 devnull _threaddebug(DBGSCHED, "p->idle is %d\n", idle->id);
277 e97ceade 2003-12-06 devnull unlock(&p->readylock);
278 e97ceade 2003-12-06 devnull }
279 e97ceade 2003-12-06 devnull
280 e97ceade 2003-12-06 devnull void
281 76193d7c 2003-09-30 devnull yield(void)
282 76193d7c 2003-09-30 devnull {
283 76193d7c 2003-09-30 devnull _sched();
284 76193d7c 2003-09-30 devnull }
285 02a1a5c1 2004-03-05 devnull
286 02a1a5c1 2004-03-05 devnull void
287 02a1a5c1 2004-03-05 devnull threadstatus(void)
288 02a1a5c1 2004-03-05 devnull {
289 02a1a5c1 2004-03-05 devnull Proc *p;
290 02a1a5c1 2004-03-05 devnull Thread *t;
291 76193d7c 2003-09-30 devnull
292 02a1a5c1 2004-03-05 devnull p = _threadgetproc();
293 02a1a5c1 2004-03-05 devnull for(t=p->threads.head; t; t=t->nextt)
294 02a1a5c1 2004-03-05 devnull fprint(2, "[%3d] %s userpc=%lux\n",
295 02a1a5c1 2004-03-05 devnull t->id, psstate(t->state), t->userpc);
296 02a1a5c1 2004-03-05 devnull }
297 02a1a5c1 2004-03-05 devnull