《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.2 KiB

10 years ago
10 years ago
  1. #include <list.h>
  2. #include <sync.h>
  3. #include <proc.h>
  4. #include <sched.h>
  5. #include <stdio.h>
  6. #include <assert.h>
  7. #include <default_sched.h>
  8. static list_entry_t timer_list;
  9. static struct sched_class *sched_class;
  10. static struct run_queue *rq;
  11. static inline void
  12. sched_class_enqueue(struct proc_struct *proc) {
  13. if (proc != idleproc) {
  14. sched_class->enqueue(rq, proc);
  15. }
  16. }
  17. static inline void
  18. sched_class_dequeue(struct proc_struct *proc) {
  19. sched_class->dequeue(rq, proc);
  20. }
  21. static inline struct proc_struct *
  22. sched_class_pick_next(void) {
  23. return sched_class->pick_next(rq);
  24. }
  25. static void
  26. sched_class_proc_tick(struct proc_struct *proc) {
  27. if (proc != idleproc) {
  28. sched_class->proc_tick(rq, proc);
  29. }
  30. else {
  31. proc->need_resched = 1;
  32. }
  33. }
  34. static struct run_queue __rq;
  35. void
  36. sched_init(void) {
  37. list_init(&timer_list);
  38. sched_class = &default_sched_class;
  39. rq = &__rq;
  40. rq->max_time_slice = 5;
  41. sched_class->init(rq);
  42. cprintf("sched class: %s\n", sched_class->name);
  43. }
  44. void
  45. wakeup_proc(struct proc_struct *proc) {
  46. assert(proc->state != PROC_ZOMBIE);
  47. bool intr_flag;
  48. local_intr_save(intr_flag);
  49. {
  50. if (proc->state != PROC_RUNNABLE) {
  51. proc->state = PROC_RUNNABLE;
  52. proc->wait_state = 0;
  53. if (proc != current) {
  54. sched_class_enqueue(proc);
  55. }
  56. }
  57. else {
  58. warn("wakeup runnable process.\n");
  59. }
  60. }
  61. local_intr_restore(intr_flag);
  62. }
  63. void
  64. schedule(void) {
  65. bool intr_flag;
  66. struct proc_struct *next;
  67. local_intr_save(intr_flag);
  68. {
  69. current->need_resched = 0;
  70. if (current->state == PROC_RUNNABLE) {
  71. sched_class_enqueue(current);
  72. }
  73. if ((next = sched_class_pick_next()) != NULL) {
  74. sched_class_dequeue(next);
  75. }
  76. if (next == NULL) {
  77. next = idleproc;
  78. }
  79. next->runs ++;
  80. if (next != current) {
  81. proc_run(next);
  82. }
  83. }
  84. local_intr_restore(intr_flag);
  85. }
  86. void
  87. add_timer(timer_t *timer) {
  88. bool intr_flag;
  89. local_intr_save(intr_flag);
  90. {
  91. assert(timer->expires > 0 && timer->proc != NULL);
  92. assert(list_empty(&(timer->timer_link)));
  93. list_entry_t *le = list_next(&timer_list);
  94. while (le != &timer_list) {
  95. timer_t *next = le2timer(le, timer_link);
  96. if (timer->expires < next->expires) {
  97. next->expires -= timer->expires;
  98. break;
  99. }
  100. timer->expires -= next->expires;
  101. le = list_next(le);
  102. }
  103. list_add_before(le, &(timer->timer_link));
  104. }
  105. local_intr_restore(intr_flag);
  106. }
  107. void
  108. del_timer(timer_t *timer) {
  109. bool intr_flag;
  110. local_intr_save(intr_flag);
  111. {
  112. if (!list_empty(&(timer->timer_link))) {
  113. if (timer->expires != 0) {
  114. list_entry_t *le = list_next(&(timer->timer_link));
  115. if (le != &timer_list) {
  116. timer_t *next = le2timer(le, timer_link);
  117. next->expires += timer->expires;
  118. }
  119. }
  120. list_del_init(&(timer->timer_link));
  121. }
  122. }
  123. local_intr_restore(intr_flag);
  124. }
  125. void
  126. run_timer_list(void) {
  127. bool intr_flag;
  128. local_intr_save(intr_flag);
  129. {
  130. list_entry_t *le = list_next(&timer_list);
  131. if (le != &timer_list) {
  132. timer_t *timer = le2timer(le, timer_link);
  133. assert(timer->expires != 0);
  134. timer->expires --;
  135. while (timer->expires == 0) {
  136. le = list_next(le);
  137. struct proc_struct *proc = timer->proc;
  138. if (proc->wait_state != 0) {
  139. assert(proc->wait_state & WT_INTERRUPTED);
  140. }
  141. else {
  142. warn("process %d's wait_state == 0.\n", proc->pid);
  143. }
  144. wakeup_proc(proc);
  145. del_timer(timer);
  146. if (le == &timer_list) {
  147. break;
  148. }
  149. timer = le2timer(le, timer_link);
  150. }
  151. }
  152. sched_class_proc_tick(current);
  153. }
  154. local_intr_restore(intr_flag);
  155. }