Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | /*******************************************************************\ | |
11 | * * | |
12 | * Information Technology Center * | |
13 | * Carnegie-Mellon University * | |
14 | * * | |
15 | * * | |
16 | \*******************************************************************/ | |
17 | ||
18 | ||
19 | /* allocate externs here */ | |
20 | #include <afsconfig.h> | |
21 | #include <afs/param.h> | |
22 | ||
23 | ||
24 | #define LWP_KERNEL | |
25 | #include "lwp.h" | |
26 | ||
27 | #define NULL 0 | |
28 | ||
29 | #define ON 1 | |
30 | #define OFF 0 | |
31 | #define TRUE 1 | |
32 | #define FALSE 0 | |
33 | #define READY (1<<1) | |
34 | #define WAITING (1<<2) | |
35 | #define DESTROYED (1<<3) | |
36 | #define MAXINT (~(1<<((sizeof(int)*8)-1))) | |
37 | #define MINSTACK 44 | |
38 | ||
39 | /* Debugging macro */ | |
40 | #ifdef DEBUG | |
41 | #define Debug(level, msg)\ | |
42 | if (lwp_debug && lwp_debug >= level) {\ | |
43 | printf("***LWP (0x%x): ", lwp_cpptr);\ | |
44 | printf msg;\ | |
45 | putchar('\n');\ | |
46 | } | |
47 | ||
48 | #else | |
49 | #define Debug(level, msg) | |
50 | ||
51 | #endif | |
52 | \f | |
53 | int Dispatcher(); | |
54 | int Create_Process_Part2(); | |
55 | int Exit_LWP(); | |
56 | int Initialize_Stack(), Stack_Used(); | |
57 | char (*RC_to_ASCII()); | |
58 | ||
59 | #define MAX_PRIORITIES (LWP_MAX_PRIORITY+1) | |
60 | ||
61 | struct QUEUE { | |
62 | PROCESS head; | |
63 | int count; | |
64 | } runnable[MAX_PRIORITIES], blocked; | |
65 | ||
66 | /* Offset of stack field within pcb -- used by stack checking stuff */ | |
67 | int stack_offset; | |
68 | ||
69 | static remove(p, q) | |
70 | PROCESS p; | |
71 | struct QUEUE *q; | |
72 | { | |
73 | /* Special test for only element on queue */ | |
74 | if (q->count == 1) | |
75 | q -> head = NULL; | |
76 | else { | |
77 | /* Not only element, do normal remove */ | |
78 | p -> next -> prev = p -> prev; | |
79 | p -> prev -> next = p -> next; | |
80 | } | |
81 | /* See if head pointing to this element */ | |
82 | if (q->head == p) q -> head = p -> next; | |
83 | q->count--; | |
84 | p -> next = p -> prev = NULL; | |
85 | } | |
86 | ||
87 | static insert(p, q) | |
88 | PROCESS p; | |
89 | struct QUEUE *q; | |
90 | { | |
91 | if (q->head == NULL) { /* Queue is empty */ | |
92 | q -> head = p; | |
93 | p -> next = p -> prev = p; | |
94 | } else { /* Regular insert */ | |
95 | p -> prev = q -> head -> prev; | |
96 | q -> head -> prev -> next = p; | |
97 | q -> head -> prev = p; | |
98 | p -> next = q -> head; | |
99 | } | |
100 | q->count++; | |
101 | } | |
102 | ||
103 | static move(p, from, to) | |
104 | PROCESS p; | |
105 | struct QUEUE *from, *to; | |
106 | { | |
107 | remove(p, from); | |
108 | insert(p, to); | |
109 | } | |
110 | ||
111 | /* Iterator macro */ | |
112 | #define for_all_elts(var, q, body)\ | |
113 | {\ | |
114 | PROCESS var, _NEXT_;\ | |
115 | int _I_;\ | |
116 | for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\ | |
117 | _NEXT_ = var -> next;\ | |
118 | body\ | |
119 | }\ | |
120 | } | |
121 | \f | |
122 | /* */ | |
123 | /*****************************************************************************\ | |
124 | * * | |
125 | * Following section documents the Assembler interfaces used by LWP code * | |
126 | * * | |
127 | \*****************************************************************************/ | |
128 | ||
129 | /* | |
130 | savecontext(int (*ep)(), struct lwp_context *savearea, char *sp); | |
131 | ||
132 | Stub for Assembler routine that will | |
133 | save the current SP value in the passed | |
134 | context savearea and call the function | |
135 | whose entry point is in ep. If the sp | |
136 | parameter is NULL, the current stack is | |
137 | used, otherwise sp becomes the new stack | |
138 | pointer. | |
139 | ||
140 | returnto(struct lwp_context *savearea); | |
141 | ||
142 | Stub for Assembler routine that will | |
143 | restore context from a passed savearea | |
144 | and return to the restored C frame. | |
145 | ||
146 | */ | |
147 | ||
148 | /* Macro to force a re-schedule. Strange name is historical */ | |
149 | ||
150 | #define Set_LWP_RC(dummy) savecontext(Dispatcher, &lwp_cpptr->context, NULL) | |
151 | ||
152 | static struct lwp_ctl *lwp_init; | |
153 | ||
154 | int LWP_CreateProcess(ep, stacksize, priority, parm, name, pid) | |
155 | int (*ep)(); | |
156 | int stacksize, priority; | |
157 | char *parm; | |
158 | char *name; | |
159 | PROCESS *pid; | |
160 | { | |
161 | PROCESS temp, temp2; | |
162 | char *stackptr; | |
163 | ||
164 | Debug(0, ("Entered LWP_CreateProcess")) | |
165 | /* Throw away all dead process control blocks */ | |
166 | purge_dead_pcbs(); | |
167 | if (lwp_init) { | |
168 | temp = malloc (sizeof (struct lwp_pcb)); | |
169 | if (temp == NULL) { | |
170 | Set_LWP_RC(); | |
171 | return LWP_ENOMEM; | |
172 | } | |
173 | if (stacksize < MINSTACK) | |
174 | stacksize = 1000; | |
175 | else | |
176 | stacksize = 4 * ((stacksize+3) / 4); | |
177 | if ((stackptr = malloc(stacksize)) == NULL) { | |
178 | Set_LWP_RC(); | |
179 | return LWP_ENOMEM; | |
180 | } | |
181 | if (priority < 0 || priority >= MAX_PRIORITIES) { | |
182 | Set_LWP_RC(); | |
183 | return LWP_EBADPRI; | |
184 | } | |
185 | #ifdef DEBUG | |
186 | #ifdef STACK_USED | |
187 | Initialize_Stack(stackptr, stacksize); | |
188 | #endif | |
189 | #endif | |
190 | Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name); | |
191 | insert(temp, &runnable[priority]); | |
192 | temp2 = lwp_cpptr; | |
193 | lwp_cpptr = temp; | |
194 | savecontext(Create_Process_Part2, &temp2->context, stackptr+stacksize-4); | |
195 | Set_LWP_RC(); | |
196 | *pid = temp; | |
197 | return 0; | |
198 | } else | |
199 | return LWP_EINIT; | |
200 | } | |
201 | ||
202 | int LWP_CurrentProcess(pid) /* returns pid of current process */ | |
203 | PROCESS *pid; | |
204 | { | |
205 | Debug(0, ("Entered Current_Process")) | |
206 | if (lwp_init) { | |
207 | *pid = lwp_cpptr; | |
208 | return LWP_SUCCESS; | |
209 | } else | |
210 | return LWP_EINIT; | |
211 | } | |
212 | ||
213 | #define LWPANCHOR (*lwp_init) | |
214 | ||
215 | int LWP_DestroyProcess(pid) /* destroy a lightweight process */ | |
216 | PROCESS pid; | |
217 | { | |
218 | PROCESS temp; | |
219 | ||
220 | Debug(0, ("Entered Destroy_Process")) | |
221 | if (lwp_init) { | |
222 | if (lwp_cpptr != pid) { | |
223 | Dispose_of_Dead_PCB(pid); | |
224 | Set_LWP_RC(); | |
225 | } else { | |
226 | pid -> status = DESTROYED; | |
227 | move(pid, &runnable[pid->priority], &blocked); | |
228 | temp = lwp_cpptr; | |
229 | savecontext(Dispatcher, &(temp -> context), | |
230 | &(LWPANCHOR.dsptchstack[(sizeof LWPANCHOR.dsptchstack)-4])); | |
231 | } | |
232 | return LWP_SUCCESS; | |
233 | } else | |
234 | return LWP_EINIT; | |
235 | } | |
236 | ||
237 | int LWP_DispatchProcess() /* explicit voluntary preemption */ | |
238 | { | |
239 | Debug(2, ("Entered Dispatch_Process")) | |
240 | if (lwp_init) { | |
241 | Set_LWP_RC(); | |
242 | return LWP_SUCCESS; | |
243 | } else | |
244 | return LWP_EINIT; | |
245 | } | |
246 | ||
247 | #ifdef DEBUG | |
248 | Dump_Processes() | |
249 | { | |
250 | if (lwp_init) { | |
251 | int i; | |
252 | for (i=0; i<MAX_PRIORITIES; i++) | |
253 | for_all_elts(x, runnable[i], { | |
254 | printf("[Priority %d]\n", i); | |
255 | Dump_One_Process(x); | |
256 | }) | |
257 | for_all_elts(x, blocked, { Dump_One_Process(x); }) | |
258 | } else | |
259 | printf("***LWP: LWP support not initialized\n"); | |
260 | } | |
261 | #endif | |
262 | ||
263 | int LWP_GetProcessPriority(pid, priority) /* returns process priority */ | |
264 | PROCESS pid; | |
265 | int *priority; | |
266 | { | |
267 | Debug(0, ("Entered Get_Process_Priority")) | |
268 | if (lwp_init) { | |
269 | *priority = pid -> priority; | |
270 | return 0; | |
271 | } else | |
272 | return LWP_EINIT; | |
273 | } | |
274 | ||
275 | int LWP_InitializeProcessSupport(priority, pid) | |
276 | int priority; | |
277 | PROCESS *pid; | |
278 | { | |
279 | PROCESS temp; | |
280 | struct lwp_pcb dummy; | |
281 | int i; | |
282 | ||
283 | Debug(0, ("Entered LWP_InitializeProcessSupport")) | |
284 | if (lwp_init != NULL) return LWP_EINIT; | |
285 | ||
286 | /* Set up offset for stack checking -- do this as soon as possible */ | |
287 | stack_offset = (char *) &dummy.stack - (char *) &dummy; | |
288 | ||
289 | if (priority >= MAX_PRIORITIES) return LWP_EBADPRI; | |
290 | for (i=0; i<MAX_PRIORITIES; i++) { | |
291 | runnable[i].head = NULL; | |
292 | runnable[i].count = 0; | |
293 | } | |
294 | blocked.head = NULL; | |
295 | blocked.count = 0; | |
296 | lwp_init = malloc(sizeof(struct lwp_ctl)); | |
297 | temp = malloc(sizeof(struct lwp_pcb)); | |
298 | if (lwp_init == NULL || temp == NULL) | |
299 | Abort_LWP("Insufficient Storage to Initialize LWP Support"); | |
300 | LWPANCHOR.processcnt = 1; | |
301 | LWPANCHOR.outerpid = temp; | |
302 | LWPANCHOR.outersp = NULL; | |
303 | Initialize_PCB(temp, priority, NULL, 0, NULL, NULL, "Main Process [created by LWP]"); | |
304 | insert(temp, &runnable[priority]); | |
305 | savecontext(Dispatcher, &temp->context, NULL); | |
306 | LWPANCHOR.outersp = temp -> context.topstack; | |
307 | Set_LWP_RC(); | |
308 | *pid = temp; | |
309 | return LWP_SUCCESS; | |
310 | } | |
311 | ||
312 | int LWP_INTERNALSIGNAL(event, yield) /* signal the occurence of an event */ | |
313 | char *event; | |
314 | int yield; | |
315 | { | |
316 | Debug(2, ("Entered LWP_SignalProcess")) | |
317 | if (lwp_init) { | |
318 | int rc; | |
319 | rc = Internal_Signal(event); | |
320 | if (yield) Set_LWP_RC(); | |
321 | return rc; | |
322 | } else | |
323 | return LWP_EINIT; | |
324 | } | |
325 | ||
326 | int LWP_TerminateProcessSupport() /* terminate all LWP support */ | |
327 | { | |
328 | int pc; | |
329 | int i; | |
330 | ||
331 | Debug(0, ("Entered Terminate_Process_Support")) | |
332 | if (lwp_init == NULL) return LWP_EINIT; | |
333 | if (lwp_cpptr != LWPANCHOR.outerpid) | |
334 | Abort_LWP("Terminate_Process_Support invoked from wrong process!"); | |
335 | pc = LWPANCHOR.processcnt-1; | |
336 | for (i=0; i<MAX_PRIORITIES; i++) | |
337 | for_all_elts(cur, runnable[i], { Free_PCB(cur); }) | |
338 | for_all_elts(cur, blocked, { Free_PCB(cur); }) | |
339 | free(lwp_init); | |
340 | lwp_init = NULL; | |
341 | return LWP_SUCCESS; | |
342 | } | |
343 | ||
344 | int LWP_WaitProcess(event) /* wait on a single event */ | |
345 | char *event; | |
346 | { | |
347 | char *tempev[2]; | |
348 | ||
349 | Debug(2, ("Entered Wait_Process")) | |
350 | if (event == NULL) return LWP_EBADEVENT; | |
351 | tempev[0] = event; | |
352 | tempev[1] = NULL; | |
353 | return LWP_MwaitProcess(1, tempev); | |
354 | } | |
355 | ||
356 | int LWP_MwaitProcess(wcount, evlist, ecount) /* wait on m of n events */ | |
357 | int wcount, ecount; | |
358 | char *evlist[]; | |
359 | { | |
360 | Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount)) | |
361 | ||
362 | if (ecount == 0) { | |
363 | Set_LWP_RC(); | |
364 | return LWP_EBADCOUNT; | |
365 | } | |
366 | if (lwp_init) { | |
367 | if (wcount>ecount || wcount<0) { | |
368 | Set_LWP_RC(); | |
369 | return LWP_EBADCOUNT; | |
370 | } | |
371 | if (ecount > LWP_MAX_EVENTS) { | |
372 | Set_LWP_RC(); | |
373 | return LWP_EBADCOUNT; | |
374 | } | |
375 | if (ecount == 1) | |
376 | lwp_cpptr->eventlist[0] = evlist[0]; | |
377 | else | |
378 | memcpy(lwp_cpptr->eventlist, evlist, ecount*sizeof(char *)); | |
379 | if (wcount > 0) { | |
380 | lwp_cpptr -> status = WAITING; | |
381 | move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked); | |
382 | } | |
383 | lwp_cpptr -> wakevent = 0; | |
384 | lwp_cpptr -> waitcnt = wcount; | |
385 | lwp_cpptr -> eventcnt = ecount; | |
386 | Set_LWP_RC(); | |
387 | return LWP_SUCCESS; | |
388 | } | |
389 | return LWP_EINIT; | |
390 | } | |
391 | ||
392 | int LWP_StackUsed(pid, max, used) | |
393 | PROCESS pid; | |
394 | int *max, *used; | |
395 | { | |
396 | #define NO_STACK_STUFF | |
397 | #ifdef DEBUG | |
398 | #ifdef STACK_USED | |
399 | #undef NO_STACK_STUFF | |
400 | #endif | |
401 | #endif | |
402 | ||
403 | #ifdef NO_STACK_STUFF | |
404 | return LWP_NO_STACK; | |
405 | #else | |
406 | *max = pid -> stacksize; | |
407 | *used = Stack_Used(pid->stack, *max); | |
408 | return LWP_SUCCESS; | |
409 | #endif | |
410 | } | |
411 | \f | |
412 | /* | |
413 | * The following functions are strictly | |
414 | * INTERNAL to the LWP support package. | |
415 | */ | |
416 | ||
417 | static Abort_LWP(msg) | |
418 | char *msg; | |
419 | { | |
420 | struct lwp_context tempcontext; | |
421 | ||
422 | Debug(0, ("Entered Abort_LWP")) | |
423 | printf("***LWP: %s\n",msg); | |
424 | printf("***LWP: Abort --- dumping PCBs ...\n"); | |
425 | #ifdef DEBUG | |
426 | Dump_Processes(); | |
427 | #endif | |
428 | if (LWPANCHOR.outersp == NULL) | |
429 | Exit_LWP(); | |
430 | else | |
431 | savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp); | |
432 | } | |
433 | ||
434 | static Create_Process_Part2 () /* creates a context for the new process */ | |
435 | { | |
436 | PROCESS temp; | |
437 | ||
438 | Debug(2, ("Entered Create_Process_Part2")) | |
439 | temp = lwp_cpptr; /* Get current process id */ | |
440 | savecontext(Dispatcher, &temp->context, NULL); | |
441 | (*temp->ep)(temp->parm); | |
442 | LWP_DestroyProcess(temp); | |
443 | } | |
444 | ||
445 | static Delete_PCB(pid) /* remove a PCB from the process list */ | |
446 | PROCESS pid; | |
447 | { | |
448 | Debug(4, ("Entered Delete_PCB")) | |
449 | remove(pid, (pid->blockflag || pid->status==WAITING || pid->status==DESTROYED | |
450 | ? &blocked | |
451 | : &runnable[pid->priority])); | |
452 | LWPANCHOR.processcnt--; | |
453 | } | |
454 | ||
455 | #ifdef DEBUG | |
456 | static Dump_One_Process(pid) | |
457 | PROCESS pid; | |
458 | { | |
459 | int i; | |
460 | ||
461 | printf("***LWP: Process Control Block at 0x%x\n", pid); | |
462 | printf("***LWP: Name: %s\n", pid->name); | |
463 | if (pid->ep != NULL) | |
464 | printf("***LWP: Initial entry point: 0x%x\n", pid->ep); | |
465 | if (pid->blockflag) printf("BLOCKED and "); | |
466 | switch (pid->status) { | |
467 | case READY: printf("READY"); break; | |
468 | case WAITING: printf("WAITING"); break; | |
469 | case DESTROYED: printf("DESTROYED"); break; | |
470 | default: printf("unknown"); | |
471 | } | |
472 | putchar('\n'); | |
473 | printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n", | |
474 | pid->priority, pid->parm); | |
475 | if (pid->stacksize != 0) { | |
476 | printf("***LWP: Stacksize: %d \tStack base address: 0x%x\n", | |
477 | pid->stacksize, pid->stack); | |
478 | printf("***LWP: HWM stack usage: "); | |
479 | printf("%d\n", Stack_Used(pid->stack,pid->stacksize)); | |
480 | free (pid->stack); | |
481 | } | |
482 | printf("***LWP: Current Stack Pointer: 0x%x\n", pid->context.topstack); | |
483 | if (pid->eventcnt > 0) { | |
484 | printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt); | |
485 | printf("***LWP: Event id list:"); | |
486 | for (i=0;i<pid->eventcnt;i++) | |
487 | printf(" 0x%x", pid->eventlist[i]); | |
488 | putchar('\n'); | |
489 | } | |
490 | if (pid->wakevent>0) | |
491 | printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent); | |
492 | } | |
493 | #endif | |
494 | ||
495 | static purge_dead_pcbs() | |
496 | { | |
497 | for_all_elts(cur, blocked, { if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur); }) | |
498 | } | |
499 | ||
500 | int LWP_TraceProcesses = 0; | |
501 | ||
502 | static Dispatcher() /* Lightweight process dispatcher */ | |
503 | { | |
504 | int i; | |
505 | #ifdef DEBUG | |
506 | static int dispatch_count = 0; | |
507 | ||
508 | if (LWP_TraceProcesses > 0) { | |
509 | for (i=0; i<MAX_PRIORITIES; i++) { | |
510 | printf("[Priority %d, runnable (%d):", i, runnable[i].count); | |
511 | for_all_elts(p, runnable[i], { | |
512 | printf(" \"%s\"", p->name); | |
513 | }) | |
514 | puts("]"); | |
515 | } | |
516 | printf("[Blocked (%d):", blocked.count); | |
517 | for_all_elts(p, blocked, { | |
518 | printf(" \"%s\"", p->name); | |
519 | }) | |
520 | puts("]"); | |
521 | } | |
522 | #endif | |
523 | ||
524 | for (i=MAX_PRIORITIES-1; i>=0; i--) | |
525 | if (runnable[i].head != NULL) break; | |
526 | ||
527 | if (i < 0) Abort_LWP("No READY processes"); | |
528 | ||
529 | #ifdef DEBUG | |
530 | if (LWP_TraceProcesses > 0) | |
531 | printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count, runnable[i].head, runnable[i].head->name); | |
532 | #endif | |
533 | lwp_cpptr = runnable[i].head; | |
534 | runnable[i].head = runnable[i].head -> next; | |
535 | returnto(&lwp_cpptr->context); | |
536 | } | |
537 | ||
538 | static Dispose_of_Dead_PCB (cur) | |
539 | PROCESS cur; | |
540 | { | |
541 | Debug(4, ("Entered Dispose_of_Dead_PCB")) | |
542 | Delete_PCB(cur); | |
543 | Free_PCB(cur); | |
544 | /* | |
545 | Internal_Signal(cur); | |
546 | */ | |
547 | } | |
548 | ||
549 | static Exit_LWP() | |
550 | { | |
551 | abort(); | |
552 | } | |
553 | ||
554 | static Free_PCB(pid) | |
555 | PROCESS pid; | |
556 | { | |
557 | Debug(4, ("Entered Free_PCB")) | |
558 | if (pid -> stack != NULL) { | |
559 | Debug(0, ("HWM stack usage: %d, [PCB at 0x%x]", | |
560 | Stack_Used(pid->stack,pid->stacksize), pid)) | |
561 | free(pid -> stack); | |
562 | } | |
563 | free(pid); | |
564 | } | |
565 | ||
566 | static Initialize_PCB(temp, priority, stack, stacksize, ep, parm, name) | |
567 | PROCESS temp; | |
568 | int (*ep)(); | |
569 | int stacksize, priority; | |
570 | char *parm; | |
571 | char *name,*stack; | |
572 | { | |
573 | int i = 0; | |
574 | ||
575 | Debug(4, ("Entered Initialize_PCB")) | |
576 | if (name != NULL) | |
577 | while (((temp -> name[i] = name[i]) != '\0') && (i < 31)) i++; | |
578 | temp -> name[31] = '\0'; | |
579 | temp -> status = READY; | |
580 | temp -> eventcnt = 0; | |
581 | temp -> wakevent = 0; | |
582 | temp -> waitcnt = 0; | |
583 | temp -> blockflag = 0; | |
584 | temp -> priority = priority; | |
585 | temp -> stack = stack; | |
586 | temp -> stacksize = stacksize; | |
587 | temp -> ep = ep; | |
588 | temp -> parm = parm; | |
589 | temp -> misc = NULL; /* currently unused */ | |
590 | temp -> next = NULL; | |
591 | temp -> prev = NULL; | |
592 | } | |
593 | ||
594 | static int Internal_Signal(event) | |
595 | char *event; | |
596 | { | |
597 | int rc = LWP_ENOWAIT; | |
598 | int i; | |
599 | ||
600 | Debug(0, ("Entered Internal_Signal [event id 0x%x]", event)) | |
601 | if (!lwp_init) return LWP_EINIT; | |
602 | if (event == NULL) return LWP_EBADEVENT; | |
603 | for_all_elts(temp, blocked, { | |
604 | if (temp->status == WAITING) | |
605 | for (i=0; i < temp->eventcnt; i++) { | |
606 | if (temp -> eventlist[i] == event) { | |
607 | temp -> eventlist[i] = NULL; | |
608 | rc = LWP_SUCCESS; | |
609 | Debug(0, ("Signal satisfied for PCB 0x%x", temp)) | |
610 | if (--temp->waitcnt == 0) { | |
611 | temp -> status = READY; | |
612 | temp -> wakevent = i+1; | |
613 | move(temp, &blocked, &runnable[temp->priority]); | |
614 | break; | |
615 | } | |
616 | } | |
617 | } | |
618 | }) | |
619 | return rc; | |
620 | } | |
621 | ||
622 | #ifdef DEBUG | |
623 | #ifdef STACK_USED | |
624 | static Initialize_Stack(stackptr, stacksize) | |
625 | char *stackptr; | |
626 | int stacksize; | |
627 | { | |
628 | int i; | |
629 | ||
630 | Debug(4, ("Entered Initialize_Stack")) | |
631 | for (i=0; i<stacksize; i++) stackptr[i] = i & 0xff; | |
632 | } | |
633 | ||
634 | static int Stack_Used(stackptr, stacksize) | |
635 | char *stackptr; | |
636 | int stacksize; | |
637 | { | |
638 | int i; | |
639 | ||
640 | for (i=0;i<stacksize;i++) | |
641 | if ((unsigned char) stackptr[i] != (i & 0xff)) | |
642 | return (stacksize-i); | |
643 | return 0; | |
644 | } | |
645 | #endif | |
646 | #endif |