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