diff --git a/src/threads/fixed-point.h b/src/threads/fixed-point.h index c56b3b6..69adb63 100644 --- a/src/threads/fixed-point.h +++ b/src/threads/fixed-point.h @@ -3,37 +3,40 @@ #define FIXED_POINT_H typedef struct -{ - int32_t raw; -} fp32_t; + { + int32_t raw; + } fp32_t; /* Fixed Point Arithmetic bit count constants */ #define NUM_FRAC_BITS 14 #define NUM_INT_BITS (31 - NUM_FRAC_BITS) -#define CONVERSION_CONST (1 << NUM_FRAC_BITS) /* f = 2^q, (2^20) */ +#define CONVERSION_FACTOR (1 << NUM_FRAC_BITS) /* f = 2^q, (2^14) */ /* Fixed Point Arithmetic conversion operations */ /* Converts an integer n to a fixed point number */ inline fp32_t -int_to_fp (int32_t n) +fp_from_int (int32_t n) { - return (fp32_t){ n * CONVERSION_CONST }; + return (fp32_t){ n * CONVERSION_FACTOR }; } -/* Handles conversion of fixed point to integer. First version truncates, second one rounds */ +/* Handles conversion of fixed point to integer, + with truncation */ inline int32_t fp_floor (fp32_t x) { - return x.raw / CONVERSION_CONST; + return x.raw / CONVERSION_FACTOR; } +/* Handles conversion of fixed point to integer, + with rounding */ inline int32_t fp_round (fp32_t x) { if (x.raw >= 0) - return (x.raw + CONVERSION_CONST / 2) / CONVERSION_CONST; + return (x.raw + CONVERSION_FACTOR / 2) / CONVERSION_FACTOR; else - return (x.raw - CONVERSION_CONST / 2) / CONVERSION_CONST; + return (x.raw - CONVERSION_FACTOR / 2) / CONVERSION_FACTOR; } /* Add two fixed points */ @@ -50,32 +53,20 @@ fp_sub (fp32_t x, fp32_t y) return (fp32_t){ x.raw - y.raw }; } -/* Add fixed point to integer */ -inline fp32_t -fp_add_int (fp32_t x, int32_t n) -{ - return (fp32_t){ x.raw + n * CONVERSION_CONST }; -} -/* Subtract integer from fixed point */ -inline fp32_t -fp_sub_int (fp32_t x, int32_t n) -{ - return (fp32_t){ x.raw - n * CONVERSION_CONST }; -} /* Multiple two fixed points */ inline fp32_t fp_mul (fp32_t x, fp32_t y) { - return (fp32_t){ ((int64_t)x.raw) * y.raw / CONVERSION_CONST }; + return (fp32_t){ ((int64_t)x.raw) * y.raw / CONVERSION_FACTOR }; } /* Divide two fixed points */ inline fp32_t fp_div (fp32_t x, fp32_t y) { - return (fp32_t){ ((int64_t)x.raw) * CONVERSION_CONST / y.raw }; + return (fp32_t){ ((int64_t)x.raw) * CONVERSION_FACTOR / y.raw }; } /* Multiply fixed point and integer */ @@ -92,4 +83,18 @@ fp_div_int (fp32_t x, int32_t n) return (fp32_t){ x.raw / n }; } +/* Add fixed point to integer */ +inline fp32_t +fp_add_int (fp32_t x, int32_t n) +{ + return (fp32_t){ x.raw + n * CONVERSION_FACTOR }; +} + +/* Subtract integer from fixed point */ +inline fp32_t +fp_sub_int (fp32_t x, int32_t n) +{ + return (fp32_t){ x.raw - n * CONVERSION_FACTOR }; +} + #endif //FIXED_POINT_H diff --git a/src/threads/synch.c b/src/threads/synch.c index 0ceb746..3fe957c 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -305,53 +305,50 @@ lock_release (struct lock *lock) ASSERT (lock != NULL); ASSERT (lock_held_by_current_thread (lock)); - if (!thread_mlfqs) - { - struct thread *current_thread = thread_current (); - struct thread *max_donor = NULL; + struct thread *current_thread = thread_current (); + struct thread *max_donor = NULL; - struct list orphan_list; - list_init (&orphan_list); + struct list orphan_list; + list_init (&orphan_list); - enum intr_level old_level = intr_disable (); - /* Loop through current thread's donors, removing the ones waiting for the - lock being released and keeping track of them (within orphan_list). - Also identifies the highest priority donor thread among them. */ - struct list_elem *tail = list_tail (¤t_thread->donors_list); - struct list_elem *e = list_begin (¤t_thread->donors_list); - while (e != tail) - { - struct thread *donor = list_entry (e, struct thread, donor_elem); - struct list_elem *next = list_next (e); + enum intr_level old_level = intr_disable (); + /* Loop through current thread's donors, removing the ones waiting for the + lock being released and keeping track of them (within orphan_list). + Also identifies the highest priority donor thread among them. */ + struct list_elem *tail = list_tail (¤t_thread->donors_list); + struct list_elem *e = list_begin (¤t_thread->donors_list); + while (e != tail) + { + struct thread *donor = list_entry (e, struct thread, donor_elem); + struct list_elem *next = list_next (e); - /* Excludes donors that aren't waiting for the lock being released, - and tracks the rest. */ - if (donor->waiting_lock == lock) - { - list_remove (e); - list_push_back (&orphan_list, e); + /* Excludes donors that aren't waiting for the lock being released, + and tracks the rest. */ + if (donor->waiting_lock == lock) + { + list_remove (e); + list_push_back (&orphan_list, e); - /* Identify highest priority donor. */ - if (max_donor == NULL || donor->priority > max_donor->priority) - max_donor = donor; - } + /* Identify highest priority donor. */ + if (max_donor == NULL || donor->priority > max_donor->priority) + max_donor = donor; + } - e = next; - } + e = next; + } - /* If there exists a maximum donor thread waiting for this lock to be - released, transfer the remaining orphaned donors to its donor list. */ - if (max_donor != NULL) - { - while (!list_empty (&orphan_list)) - list_push_back (&max_donor->donors_list, list_pop_front (&orphan_list)); - } + /* If there exists a maximum donor thread waiting for this lock to be + released, transfer the remaining orphaned donors to its donor list. */ + if (max_donor != NULL) + { + while (!list_empty (&orphan_list)) + list_push_back (&max_donor->donors_list, list_pop_front (&orphan_list)); + } - intr_set_level (old_level); - /* Removal of donors to this thread may change its effective priority, - so recalculate. */ - thread_recalculate_priority (); - } + intr_set_level (old_level); + /* Removal of donors to this thread may change its effective priority, + so recalculate. */ + thread_recalculate_priority (); lock->holder = NULL; sema_up (&lock->semaphore); diff --git a/src/threads/thread.c b/src/threads/thread.c index cb60d1b..880737a 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -72,7 +72,7 @@ static void init_thread (struct thread *, const char *name, int nice, static bool is_thread (struct thread *) UNUSED; static void *alloc_frame (struct thread *, size_t size); static int calculate_bsd_priority (fp32_t recent_cpu, int nice); -static void thread_update_recent_cpu (struct thread *t, void *aux UNUSED); +static void update_recent_cpu (struct thread *t, void *aux UNUSED); static void schedule (void); void thread_schedule_tail (struct thread *prev); static tid_t allocate_tid (void); @@ -157,23 +157,24 @@ thread_tick (void) /* Update system load_avg and all threads recent_cpu every second. */ int64_t ticks = timer_ticks (); - if (thread_mlfqs && (ticks % TIMER_FREQ == 0)) + if (thread_mlfqs) { - size_t ready = threads_ready (); if (t != idle_thread) - ready++; - fp32_t old_coeff = fp_div_int (fp_mul_int(load_avg, 59), 60); - fp32_t new_coeff = fp_div_int (int_to_fp (ready), 60); - load_avg = fp_add (old_coeff, new_coeff); + t->recent_cpu = fp_add_int (t->recent_cpu, 1); - thread_foreach (thread_update_recent_cpu, NULL); - } + if (ticks % TIMER_FREQ == 0) + { + size_t ready = threads_ready (); + if (t != idle_thread) + ready++; + fp32_t old_coeff = fp_div_int (fp_mul_int (load_avg, 59), 60); + fp32_t new_coeff = fp_div_int (fp_from_int (ready), 60); + load_avg = fp_add (old_coeff, new_coeff); - /* Update current thread's recent_cpu. */ - if (thread_mlfqs && (t != idle_thread)) - { - t->recent_cpu = fp_add_int (t->recent_cpu, 1); - if (ticks % 4 == 0) // recent_cpu was updated, update priority. + thread_foreach (update_recent_cpu, NULL); + } + + if (ticks % TIME_SLICE == 0) // recent_cpu was updated, update priority. t->priority = calculate_bsd_priority (t->recent_cpu, t->nice); } @@ -224,8 +225,8 @@ thread_create (const char *name, int priority, return TID_ERROR; /* Initialize thread. */ - struct thread *pt = thread_current (); - init_thread (t, name, pt->nice, priority, pt->recent_cpu); + struct thread *parent_thread = thread_current (); + init_thread (t, name, parent_thread->nice, priority, parent_thread->recent_cpu); tid = t->tid = allocate_tid (); /* Prepare thread for first run by initializing its stack. @@ -291,9 +292,8 @@ thread_unblock (struct thread *t) old_level = intr_disable (); ASSERT (t->status == THREAD_BLOCKED); - /* Insert the thread back into the ready list in priority order. */ - list_insert_ordered(&ready_list, &t->elem, priority_more, NULL); + list_insert_ordered (&ready_list, &t->elem, priority_more, NULL); t->status = THREAD_READY; intr_set_level (old_level); @@ -367,10 +367,8 @@ thread_yield (void) if (cur != idle_thread) { - /* Insert the thread back into the ready list in priority order. */ - list_insert_ordered(&ready_list, &cur->elem, priority_more, NULL); - + list_insert_ordered (&ready_list, &cur->elem, priority_more, NULL); } cur->status = THREAD_READY; @@ -402,7 +400,6 @@ bool priority_more (const struct list_elem *a_, const struct list_elem *b_, void *aux UNUSED) { - struct thread *a = list_entry (a_, struct thread, elem); struct thread *b = list_entry (b_, struct thread, elem); @@ -457,7 +454,7 @@ thread_get_priority (void) /* Updates recent_cpu for a thread. */ static void -thread_update_recent_cpu (struct thread *t, void *aux UNUSED) +update_recent_cpu (struct thread *t, void *aux UNUSED) { fp32_t curr_recent_cpu = t->recent_cpu; fp32_t dbl_load_avg = fp_mul_int (load_avg, 2); @@ -474,7 +471,8 @@ thread_recalculate_priority (void) { struct thread *t = thread_current (); - ASSERT(!thread_mlfqs) + if (thread_mlfqs) + return; enum intr_level old_level = intr_disable (); t->priority = t->base_priority; @@ -634,17 +632,16 @@ init_thread (struct thread *t, const char *name, int nice, int priority, t->status = THREAD_BLOCKED; strlcpy (t->name, name, sizeof t->name); t->stack = (uint8_t *) t + PGSIZE; + t->magic = THREAD_MAGIC; + + t->base_priority = priority; + list_init (&t->donors_list); + t->waiting_lock = NULL; t->nice = nice; t->recent_cpu = recent_cpu; - - t->base_priority = priority; - - t->magic = THREAD_MAGIC; - - list_init (&t->donors_list); - t->priority = thread_mlfqs ? calculate_bsd_priority (recent_cpu, nice) : t->base_priority; - t->waiting_lock = NULL; + t->priority = thread_mlfqs ? calculate_bsd_priority (recent_cpu, nice) + : t->base_priority; old_level = intr_disable (); list_push_back (&all_list, &t->allelem); @@ -729,7 +726,7 @@ static int calculate_bsd_priority (fp32_t recent_cpu, int nice) { - ASSERT(thread_mlfqs); + ASSERT (thread_mlfqs); int priority = PRI_MAX - (fp_round (recent_cpu) / 4) - (nice * 2); if (priority < PRI_MIN) diff --git a/src/threads/thread.h b/src/threads/thread.h index 8139b44..c7cc364 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -104,13 +104,14 @@ struct thread struct list_elem donor_elem; /* List element so that thread can be enlisted in other donors list. */ - /* Shared between thread.c and synch.c. */ - struct list_elem elem; /* List element. */ - /* MLFQS items */ int nice; /* Nice value for this thread */ fp32_t recent_cpu; /* Amount of time this process received */ + /* Shared between thread.c and synch.c. */ + struct list_elem elem; /* List element. */ + + #ifdef USERPROG /* Owned by userprog/process.c. */ uint32_t *pagedir; /* Page directory. */