update name of code to labcodes
This commit is contained in:
58
labcodes/lab8/kern/schedule/default_sched.c
Normal file
58
labcodes/lab8/kern/schedule/default_sched.c
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <defs.h>
|
||||
#include <list.h>
|
||||
#include <proc.h>
|
||||
#include <assert.h>
|
||||
#include <default_sched.h>
|
||||
|
||||
static void
|
||||
RR_init(struct run_queue *rq) {
|
||||
list_init(&(rq->run_list));
|
||||
rq->proc_num = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
RR_enqueue(struct run_queue *rq, struct proc_struct *proc) {
|
||||
assert(list_empty(&(proc->run_link)));
|
||||
list_add_before(&(rq->run_list), &(proc->run_link));
|
||||
if (proc->time_slice == 0 || proc->time_slice > rq->max_time_slice) {
|
||||
proc->time_slice = rq->max_time_slice;
|
||||
}
|
||||
proc->rq = rq;
|
||||
rq->proc_num ++;
|
||||
}
|
||||
|
||||
static void
|
||||
RR_dequeue(struct run_queue *rq, struct proc_struct *proc) {
|
||||
assert(!list_empty(&(proc->run_link)) && proc->rq == rq);
|
||||
list_del_init(&(proc->run_link));
|
||||
rq->proc_num --;
|
||||
}
|
||||
|
||||
static struct proc_struct *
|
||||
RR_pick_next(struct run_queue *rq) {
|
||||
list_entry_t *le = list_next(&(rq->run_list));
|
||||
if (le != &(rq->run_list)) {
|
||||
return le2proc(le, run_link);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
RR_proc_tick(struct run_queue *rq, struct proc_struct *proc) {
|
||||
if (proc->time_slice > 0) {
|
||||
proc->time_slice --;
|
||||
}
|
||||
if (proc->time_slice == 0) {
|
||||
proc->need_resched = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct sched_class default_sched_class = {
|
||||
.name = "RR_scheduler",
|
||||
.init = RR_init,
|
||||
.enqueue = RR_enqueue,
|
||||
.dequeue = RR_dequeue,
|
||||
.pick_next = RR_pick_next,
|
||||
.proc_tick = RR_proc_tick,
|
||||
};
|
||||
|
||||
9
labcodes/lab8/kern/schedule/default_sched.h
Normal file
9
labcodes/lab8/kern/schedule/default_sched.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __KERN_SCHEDULE_SCHED_RR_H__
|
||||
#define __KERN_SCHEDULE_SCHED_RR_H__
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
extern struct sched_class default_sched_class;
|
||||
|
||||
#endif /* !__KERN_SCHEDULE_SCHED_RR_H__ */
|
||||
|
||||
133
labcodes/lab8/kern/schedule/default_sched_stride_c
Normal file
133
labcodes/lab8/kern/schedule/default_sched_stride_c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <defs.h>
|
||||
#include <list.h>
|
||||
#include <proc.h>
|
||||
#include <assert.h>
|
||||
#include <default_sched.h>
|
||||
|
||||
#define USE_SKEW_HEAP 1
|
||||
|
||||
/* You should define the BigStride constant here*/
|
||||
/* LAB6: YOUR CODE */
|
||||
#define BIG_STRIDE /* you should give a value, and is ??? */
|
||||
|
||||
/* The compare function for two skew_heap_node_t's and the
|
||||
* corresponding procs*/
|
||||
static int
|
||||
proc_stride_comp_f(void *a, void *b)
|
||||
{
|
||||
struct proc_struct *p = le2proc(a, lab6_run_pool);
|
||||
struct proc_struct *q = le2proc(b, lab6_run_pool);
|
||||
int32_t c = p->lab6_stride - q->lab6_stride;
|
||||
if (c > 0) return 1;
|
||||
else if (c == 0) return 0;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* stride_init initializes the run-queue rq with correct assignment for
|
||||
* member variables, including:
|
||||
*
|
||||
* - run_list: should be a empty list after initialization.
|
||||
* - lab6_run_pool: NULL
|
||||
* - proc_num: 0
|
||||
* - max_time_slice: no need here, the variable would be assigned by the caller.
|
||||
*
|
||||
* hint: see libs/list.h for routines of the list structures.
|
||||
*/
|
||||
static void
|
||||
stride_init(struct run_queue *rq) {
|
||||
/* LAB6: YOUR CODE
|
||||
* (1) init the ready process list: rq->run_list
|
||||
* (2) init the run pool: rq->lab6_run_pool
|
||||
* (3) set number of process: rq->proc_num to 0
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* stride_enqueue inserts the process ``proc'' into the run-queue
|
||||
* ``rq''. The procedure should verify/initialize the relevant members
|
||||
* of ``proc'', and then put the ``lab6_run_pool'' node into the
|
||||
* queue(since we use priority queue here). The procedure should also
|
||||
* update the meta date in ``rq'' structure.
|
||||
*
|
||||
* proc->time_slice denotes the time slices allocation for the
|
||||
* process, which should set to rq->max_time_slice.
|
||||
*
|
||||
* hint: see libs/skew_heap.h for routines of the priority
|
||||
* queue structures.
|
||||
*/
|
||||
static void
|
||||
stride_enqueue(struct run_queue *rq, struct proc_struct *proc) {
|
||||
/* LAB6: YOUR CODE
|
||||
* (1) insert the proc into rq correctly
|
||||
* NOTICE: you can use skew_heap or list. Important functions
|
||||
* skew_heap_insert: insert a entry into skew_heap
|
||||
* list_add_before: insert a entry into the last of list
|
||||
* (2) recalculate proc->time_slice
|
||||
* (3) set proc->rq pointer to rq
|
||||
* (4) increase rq->proc_num
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* stride_dequeue removes the process ``proc'' from the run-queue
|
||||
* ``rq'', the operation would be finished by the skew_heap_remove
|
||||
* operations. Remember to update the ``rq'' structure.
|
||||
*
|
||||
* hint: see libs/skew_heap.h for routines of the priority
|
||||
* queue structures.
|
||||
*/
|
||||
static void
|
||||
stride_dequeue(struct run_queue *rq, struct proc_struct *proc) {
|
||||
/* LAB6: YOUR CODE
|
||||
* (1) remove the proc from rq correctly
|
||||
* NOTICE: you can use skew_heap or list. Important functions
|
||||
* skew_heap_remove: remove a entry from skew_heap
|
||||
* list_del_init: remove a entry from the list
|
||||
*/
|
||||
}
|
||||
/*
|
||||
* stride_pick_next pick the element from the ``run-queue'', with the
|
||||
* minimum value of stride, and returns the corresponding process
|
||||
* pointer. The process pointer would be calculated by macro le2proc,
|
||||
* see kern/process/proc.h for definition. Return NULL if
|
||||
* there is no process in the queue.
|
||||
*
|
||||
* When one proc structure is selected, remember to update the stride
|
||||
* property of the proc. (stride += BIG_STRIDE / priority)
|
||||
*
|
||||
* hint: see libs/skew_heap.h for routines of the priority
|
||||
* queue structures.
|
||||
*/
|
||||
static struct proc_struct *
|
||||
stride_pick_next(struct run_queue *rq) {
|
||||
/* LAB6: YOUR CODE
|
||||
* (1) get a proc_struct pointer p with the minimum value of stride
|
||||
(1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
|
||||
(1.2) If using list, we have to search list to find the p with minimum stride value
|
||||
* (2) update p;s stride value: p->lab6_stride
|
||||
* (3) return p
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* stride_proc_tick works with the tick event of current process. You
|
||||
* should check whether the time slices for current process is
|
||||
* exhausted and update the proc struct ``proc''. proc->time_slice
|
||||
* denotes the time slices left for current
|
||||
* process. proc->need_resched is the flag variable for process
|
||||
* switching.
|
||||
*/
|
||||
static void
|
||||
stride_proc_tick(struct run_queue *rq, struct proc_struct *proc) {
|
||||
/* LAB6: YOUR CODE */
|
||||
}
|
||||
|
||||
struct sched_class default_sched_class = {
|
||||
.name = "stride_scheduler",
|
||||
.init = stride_init,
|
||||
.enqueue = stride_enqueue,
|
||||
.dequeue = stride_dequeue,
|
||||
.pick_next = stride_pick_next,
|
||||
.proc_tick = stride_proc_tick,
|
||||
};
|
||||
175
labcodes/lab8/kern/schedule/sched.c
Normal file
175
labcodes/lab8/kern/schedule/sched.c
Normal file
@@ -0,0 +1,175 @@
|
||||
#include <list.h>
|
||||
#include <sync.h>
|
||||
#include <proc.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <default_sched.h>
|
||||
|
||||
// the list of timer
|
||||
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 = MAX_TIME_SLICE;
|
||||
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);
|
||||
}
|
||||
|
||||
// del timer from timer_list
|
||||
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);
|
||||
}
|
||||
|
||||
// call scheduler to update tick related info, and check the timer is expired? If expired, then wakup proc
|
||||
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);
|
||||
}
|
||||
73
labcodes/lab8/kern/schedule/sched.h
Normal file
73
labcodes/lab8/kern/schedule/sched.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef __KERN_SCHEDULE_SCHED_H__
|
||||
#define __KERN_SCHEDULE_SCHED_H__
|
||||
|
||||
#include <defs.h>
|
||||
#include <list.h>
|
||||
#include <skew_heap.h>
|
||||
|
||||
#define MAX_TIME_SLICE 20
|
||||
|
||||
struct proc_struct;
|
||||
|
||||
typedef struct {
|
||||
unsigned int expires; //the expire time
|
||||
struct proc_struct *proc; //the proc wait in this timer. If the expire time is end, then this proc will be scheduled
|
||||
list_entry_t timer_link; //the timer list
|
||||
} timer_t;
|
||||
|
||||
#define le2timer(le, member) \
|
||||
to_struct((le), timer_t, member)
|
||||
|
||||
// init a timer
|
||||
static inline timer_t *
|
||||
timer_init(timer_t *timer, struct proc_struct *proc, int expires) {
|
||||
timer->expires = expires;
|
||||
timer->proc = proc;
|
||||
list_init(&(timer->timer_link));
|
||||
return timer;
|
||||
}
|
||||
|
||||
struct run_queue;
|
||||
|
||||
// The introduction of scheduling classes is borrrowed from Linux, and makes the
|
||||
// core scheduler quite extensible. These classes (the scheduler modules) encapsulate
|
||||
// the scheduling policies.
|
||||
struct sched_class {
|
||||
// the name of sched_class
|
||||
const char *name;
|
||||
// Init the run queue
|
||||
void (*init)(struct run_queue *rq);
|
||||
// put the proc into runqueue, and this function must be called with rq_lock
|
||||
void (*enqueue)(struct run_queue *rq, struct proc_struct *proc);
|
||||
// get the proc out runqueue, and this function must be called with rq_lock
|
||||
void (*dequeue)(struct run_queue *rq, struct proc_struct *proc);
|
||||
// choose the next runnable task
|
||||
struct proc_struct *(*pick_next)(struct run_queue *rq);
|
||||
// dealer of the time-tick
|
||||
void (*proc_tick)(struct run_queue *rq, struct proc_struct *proc);
|
||||
/* for SMP support in the future
|
||||
* load_balance
|
||||
* void (*load_balance)(struct rq* rq);
|
||||
* get some proc from this rq, used in load_balance,
|
||||
* return value is the num of gotten proc
|
||||
* int (*get_proc)(struct rq* rq, struct proc* procs_moved[]);
|
||||
*/
|
||||
};
|
||||
|
||||
struct run_queue {
|
||||
list_entry_t run_list;
|
||||
unsigned int proc_num;
|
||||
int max_time_slice;
|
||||
// For LAB6 ONLY
|
||||
skew_heap_entry_t *lab6_run_pool;
|
||||
};
|
||||
|
||||
void sched_init(void);
|
||||
void wakeup_proc(struct proc_struct *proc);
|
||||
void schedule(void);
|
||||
void add_timer(timer_t *timer); // add timer to timer_list
|
||||
void del_timer(timer_t *timer); // del timer from timer_list
|
||||
void run_timer_list(void); // call scheduler to update tick related info, and check the timer is expired? If expired, then wakup proc
|
||||
|
||||
#endif /* !__KERN_SCHEDULE_SCHED_H__ */
|
||||
|
||||
Reference in New Issue
Block a user