d9a83bd7be
The original time slice (200ms) is too large for the priority test to generate a satisfactory result in 20s. If we only schedule 5 times a second, there are only 100 pick_next calls to the scheduler. I believe making scheduling more frequently does little harm to the system. Actually more scheduling opportunities may also reveal bugs which are not triggered previously. Adopting smaller time slices also allows us to reduce the time spent on the priority test, which can benefit the autotesting system. Signed-off-by: Junjie Mao <junjie.mao@hotmail.com>
173 lines
4.2 KiB
C
173 lines
4.2 KiB
C
#include <list.h>
|
|
#include <sync.h>
|
|
#include <proc.h>
|
|
#include <sched.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <default_sched.h>
|
|
|
|
static list_entry_t timer_list;
|
|
|
|
static struct sched_class *sched_class;
|
|
|
|
static struct run_queue *rq;
|
|
|
|
static inline void
|
|
sched_class_enqueue(struct proc_struct *proc) {
|
|
if (proc != idleproc) {
|
|
sched_class->enqueue(rq, proc);
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
sched_class_dequeue(struct proc_struct *proc) {
|
|
sched_class->dequeue(rq, proc);
|
|
}
|
|
|
|
static inline struct proc_struct *
|
|
sched_class_pick_next(void) {
|
|
return sched_class->pick_next(rq);
|
|
}
|
|
|
|
static void
|
|
sched_class_proc_tick(struct proc_struct *proc) {
|
|
if (proc != idleproc) {
|
|
sched_class->proc_tick(rq, proc);
|
|
}
|
|
else {
|
|
proc->need_resched = 1;
|
|
}
|
|
}
|
|
|
|
static struct run_queue __rq;
|
|
|
|
void
|
|
sched_init(void) {
|
|
list_init(&timer_list);
|
|
|
|
sched_class = &default_sched_class;
|
|
|
|
rq = &__rq;
|
|
rq->max_time_slice = 5;
|
|
sched_class->init(rq);
|
|
|
|
cprintf("sched class: %s\n", sched_class->name);
|
|
}
|
|
|
|
void
|
|
wakeup_proc(struct proc_struct *proc) {
|
|
assert(proc->state != PROC_ZOMBIE);
|
|
bool intr_flag;
|
|
local_intr_save(intr_flag);
|
|
{
|
|
if (proc->state != PROC_RUNNABLE) {
|
|
proc->state = PROC_RUNNABLE;
|
|
proc->wait_state = 0;
|
|
if (proc != current) {
|
|
sched_class_enqueue(proc);
|
|
}
|
|
}
|
|
else {
|
|
warn("wakeup runnable process.\n");
|
|
}
|
|
}
|
|
local_intr_restore(intr_flag);
|
|
}
|
|
|
|
void
|
|
schedule(void) {
|
|
bool intr_flag;
|
|
struct proc_struct *next;
|
|
local_intr_save(intr_flag);
|
|
{
|
|
current->need_resched = 0;
|
|
if (current->state == PROC_RUNNABLE) {
|
|
sched_class_enqueue(current);
|
|
}
|
|
if ((next = sched_class_pick_next()) != NULL) {
|
|
sched_class_dequeue(next);
|
|
}
|
|
if (next == NULL) {
|
|
next = idleproc;
|
|
}
|
|
next->runs ++;
|
|
if (next != current) {
|
|
proc_run(next);
|
|
}
|
|
}
|
|
local_intr_restore(intr_flag);
|
|
}
|
|
|
|
void
|
|
add_timer(timer_t *timer) {
|
|
bool intr_flag;
|
|
local_intr_save(intr_flag);
|
|
{
|
|
assert(timer->expires > 0 && timer->proc != NULL);
|
|
assert(list_empty(&(timer->timer_link)));
|
|
list_entry_t *le = list_next(&timer_list);
|
|
while (le != &timer_list) {
|
|
timer_t *next = le2timer(le, timer_link);
|
|
if (timer->expires < next->expires) {
|
|
next->expires -= timer->expires;
|
|
break;
|
|
}
|
|
timer->expires -= next->expires;
|
|
le = list_next(le);
|
|
}
|
|
list_add_before(le, &(timer->timer_link));
|
|
}
|
|
local_intr_restore(intr_flag);
|
|
}
|
|
|
|
void
|
|
del_timer(timer_t *timer) {
|
|
bool intr_flag;
|
|
local_intr_save(intr_flag);
|
|
{
|
|
if (!list_empty(&(timer->timer_link))) {
|
|
if (timer->expires != 0) {
|
|
list_entry_t *le = list_next(&(timer->timer_link));
|
|
if (le != &timer_list) {
|
|
timer_t *next = le2timer(le, timer_link);
|
|
next->expires += timer->expires;
|
|
}
|
|
}
|
|
list_del_init(&(timer->timer_link));
|
|
}
|
|
}
|
|
local_intr_restore(intr_flag);
|
|
}
|
|
|
|
void
|
|
run_timer_list(void) {
|
|
bool intr_flag;
|
|
local_intr_save(intr_flag);
|
|
{
|
|
list_entry_t *le = list_next(&timer_list);
|
|
if (le != &timer_list) {
|
|
timer_t *timer = le2timer(le, timer_link);
|
|
assert(timer->expires != 0);
|
|
timer->expires --;
|
|
while (timer->expires == 0) {
|
|
le = list_next(le);
|
|
struct proc_struct *proc = timer->proc;
|
|
if (proc->wait_state != 0) {
|
|
assert(proc->wait_state & WT_INTERRUPTED);
|
|
}
|
|
else {
|
|
warn("process %d's wait_state == 0.\n", proc->pid);
|
|
}
|
|
wakeup_proc(proc);
|
|
del_timer(timer);
|
|
if (le == &timer_list) {
|
|
break;
|
|
}
|
|
timer = le2timer(le, timer_link);
|
|
}
|
|
}
|
|
sched_class_proc_tick(current);
|
|
}
|
|
local_intr_restore(intr_flag);
|
|
}
|