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

175 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 = 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. void
  88. add_timer(timer_t *timer) {
  89. bool intr_flag;
  90. local_intr_save(intr_flag);
  91. {
  92. assert(timer->expires > 0 && timer->proc != NULL);
  93. assert(list_empty(&(timer->timer_link)));
  94. list_entry_t *le = list_next(&timer_list);
  95. while (le != &timer_list) {
  96. timer_t *next = le2timer(le, timer_link);
  97. if (timer->expires < next->expires) {
  98. next->expires -= timer->expires;
  99. break;
  100. }
  101. timer->expires -= next->expires;
  102. le = list_next(le);
  103. }
  104. list_add_before(le, &(timer->timer_link));
  105. }
  106. local_intr_restore(intr_flag);
  107. }
  108. // del timer from timer_list
  109. void
  110. del_timer(timer_t *timer) {
  111. bool intr_flag;
  112. local_intr_save(intr_flag);
  113. {
  114. if (!list_empty(&(timer->timer_link))) {
  115. if (timer->expires != 0) {
  116. list_entry_t *le = list_next(&(timer->timer_link));
  117. if (le != &timer_list) {
  118. timer_t *next = le2timer(le, timer_link);
  119. next->expires += timer->expires;
  120. }
  121. }
  122. list_del_init(&(timer->timer_link));
  123. }
  124. }
  125. local_intr_restore(intr_flag);
  126. }
  127. // call scheduler to update tick related info, and check the timer is expired? If expired, then wakup proc
  128. void
  129. run_timer_list(void) {
  130. bool intr_flag;
  131. local_intr_save(intr_flag);
  132. {
  133. list_entry_t *le = list_next(&timer_list);
  134. if (le != &timer_list) {
  135. timer_t *timer = le2timer(le, timer_link);
  136. assert(timer->expires != 0);
  137. timer->expires --;
  138. while (timer->expires == 0) {
  139. le = list_next(le);
  140. struct proc_struct *proc = timer->proc;
  141. if (proc->wait_state != 0) {
  142. assert(proc->wait_state & WT_INTERRUPTED);
  143. }
  144. else {
  145. warn("process %d's wait_state == 0.\n", proc->pid);
  146. }
  147. wakeup_proc(proc);
  148. del_timer(timer);
  149. if (le == &timer_list) {
  150. break;
  151. }
  152. timer = le2timer(le, timer_link);
  153. }
  154. }
  155. sched_class_proc_tick(current);
  156. }
  157. local_intr_restore(intr_flag);
  158. }