《操作系统》的实验代码。
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.

176 lines
4.3 KiB

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