This source file includes following definitions.
- runq_top
- runq_enqueue
- runq_insert
- runq_dequeue
- runq_remove
- wakeq_flush
- sleep_expire
- sched_switch
- sched_tsleep
- sched_wakeup
- sched_wakeone
- sched_unsleep
- sched_yield
- sched_suspend
- sched_resume
- sched_tick
- sched_start
- sched_stop
- sched_lock
- sched_unlock
- sched_getprio
- sched_setprio
- sched_getpolicy
- sched_setpolicy
- dpc_thread
- sched_dpc
- sched_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 #include <kernel.h>
88 #include <queue.h>
89 #include <event.h>
90 #include <irq.h>
91 #include <thread.h>
92 #include <timer.h>
93 #include <vm.h>
94 #include <task.h>
95 #include <system.h>
96 #include <sched.h>
97
98 static struct queue runq[NR_PRIOS];
99 static struct queue wakeq;
100 static struct queue dpcq;
101 static int top_prio;
102
103 static struct event dpc_event;
104
105
106
107
108 static int
109 runq_top(void)
110 {
111 int prio;
112
113 for (prio = 0; prio < MIN_PRIO; prio++)
114 if (!queue_empty(&runq[prio]))
115 break;
116 return prio;
117 }
118
119
120
121
122
123
124 static void
125 runq_enqueue(thread_t th)
126 {
127
128 enqueue(&runq[th->prio], &th->link);
129 if (th->prio < top_prio) {
130 top_prio = th->prio;
131 cur_thread->need_resched = 1;
132 }
133 }
134
135
136
137
138
139
140 static void
141 runq_insert(thread_t th)
142 {
143
144 queue_insert(&runq[th->prio], &th->link);
145 if (th->prio < top_prio)
146 top_prio = th->prio;
147 }
148
149
150
151
152
153
154 static thread_t
155 runq_dequeue(void)
156 {
157 queue_t q;
158 thread_t th;
159
160 q = dequeue(&runq[top_prio]);
161 th = queue_entry(q, struct thread, link);
162 if (queue_empty(&runq[top_prio]))
163 top_prio = runq_top();
164 return th;
165 }
166
167
168
169
170 static void
171 runq_remove(thread_t th)
172 {
173
174 queue_remove(&th->link);
175 top_prio = runq_top();
176 }
177
178
179
180
181
182
183 static void
184 wakeq_flush(void)
185 {
186 queue_t q;
187 thread_t th;
188
189 while (!queue_empty(&wakeq)) {
190
191
192
193 q = dequeue(&wakeq);
194 th = queue_entry(q, struct thread, link);
195 th->sleep_event = 0;
196 th->state &= ~TH_SLEEP;
197
198 if (th != cur_thread && th->state == TH_RUN)
199 runq_enqueue(th);
200 }
201 }
202
203
204
205
206
207
208
209 static void
210 sleep_expire(void *arg)
211 {
212
213 sched_unsleep((thread_t)arg, SLP_TIMEOUT);
214 }
215
216
217
218
219
220
221
222
223
224
225 static void
226 sched_switch(void)
227 {
228 thread_t prev, next;
229
230 ASSERT(irq_level == 0);
231
232 prev = cur_thread;
233 if (prev->state == TH_RUN) {
234 if (prev->prio > top_prio)
235 runq_insert(prev);
236 else
237 runq_enqueue(prev);
238 }
239 prev->need_resched = 0;
240
241
242
243
244 next = runq_dequeue();
245 if (next == prev)
246 return;
247 cur_thread = next;
248
249 if (prev->task != next->task)
250 vm_switch(next->task->map);
251
252 context_switch(&prev->context, &next->context);
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 int
270 sched_tsleep(struct event *evt, u_long timeout)
271 {
272 int s;
273
274 ASSERT(irq_level == 0);
275 ASSERT(evt);
276
277 sched_lock();
278 interrupt_save(&s);
279 interrupt_disable();
280
281 cur_thread->sleep_event = evt;
282 cur_thread->state |= TH_SLEEP;
283 enqueue(&evt->sleepq, &cur_thread->link);
284
285 if (timeout != 0) {
286 timer_callout(&cur_thread->timeout, sleep_expire,
287 cur_thread, timeout);
288 }
289 wakeq_flush();
290 sched_switch();
291
292 interrupt_restore(s);
293 sched_unlock();
294 return cur_thread->sleep_result;
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 void
314 sched_wakeup(struct event *evt)
315 {
316 queue_t q;
317 thread_t th;
318
319 irq_lock();
320 while (!queue_empty(&evt->sleepq)) {
321
322
323
324 q = dequeue(&evt->sleepq);
325 th = queue_entry(q, struct thread, link);
326 th->sleep_result = 0;
327 enqueue(&wakeq, q);
328 timer_stop(&th->timeout);
329 }
330 irq_unlock();
331 }
332
333
334
335
336
337
338
339
340 thread_t
341 sched_wakeone(struct event *evt)
342 {
343 queue_t head, q;
344 thread_t top, th = NULL;
345
346 irq_lock();
347 head = &evt->sleepq;
348 if (!queue_empty(head)) {
349
350
351
352
353
354 q = queue_first(head);
355 top = queue_entry(q, struct thread, link);
356 while (!queue_end(head, q)) {
357 th = queue_entry(q, struct thread, link);
358 if (th->prio < top->prio)
359 top = th;
360 q = queue_next(q);
361 }
362 queue_remove(&top->link);
363 enqueue(&wakeq, &top->link);
364 timer_stop(&top->timeout);
365 }
366 irq_unlock();
367 return th;
368 }
369
370
371
372
373
374
375
376
377 void
378 sched_unsleep(thread_t th, int result)
379 {
380 sched_lock();
381 if (th->state & TH_SLEEP) {
382 irq_lock();
383 queue_remove(&th->link);
384 th->sleep_result = result;
385 enqueue(&wakeq, &th->link);
386 timer_stop(&th->timeout);
387 irq_unlock();
388
389 }
390 sched_unlock();
391 }
392
393
394
395
396
397
398
399
400
401 void
402 sched_yield(void)
403 {
404 ASSERT(irq_level == 0);
405
406 sched_lock();
407
408 if (!queue_empty(&runq[cur_thread->prio]))
409 cur_thread->need_resched = 1;
410
411 sched_unlock();
412 }
413
414
415
416
417
418
419 void
420 sched_suspend(thread_t th)
421 {
422 ASSERT(cur_thread->lock_count > 0);
423
424 if (th->state == TH_RUN) {
425 if (th == cur_thread)
426 cur_thread->need_resched = 1;
427 else
428 runq_remove(th);
429 }
430 th->state |= TH_SUSPEND;
431 }
432
433
434
435
436
437 void
438 sched_resume(thread_t th)
439 {
440 ASSERT(cur_thread->lock_count > 0);
441
442 if (th->state & TH_SUSPEND) {
443 th->state &= ~TH_SUSPEND;
444 if (th->state == TH_RUN)
445 runq_enqueue(th);
446 }
447 }
448
449
450
451
452
453
454 void
455 sched_tick(void)
456 {
457
458 cur_thread->total_ticks++;
459
460 if (cur_thread->policy == SCHED_RR) {
461 if (--cur_thread->ticks_left <= 0) {
462 cur_thread->ticks_left = QUANTUM;
463 cur_thread->need_resched = 1;
464 }
465 }
466 }
467
468
469
470
471 void
472 sched_start(thread_t th)
473 {
474
475 th->state = TH_RUN | TH_SUSPEND;
476 th->policy = SCHED_RR;
477 th->prio = PRIO_USER;
478 th->base_prio = PRIO_USER;
479 th->ticks_left = QUANTUM;
480 }
481
482
483
484
485 void
486 sched_stop(thread_t th)
487 {
488 ASSERT(irq_level == 0);
489 ASSERT(cur_thread->lock_count > 0);
490
491 if (th == cur_thread) {
492
493
494
495
496
497
498 cur_thread->lock_count = 1;
499 cur_thread->need_resched = 1;
500 } else {
501 if (th->state == TH_RUN)
502 runq_remove(th);
503 else if (th->state & TH_SLEEP)
504 queue_remove(&th->link);
505 }
506 timer_stop(&th->timeout);
507 th->state = TH_EXIT;
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 void
524 sched_lock(void)
525 {
526
527 cur_thread->lock_count++;
528 }
529
530
531
532
533
534
535
536
537
538
539
540 void
541 sched_unlock(void)
542 {
543 int s;
544
545 ASSERT(cur_thread->lock_count > 0);
546
547 interrupt_save(&s);
548 interrupt_disable();
549
550 if (cur_thread->lock_count == 1) {
551 wakeq_flush();
552 while (cur_thread->need_resched) {
553
554
555 sched_switch();
556
557
558
559
560
561
562
563
564 interrupt_restore(s);
565 interrupt_disable();
566 wakeq_flush();
567 }
568 }
569 cur_thread->lock_count--;
570
571 interrupt_restore(s);
572 }
573
574 int
575 sched_getprio(thread_t th)
576 {
577
578 return th->prio;
579 }
580
581
582
583
584
585
586
587
588
589 void
590 sched_setprio(thread_t th, int base, int prio)
591 {
592
593 th->base_prio = base;
594
595 if (th == cur_thread) {
596
597
598
599
600 th->prio = prio;
601 top_prio = runq_top();
602 if (prio != top_prio)
603 cur_thread->need_resched = 1;
604 } else {
605 if (th->state == TH_RUN) {
606
607
608
609
610 runq_remove(th);
611 th->prio = prio;
612 runq_enqueue(th);
613 } else
614 th->prio = prio;
615 }
616 }
617
618 int
619 sched_getpolicy(thread_t th)
620 {
621
622 return th->policy;
623 }
624
625 int
626 sched_setpolicy(thread_t th, int policy)
627 {
628 int err = 0;
629
630 switch (policy) {
631 case SCHED_RR:
632 case SCHED_FIFO:
633 th->ticks_left = QUANTUM;
634 th->policy = policy;
635 break;
636 default:
637 err = -1;
638 break;
639 }
640 return err;
641 }
642
643
644
645
646
647
648
649
650
651
652 static void
653 dpc_thread(u_long unused)
654 {
655 queue_t q;
656 struct dpc *dpc;
657
658 for (;;) {
659
660
661 sched_sleep(&dpc_event);
662
663 while (!queue_empty(&dpcq)) {
664 q = dequeue(&dpcq);
665 dpc = queue_entry(q, struct dpc, link);
666 dpc->state = DPC_FREE;
667
668 interrupt_enable();
669 (*dpc->func)(dpc->arg);
670 interrupt_disable();
671 }
672 }
673
674 }
675
676
677
678
679
680
681
682
683 void
684 sched_dpc(struct dpc *dpc, void (*func)(void *), void *arg)
685 {
686 ASSERT(dpc);
687 ASSERT(func);
688
689 irq_lock();
690 dpc->func = func;
691 dpc->arg = arg;
692 if (dpc->state != DPC_PENDING)
693 enqueue(&dpcq, &dpc->link);
694 dpc->state = DPC_PENDING;
695 sched_wakeup(&dpc_event);
696 irq_unlock();
697 }
698
699
700
701
702 void
703 sched_init(void)
704 {
705 int i;
706
707 for (i = 0; i < NR_PRIOS; i++)
708 queue_init(&runq[i]);
709
710 queue_init(&wakeq);
711 queue_init(&dpcq);
712 event_init(&dpc_event, "dpc");
713 top_prio = PRIO_IDLE;
714 cur_thread->need_resched = 1;
715
716
717
718
719 if (kernel_thread(PRIO_DPC, dpc_thread, 0) == NULL)
720 panic("sched_init");
721
722 printk("Time slice is %d msec\n", CONFIG_TIME_SLICE);
723 }
|