diff --git a/src/devices/timer.c b/src/devices/timer.c index 4bb602e..3e481cc 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -199,6 +199,10 @@ static void timer_interrupt (struct intr_frame *args UNUSED) { ticks++; + if (ticks % TIMER_FREQ == 0) + { + calculate_recent_cpu (); + } for (struct list_elem *e = list_begin (&sleeping_threads); e != list_end (&sleeping_threads); e = list_next (e)) { @@ -208,6 +212,7 @@ timer_interrupt (struct intr_frame *args UNUSED) else break; } + thread_increment_recent_cpu (); thread_tick (); } diff --git a/src/threads/thread.c b/src/threads/thread.c index bf65702..62a8c57 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -65,7 +65,7 @@ static void kernel_thread (thread_func *, void *aux); static void idle (void *aux UNUSED); static struct thread *running_thread (void); static struct thread *next_thread_to_run (void); -static void init_thread (struct thread *, const char *name, int priority); +static void init_thread (struct thread *, const char *name, int priority, fp32_t recent_cpu); static bool is_thread (struct thread *) UNUSED; static void *alloc_frame (struct thread *, size_t size); static void schedule (void); @@ -96,7 +96,8 @@ thread_init (void) /* Set up a thread structure for the running thread. */ initial_thread = running_thread (); - init_thread (initial_thread, "main", PRI_DEFAULT); + fp32_t initial_thread_recent_cpu = { 0 }; + init_thread (initial_thread, "main", PRI_DEFAULT, initial_thread_recent_cpu); initial_thread->status = THREAD_RUNNING; initial_thread->tid = allocate_tid (); } @@ -193,7 +194,8 @@ thread_create (const char *name, int priority, return TID_ERROR; /* Initialize thread. */ - init_thread (t, name, priority); + fp32_t parent_recent_cpu = thread_current ()->recent_cpu; + init_thread (t, name, priority, parent_recent_cpu); tid = t->tid = allocate_tid (); /* Prepare thread for first run by initializing its stack. @@ -373,6 +375,30 @@ calculate_priority (void) return 0; } +void +calculate_recent_cpu (void) +{ + struct thread *t = thread_current (); + fp32_t curr_recent_cpu = t->recent_cpu; + fp32_t curr_load_avg = fp_mul_int(thread_get_load_avg (), 2); + fp32_t recent_cpu_coeff = fp_div(curr_load_avg, fp_add_int(curr_load_avg, 1)); + fp32_t new_recent_cpu = fp_add_int(fp_mul(recent_cpu_coeff, curr_recent_cpu), thread_get_nice ()); + t->recent_cpu = new_recent_cpu; +} + +void +thread_increment_recent_cpu (void) +{ + struct thread *t = thread_current (); + if (t == idle_thread) + { + return; + } + fp32_t old_recent_cpu = t->recent_cpu; + old_recent_cpu.raw = old_recent_cpu.raw + 1; + t->recent_cpu = old_recent_cpu; +} + /* Sets the current thread's nice value to NICE. */ void thread_set_nice (int nice) @@ -476,7 +502,7 @@ is_thread (struct thread *t) /* Does basic initialization of T as a blocked thread named NAME. */ static void -init_thread (struct thread *t, const char *name, int priority) +init_thread (struct thread *t, const char *name, int priority, fp32_t recent_cpu) { enum intr_level old_level; @@ -490,6 +516,7 @@ init_thread (struct thread *t, const char *name, int priority) t->stack = (uint8_t *) t + PGSIZE; t->priority = priority; t->magic = THREAD_MAGIC; + t->recent_cpu = recent_cpu; old_level = intr_disable (); list_push_back (&all_list, &t->allelem); diff --git a/src/threads/thread.h b/src/threads/thread.h index f85b814..1124b8d 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -96,7 +96,7 @@ struct thread /* MLFQS items */ int nice; /* Nice value for this thread */ - fp32_t recent_cpu; /* Amount of time this process received */ + fp32_t recent_cpu; /* Amount of time this process received */ #ifdef USERPROG /* Owned by userprog/process.c. */