From 4ed64cf173966d447b9851717a0013bd122d242c Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 10:47:38 +0100 Subject: [PATCH 01/64] Add guard in thread_set_priority ensuring priority values are within correct range --- src/threads/thread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 30ca2bd..ed305ad 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -354,6 +354,7 @@ thread_foreach (thread_action_func *func, void *aux) void thread_set_priority (int new_priority) { + ASSERT (PRI_MIN <= new_priority && new_priority <= PRI_MAX); thread_current ()->priority = new_priority; } -- 2.49.1 From 1821d73b09616e61e5d8344db49ad42b7492723d Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 11:50:04 +0100 Subject: [PATCH 02/64] Add comparison function for thread list elements based on thread priority --- src/threads/thread.c | 11 +++++++++++ src/threads/thread.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index ed305ad..8e18ca9 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -599,6 +599,17 @@ allocate_tid (void) return tid; } +/* Returns true iff the priority of the first list element's thread is greater + than that of the second list element's thread. */ +bool +thread_priority_greater (const struct list_elem *a, const struct list_elem *b, + void *aux) +{ + struct thread *ta = list_entry (a, struct thread, elem); + struct thread *tb = list_entry (b, struct thread, elem); + return ta->priority > tb->priority; +} + /* Offset of `stack' member within `struct thread'. Used by switch.S, which can't figure it out on its own. */ uint32_t thread_stack_ofs = offsetof (struct thread, stack); diff --git a/src/threads/thread.h b/src/threads/thread.h index f36d7ac..0503af9 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -139,4 +139,7 @@ void thread_set_nice (int); int thread_get_recent_cpu (void); int thread_get_load_avg (void); +/* Returns true iff the priority of the first list element's thread is greater + than that of the second list element's thread. */ +list_less_func thread_priority_greater; #endif /* threads/thread.h */ -- 2.49.1 From f1fa7d2ffbfba3a562f60542171bed75d85fc2a0 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 11:51:40 +0100 Subject: [PATCH 03/64] Reformat thread_priority_greater to fit code style --- src/threads/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 8e18ca9..dfc70df 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -603,7 +603,7 @@ allocate_tid (void) than that of the second list element's thread. */ bool thread_priority_greater (const struct list_elem *a, const struct list_elem *b, - void *aux) + void *aux) { struct thread *ta = list_entry (a, struct thread, elem); struct thread *tb = list_entry (b, struct thread, elem); -- 2.49.1 From d4d5a7a937ecefa53915e6c82538d73fa015123f Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 12:01:03 +0100 Subject: [PATCH 04/64] Update thread_priority_greater function signature to explicitly signal unused parameter --- src/threads/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index dfc70df..146a430 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -603,7 +603,7 @@ allocate_tid (void) than that of the second list element's thread. */ bool thread_priority_greater (const struct list_elem *a, const struct list_elem *b, - void *aux) + void *aux UNUSED) { struct thread *ta = list_entry (a, struct thread, elem); struct thread *tb = list_entry (b, struct thread, elem); -- 2.49.1 From 79061fcb9b45219af33d2439fc91af9a5a10d463 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 13:51:41 +0100 Subject: [PATCH 05/64] Update thread module to maintain list of ready threads in descending order of priority --- src/threads/thread.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 146a430..709fcef 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -256,7 +256,7 @@ thread_unblock (struct thread *t) old_level = intr_disable (); ASSERT (t->status == THREAD_BLOCKED); - list_push_back (&ready_list, &t->elem); + list_insert_ordered (&ready_list, &t->elem, &thread_priority_greater, NULL); t->status = THREAD_READY; intr_set_level (old_level); } @@ -327,7 +327,8 @@ thread_yield (void) old_level = intr_disable (); if (cur != idle_thread) - list_push_back (&ready_list, &cur->elem); + list_insert_ordered (&ready_list, &cur->elem, thread_priority_greater, + NULL); cur->status = THREAD_READY; schedule (); intr_set_level (old_level); -- 2.49.1 From 6855a48603ac6a53b4b55d390f49b396f6623013 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 13:53:48 +0100 Subject: [PATCH 06/64] Update semaphore code to wake highest priority thread, and run if required --- src/threads/synch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 7776cb0..e1bcf9f 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -68,7 +68,8 @@ sema_down (struct semaphore *sema) old_level = intr_disable (); while (sema->value == 0) { - list_push_back (&sema->waiters, &thread_current ()->elem); + list_insert_ordered (&sema->waiters, &thread_current ()->elem, + &thread_priority_greater, NULL); thread_block (); } sema->value--; @@ -118,6 +119,7 @@ sema_up (struct semaphore *sema) struct thread, elem)); sema->value++; intr_set_level (old_level); + thread_yield (); } static void sema_test_helper (void *sema_); -- 2.49.1 From 54b46806babf9412e8c5b22d9fb28cd7ccc868ca Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 15:12:01 +0100 Subject: [PATCH 07/64] Update thread creation to yield thread in case it's no longer the highest priority --- src/threads/thread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 709fcef..6b48788 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -219,6 +219,7 @@ thread_create (const char *name, int priority, /* Add to run queue. */ thread_unblock (t); + thread_yield (); return tid; } -- 2.49.1 From 3c1a26b668c38b8a205194f2c52d47b57e7d9f5a Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 15:14:05 +0100 Subject: [PATCH 08/64] Update setting of thread priorities to yield in case a higher priority thread requires control --- src/threads/thread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 6b48788..6c1dcca 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -358,6 +358,7 @@ thread_set_priority (int new_priority) { ASSERT (PRI_MIN <= new_priority && new_priority <= PRI_MAX); thread_current ()->priority = new_priority; + thread_yield (); } /* Returns the current thread's priority. */ -- 2.49.1 From 163b7f9016162f976090c172f9dba655b0f54aaa Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 15:38:31 +0100 Subject: [PATCH 09/64] Update setting of priority of threads to only yield when current thread's priority has been lowered --- src/threads/thread.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 6c1dcca..3a428f1 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -357,8 +357,11 @@ void thread_set_priority (int new_priority) { ASSERT (PRI_MIN <= new_priority && new_priority <= PRI_MAX); + int old_priority = thread_get_priority (); + thread_current ()->priority = new_priority; - thread_yield (); + if (new_priority < old_priority) + thread_yield (); } /* Returns the current thread's priority. */ -- 2.49.1 From c32a69a368e6539c5791d3d69e0bb088ff41d237 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 15 Oct 2024 17:00:02 +0100 Subject: [PATCH 10/64] Update repository settings to ignore shell scripts --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 5d8d05c..9546b0d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ #ignore pdf files (just keep source files) *.pdf +#ignore shell scripts (only used for testing) +*.sh + #ignore junk files from latex output *.out *.log -- 2.49.1 From 9f71c989a93a45d95524a5853094f3718af604b7 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 07:10:31 +0100 Subject: [PATCH 11/64] Update gitignore to ignore temporary Mac OS files and code editor folders --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 5d8d05c..8d2540f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,13 @@ #ignore pdf files (just keep source files) *.pdf +#ignore Mac OS generated files +.DS_Store + +#ignore code editor generated directories +.idea +.vscode + #ignore junk files from latex output *.out *.log -- 2.49.1 From 83910f945c416d4d11c33f5b9d77c46c6404356b Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 07:26:02 +0100 Subject: [PATCH 12/64] Add priority comparator function for thread list sorting --- src/threads/thread.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 30ca2bd..2d931e2 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -70,6 +70,9 @@ static void *alloc_frame (struct thread *, size_t size); static void schedule (void); void thread_schedule_tail (struct thread *prev); static tid_t allocate_tid (void); +static bool priority_more (const struct list_elem *a_, + const struct list_elem *b_, + void *aux UNUSED) /* Initializes the threading system by transforming the code that's currently running into a thread. This can't work in @@ -350,6 +353,19 @@ thread_foreach (thread_action_func *func, void *aux) } } +/* Function that compares the two threads associated with the provided + list_elem structures. Returns true if the thread associated with a_ has + a higher priority than that of b_. */ +static 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); + + return a->priority > b->priority; +} + /* Sets the current thread's priority to NEW_PRIORITY. */ void thread_set_priority (int new_priority) -- 2.49.1 From 8b3f9e353f5724d345185442ddbfa42aaf2d34a1 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 07:33:24 +0100 Subject: [PATCH 13/64] Update creating thread to yield if the new thread has higher priority --- src/threads/thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 2d931e2..96d72be 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -223,6 +223,10 @@ thread_create (const char *name, int priority, /* Add to run queue. */ thread_unblock (t); + /* Yield if the new thread has a higher priority than the current thread. */ + if (priority > thread_get_priority ()) + thread_yield (); + return tid; } -- 2.49.1 From 9bb0b758c819c22467db99260b3ff382c2c6c4d8 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 07:40:41 +0100 Subject: [PATCH 14/64] Fix Error missing semicolon after function signature --- src/threads/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 96d72be..5bca536 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -72,7 +72,7 @@ void thread_schedule_tail (struct thread *prev); static tid_t allocate_tid (void); static bool priority_more (const struct list_elem *a_, const struct list_elem *b_, - void *aux UNUSED) + void *aux UNUSED); /* Initializes the threading system by transforming the code that's currently running into a thread. This can't work in -- 2.49.1 From 1c53790ca7b8aebbae192668a28cdd4b965bd26f Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 07:58:35 +0100 Subject: [PATCH 15/64] Update set_priority to ensure that the new priority is within bounds --- src/threads/thread.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 5bca536..4ddee22 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -374,6 +374,9 @@ priority_more (const struct list_elem *a_, const struct list_elem *b_, void thread_set_priority (int new_priority) { + ASSERT (new_priority >= PRI_MIN); + ASSERT (new_priority <= PRI_MAX); + thread_current ()->priority = new_priority; } -- 2.49.1 From fda79173c092e7eb7537557ae1cd19447dd1462b Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 08:00:50 +0100 Subject: [PATCH 16/64] Update thread_unblock to maintain priority order in ready_list --- src/threads/thread.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 4ddee22..0a66d65 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -263,7 +263,10 @@ thread_unblock (struct thread *t) old_level = intr_disable (); ASSERT (t->status == THREAD_BLOCKED); - list_push_back (&ready_list, &t->elem); + + /* Insert the thread back into the ready list in priority order. */ + list_insert_ordered(&ready_list, &t->elem, priority_more, NULL); + t->status = THREAD_READY; intr_set_level (old_level); } -- 2.49.1 From 62c8818c05d1d7ee79c35c39be73b0285b543ea1 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Oct 2024 08:18:51 +0100 Subject: [PATCH 17/64] Update thread_yield to add thread back in sorted order of priority --- src/threads/thread.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 0a66d65..e34d23e 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -336,8 +336,11 @@ thread_yield (void) ASSERT (!intr_context ()); old_level = intr_disable (); + + /* Insert the thread back into the ready list in priority order. */ if (cur != idle_thread) - list_push_back (&ready_list, &cur->elem); + list_insert_ordered(&ready_list, &cur->elem, priority_more, NULL); + cur->status = THREAD_READY; schedule (); intr_set_level (old_level); -- 2.49.1 From 9f53040d27a33168c2bc43f61a1e5b59253de9f3 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 06:00:34 +0100 Subject: [PATCH 18/64] Update thread_set_priority to not do anything if priority is unchanged --- src/threads/thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index e34d23e..f681f92 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -383,6 +383,10 @@ thread_set_priority (int new_priority) ASSERT (new_priority >= PRI_MIN); ASSERT (new_priority <= PRI_MAX); + int old_priority = thread_get_priority (); + if (new_priority == old_priority) + return; + thread_current ()->priority = new_priority; } -- 2.49.1 From 5c09ff0149f937a95cd15d2d18558a27d447a1e5 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 06:27:59 +0100 Subject: [PATCH 19/64] Updated set priority to yield if priority is lowered --- src/threads/thread.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index f681f92..7366641 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -388,6 +388,19 @@ thread_set_priority (int new_priority) return; thread_current ()->priority = new_priority; + + if (new_priority < old_priority && !list_empty (&ready_list)) { + /* If the new priority is lower than the old priority, check if the current + thread no longer has the highest priority. If it doesn't, yield the CPU. + */ + + struct thread *next_thread = + list_entry (list_front (&ready_list), struct thread, elem); + + if (next_thread->priority > new_priority) { + thread_yield(); + } + } } /* Returns the current thread's priority. */ -- 2.49.1 From 949455aae581f6bee62c42365775a216d758d454 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 06:35:39 +0100 Subject: [PATCH 20/64] Update set priority to eliminate race condition when accessing ready list --- src/threads/thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 7366641..f364679 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -389,6 +389,8 @@ thread_set_priority (int new_priority) thread_current ()->priority = new_priority; + enum intr_level old_level = intr_disable (); + if (new_priority < old_priority && !list_empty (&ready_list)) { /* If the new priority is lower than the old priority, check if the current thread no longer has the highest priority. If it doesn't, yield the CPU. @@ -401,6 +403,8 @@ thread_set_priority (int new_priority) thread_yield(); } } + + intr_set_level (old_level); } /* Returns the current thread's priority. */ -- 2.49.1 From dbb7fd56e3b42369de23a3954b0007e8094fdd38 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 06:38:27 +0100 Subject: [PATCH 21/64] Update set priority to reorder the list if priority is changed --- src/threads/thread.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index f364679..52d8577 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -391,6 +391,15 @@ thread_set_priority (int new_priority) enum intr_level old_level = intr_disable (); + /* If the thread is in the ready list, the list must be reordered to maintain + the priority order. */ + if (thread_current ()->status == THREAD_READY) { + /* Remove from the ready list and reinsert it in priority order. */ + list_remove (&thread_current ()->elem); + list_insert_ordered (&ready_list, &thread_current ()->elem, priority_more, + NULL); + } + if (new_priority < old_priority && !list_empty (&ready_list)) { /* If the new priority is lower than the old priority, check if the current thread no longer has the highest priority. If it doesn't, yield the CPU. -- 2.49.1 From fb268cdef0493b508eaeb44997e29a6da4421b41 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 06:47:58 +0100 Subject: [PATCH 22/64] Update thread make priority_more public --- src/threads/thread.c | 5 +---- src/threads/thread.h | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 52d8577..67d08d1 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -70,9 +70,6 @@ static void *alloc_frame (struct thread *, size_t size); static void schedule (void); void thread_schedule_tail (struct thread *prev); static tid_t allocate_tid (void); -static bool priority_more (const struct list_elem *a_, - const struct list_elem *b_, - void *aux UNUSED); /* Initializes the threading system by transforming the code that's currently running into a thread. This can't work in @@ -366,7 +363,7 @@ thread_foreach (thread_action_func *func, void *aux) /* Function that compares the two threads associated with the provided list_elem structures. Returns true if the thread associated with a_ has a higher priority than that of b_. */ -static bool +bool priority_more (const struct list_elem *a_, const struct list_elem *b_, void *aux UNUSED) { diff --git a/src/threads/thread.h b/src/threads/thread.h index f36d7ac..1cde088 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -131,6 +131,8 @@ void thread_yield (void); typedef void thread_action_func (struct thread *t, void *aux); void thread_foreach (thread_action_func *, void *); +bool priority_more (const struct list_elem *a_, const struct list_elem *b_, + void *aux UNUSED); int thread_get_priority (void); void thread_set_priority (int); -- 2.49.1 From 24900545d4718e28ab396562c9bb2c1bfffb428a Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 06:54:10 +0100 Subject: [PATCH 23/64] Update sema_down to insert into waiters list in priority sorted order --- src/threads/synch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 7776cb0..39575ca 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -68,7 +68,8 @@ sema_down (struct semaphore *sema) old_level = intr_disable (); while (sema->value == 0) { - list_push_back (&sema->waiters, &thread_current ()->elem); + list_insert_ordered(&sema->waiters, &thread_current ()->elem, + priority_more, NULL); thread_block (); } sema->value--; -- 2.49.1 From 0d6fb2f1675d1dec50c8618e0751491c06edf939 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 07:15:10 +0100 Subject: [PATCH 24/64] Update sema_up to yield CPU if unblocked has higher priority --- src/threads/synch.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 39575ca..ffdb588 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -114,11 +114,22 @@ sema_up (struct semaphore *sema) ASSERT (sema != NULL); old_level = intr_disable (); - if (!list_empty (&sema->waiters)) - thread_unblock (list_entry (list_pop_front (&sema->waiters), - struct thread, elem)); + + /* Wake up (unblock) the highest priority thread from the waiters list */ + struct thread *t = NULL; + if (!list_empty (&sema->waiters)) + { + t = list_entry (list_pop_front (&sema->waiters), struct thread, elem); + thread_unblock (t); + } + sema->value++; intr_set_level (old_level); + + /* If the unblocked thread has higher priority than the current running thread + then yield the CPU to the unblocked thread */ + if (!intr_context() && t != NULL && t->priority > thread_get_priority ()) + thread_yield (); } static void sema_test_helper (void *sema_); -- 2.49.1 From 53b296d6c4fab1ac436de6962733f4df7249d950 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 08:36:29 +0100 Subject: [PATCH 25/64] Add function to compare the priority of two semaphores --- src/threads/synch.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index ffdb588..078f142 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -265,6 +265,27 @@ struct semaphore_elem struct semaphore semaphore; /* This semaphore. */ }; +/* Function that compares the two *semaphores* associated with the provided + list_elem structures. [i.e., takes list_elem of semaphore_elem, and] + Returns true if the thread associated with the semaphore associated with a_ + has a higher priority than that of b_. */ +static bool +sema_priority_more(const struct list_elem *a_, const struct list_elem *b_, + void *aux UNUSED) +{ + struct semaphore_elem *a = list_entry(a_, struct semaphore_elem, elem); + struct semaphore_elem *b = list_entry(b_, struct semaphore_elem, elem); + + /* Get the highest priority thread from the waiters list of each semaphore. By + design, this is the first element in the list (See sema_down). */ + struct thread *a_thread = + list_entry(list_front(&a->semaphore.waiters), struct thread, elem); + struct thread *b_thread = + list_entry(list_front(&b->semaphore.waiters), struct thread, elem); + + return a_thread->priority > b_thread->priority; +} + /* Initializes condition variable COND. A condition variable allows one piece of code to signal a condition and cooperating code to receive the signal and act upon it. */ -- 2.49.1 From e74ee59e17a220143486a7d7b57f12f52efc761e Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 08:46:14 +0100 Subject: [PATCH 26/64] Update sema priority compare to take aux optionally as priority of first sema --- src/threads/synch.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 078f142..b588656 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -268,22 +268,49 @@ struct semaphore_elem /* Function that compares the two *semaphores* associated with the provided list_elem structures. [i.e., takes list_elem of semaphore_elem, and] Returns true if the thread associated with the semaphore associated with a_ - has a higher priority than that of b_. */ + has a higher priority than that of b_. + + If aux is provided, then it is a pointer to an integer representing the + priority of the first semaphore. This is useful when the thread has not been + sema'd down yet. */ static bool sema_priority_more(const struct list_elem *a_, const struct list_elem *b_, - void *aux UNUSED) + void *aux) { - struct semaphore_elem *a = list_entry(a_, struct semaphore_elem, elem); + int a_priority, b_priority; + + /* If an aux is provided, then use it as the priority of the first semaphore. + Otherwise, get the priority of the first semaphore. */ + if (aux != NULL) + a_priority = *(int *) aux; + else + { + struct semaphore_elem *a = list_entry(a_, struct semaphore_elem, elem); + + /* If waiters list is empty, return false (i.e., a has lower priority) */ + if (list_empty(&a->semaphore.waiters)) + return false; + + /* Otherwise, get the thread with the highest priority from the waiters + list. By design, this is the first one in the list (See sema_down). */ + struct thread *a_thread = + list_entry(list_front(&a->semaphore.waiters), struct thread, elem); + + a_priority = a_thread->priority; + } + struct semaphore_elem *b = list_entry(b_, struct semaphore_elem, elem); - /* Get the highest priority thread from the waiters list of each semaphore. By - design, this is the first element in the list (See sema_down). */ - struct thread *a_thread = - list_entry(list_front(&a->semaphore.waiters), struct thread, elem); + /* If waiters list is empty, return true (i.e., a has higher priority) */ + if (list_empty(&b->semaphore.waiters)) + return true; + struct thread *b_thread = list_entry(list_front(&b->semaphore.waiters), struct thread, elem); - return a_thread->priority > b_thread->priority; + b_priority = b_thread->priority; + + return a_priority > b_priority; } /* Initializes condition variable COND. A condition variable -- 2.49.1 From 88967acdaa49de4b71294cce988687f06c192e19 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 08:53:53 +0100 Subject: [PATCH 27/64] Update cond_wait to insert into waiters list in sorted order of priority --- src/threads/synch.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index b588656..2431494 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -355,7 +355,14 @@ cond_wait (struct condition *cond, struct lock *lock) ASSERT (lock_held_by_current_thread (lock)); sema_init (&waiter.semaphore, 0); - list_push_back (&cond->waiters, &waiter.elem); + + /* Insert the semaphore_elem into the waiters list in order of priority. + We pass the priority of the current thread as aux to sema_priority_more + because the thread has not been sema'd down yet (See sema_priority_more) */ + int priority = thread_current ()->priority; + list_insert_ordered (&cond->waiters, &waiter.elem, sema_priority_more, + &priority); + lock_release (lock); sema_down (&waiter.semaphore); lock_acquire (lock); -- 2.49.1 From 711efdc78ab1960074a5e0283b900861d21fc590 Mon Sep 17 00:00:00 2001 From: Themis Date: Thu, 17 Oct 2024 19:43:35 +0100 Subject: [PATCH 28/64] Implement priority scheduling for condition variables --- src/threads/synch.c | 47 +++++++++++++++------------------------------ 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 387f060..374817f 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -265,43 +265,25 @@ struct semaphore_elem priority of the first semaphore. This is useful when the thread has not been sema'd down yet. */ static bool -sema_priority_more(const struct list_elem *a_, const struct list_elem *b_, - void *aux) +sema_priority_more(const struct list_elem *a, const struct list_elem *b, + void *inserting_telem) { - int a_priority, b_priority; + struct list_elem *te_a, *te_b; + + te_b = list_front ( + &list_entry (b, struct semaphore_elem, elem)->semaphore.waiters); - /* If an aux is provided, then use it as the priority of the first semaphore. - Otherwise, get the priority of the first semaphore. */ - if (aux != NULL) - a_priority = *(int *) aux; + if (inserting_telem == NULL) + { + te_a = list_front ( + &list_entry (a, struct semaphore_elem, elem)->semaphore.waiters); + } else { - struct semaphore_elem *a = list_entry(a_, struct semaphore_elem, elem); - - /* If waiters list is empty, return false (i.e., a has lower priority) */ - if (list_empty(&a->semaphore.waiters)) - return false; - - /* Otherwise, get the thread with the highest priority from the waiters - list. By design, this is the first one in the list (See sema_down). */ - struct thread *a_thread = - list_entry(list_front(&a->semaphore.waiters), struct thread, elem); - - a_priority = a_thread->priority; + te_a = inserting_telem; } - struct semaphore_elem *b = list_entry(b_, struct semaphore_elem, elem); - - /* If waiters list is empty, return true (i.e., a has higher priority) */ - if (list_empty(&b->semaphore.waiters)) - return true; - - struct thread *b_thread = - list_entry(list_front(&b->semaphore.waiters), struct thread, elem); - - b_priority = b_thread->priority; - - return a_priority > b_priority; + return priority_more (te_a, te_b, NULL); } /* Initializes condition variable COND. A condition variable @@ -346,7 +328,8 @@ cond_wait (struct condition *cond, struct lock *lock) ASSERT (lock_held_by_current_thread (lock)); sema_init (&waiter.semaphore, 0); - list_push_back (&cond->waiters, &waiter.elem); + list_insert_ordered (&cond->waiters, &waiter.elem, sema_priority_more, + &thread_current ()->elem); lock_release (lock); sema_down (&waiter.semaphore); lock_acquire (lock); -- 2.49.1 From bfdedc53e263fc0b80b86c587bad053f5c5cd38c Mon Sep 17 00:00:00 2001 From: sBubshait Date: Thu, 17 Oct 2024 19:46:10 +0100 Subject: [PATCH 29/64] Update set priority so not to yield if no ready threads --- src/threads/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index e587626..3e5d15c 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -383,7 +383,7 @@ thread_set_priority (int new_priority) thread_current ()->priority = new_priority; - if (new_priority < old_priority) + if (new_priority < old_priority && !list_empty (&ready_list)) thread_yield (); } -- 2.49.1 From 6b9b671368faeb19e4fab0bd0b3e3c66e782727d Mon Sep 17 00:00:00 2001 From: Themis Date: Thu, 17 Oct 2024 20:01:39 +0100 Subject: [PATCH 30/64] Update sema_up to properly yield during execution of an interrupt handler --- src/threads/synch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 374817f..d773824 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -120,7 +120,10 @@ sema_up (struct semaphore *sema) sema->value++; intr_set_level (old_level); - thread_yield (); + if (intr_context ()) + intr_yield_on_return (); + else + thread_yield (); } static void sema_test_helper (void *sema_); -- 2.49.1 From 8b1e0b9559164cc198d26b7745805bb836db68bf Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sun, 20 Oct 2024 17:04:14 +0100 Subject: [PATCH 31/64] Add donation-related information to the thread structure, w/ T --- src/threads/thread.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/threads/thread.h b/src/threads/thread.h index a4a2439..4e719a7 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -90,6 +90,15 @@ struct thread int priority; /* Priority. */ struct list_elem allelem; /* List element for all threads list. */ + /* Donation Related */ + int base_priority; /* Base priority of the thread. */ + struct list donors_list; /* List of threads that have donated + to this thread. */ + struct lock *waiting_lock; /* The lock that the current thread is + waiting for. */ + 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. */ -- 2.49.1 From fcc8cbb71e9a05b0b3a0561d5ef80e7420e82587 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 17:11:44 +0100 Subject: [PATCH 32/64] Implement initialization of new threads to track donation information, w/ S --- src/threads/thread.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 3e5d15c..3fcfe1e 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -510,9 +510,13 @@ init_thread (struct thread *t, const char *name, int priority) t->status = THREAD_BLOCKED; strlcpy (t->name, name, sizeof t->name); t->stack = (uint8_t *) t + PGSIZE; - t->priority = priority; + t->base_priority = priority; t->magic = THREAD_MAGIC; + list_init (&t->donors_list); + t->priority = t->base_priority; + t->waiting_lock = NULL; + old_level = intr_disable (); list_push_back (&all_list, &t->allelem); intr_set_level (old_level); -- 2.49.1 From 5a651f12794dc5fb04febe6ccc21159656a154fe Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sun, 20 Oct 2024 18:06:07 +0100 Subject: [PATCH 33/64] Update implementation of thread set priority to account for donations, w/ T --- src/threads/thread.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 3fcfe1e..d65d7c4 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -370,21 +370,35 @@ priority_more (const struct list_elem *a_, const struct list_elem *b_, return a->priority > b->priority; } -/* Sets the current thread's priority to NEW_PRIORITY. */ +/* Sets the current thread's base priority to new_base_priority. + Updates the current thread's effective priority if necessary. */ void -thread_set_priority (int new_priority) +thread_set_priority (int new_base_priority) { - ASSERT (new_priority >= PRI_MIN); - ASSERT (new_priority <= PRI_MAX); + ASSERT (new_base_priority >= PRI_MIN); + ASSERT (new_base_priority <= PRI_MAX); + struct thread *t = thread_current (); + + int old_base_priority = t->base_priority; int old_priority = thread_get_priority (); - if (new_priority == old_priority) + if (new_base_priority == old_base_priority) return; - thread_current ()->priority = new_priority; - if (new_priority < old_priority && !list_empty (&ready_list)) - thread_yield (); + t->base_priority = new_base_priority; + t->priority = new_base_priority; + + if (!list_empty (&t->donors_list) && new_base_priority < old_priority) { + int max_donated_priority = + list_entry (list_max (&t->donors_list, priority_more, NULL), + struct thread, donor_elem)->priority; + + if(new_base_priority < max_donated_priority) + t->priority = new_base_priority; + } + + thread_yield (); } /* Returns the current thread's priority. */ -- 2.49.1 From f98e4bc81c70ee4e0ec90536d9f02329ff702210 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 19:19:43 +0100 Subject: [PATCH 34/64] Update lock_acquire to attempt donation of priorities, w/ S --- src/threads/synch.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index d773824..4bf54a6 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -187,6 +187,9 @@ lock_init (struct lock *lock) sema_init (&lock->semaphore, 1); } +static void +donate_priority (struct thread *donor, struct thread *donee); + /* Acquires LOCK, sleeping until it becomes available if necessary. The lock must not already be held by the current thread. @@ -202,8 +205,18 @@ lock_acquire (struct lock *lock) ASSERT (!intr_context ()); ASSERT (!lock_held_by_current_thread (lock)); + struct thread *t = thread_current (); + + /* TODO: If a high-priority thread holding a lock sleeps, this may cause a + race condition here or break the assumption that donation must occur. */ + if (lock->holder != NULL) + { + t->waiting_lock = lock; + } + sema_down (&lock->semaphore); lock->holder = thread_current (); + t->waiting_lock = NULL; } /* Tries to acquires LOCK and returns true if successful or false -- 2.49.1 From 343ac55d372f6f6d93c2c7e6a96d46e2ae889a44 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sun, 20 Oct 2024 19:42:35 +0100 Subject: [PATCH 35/64] Implement priority donation helper function with propagation, w/ T --- src/threads/synch.c | 16 +++++++++++++++- src/threads/thread.c | 6 ++++++ src/threads/thread.h | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 4bf54a6..3495ca8 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -188,7 +188,21 @@ lock_init (struct lock *lock) } static void -donate_priority (struct thread *donor, struct thread *donee); +donate_priority (struct thread *donor, struct thread *donee) { + while (donee != NULL) + { + if (donor->priority <= donee->priority) + break; + + donee->priority = donor->priority; + if (donee->waiting_lock == NULL) + donee = NULL; + else + donee = donee->waiting_lock->holder; + } + + ready_list_reorder (); +} /* Acquires LOCK, sleeping until it becomes available if necessary. The lock must not already be held by the current diff --git a/src/threads/thread.c b/src/threads/thread.c index d65d7c4..b7bab5b 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -439,6 +439,12 @@ thread_get_recent_cpu (void) return 0; } +void +ready_list_reorder (void) +{ + list_sort (&ready_list, priority_more, NULL); +} + /* Idle thread. Executes when no other thread is ready to run. The idle thread is initially put on the ready list by diff --git a/src/threads/thread.h b/src/threads/thread.h index 4e719a7..083a5ab 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -150,6 +150,8 @@ void thread_set_nice (int); int thread_get_recent_cpu (void); int thread_get_load_avg (void); +void ready_list_reorder (void); + /* Returns true iff the priority of the first list element's thread is greater than that of the second list element's thread. */ list_less_func thread_priority_greater; -- 2.49.1 From ee0cf632b9018b021c9393b5474a5232948bb2e4 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 19:45:05 +0100 Subject: [PATCH 36/64] Fix attempt to donate priority within lock acquisition w/ S --- src/threads/synch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index 3495ca8..6d71c83 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -226,6 +226,7 @@ lock_acquire (struct lock *lock) if (lock->holder != NULL) { t->waiting_lock = lock; + donate_priority (t, lock->holder); } sema_down (&lock->semaphore); -- 2.49.1 From 8e20884a23c857f18e756b2b19445c196919091c Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 20:17:27 +0100 Subject: [PATCH 37/64] Update releasing of locks to update donation information w/ S --- src/threads/synch.c | 12 ++++++++++++ src/threads/thread.c | 7 +++++++ src/threads/thread.h | 1 + 3 files changed, 20 insertions(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index 6d71c83..027018e 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -265,6 +265,18 @@ lock_release (struct lock *lock) ASSERT (lock != NULL); ASSERT (lock_held_by_current_thread (lock)); + struct thread *current_thread = thread_current (); + struct list_elem *tail = list_tail (¤t_thread->donors_list); + for (struct list_elem *e = list_begin (¤t_thread->donors_list); + e != tail; e = e->next) + { + struct thread *donor = list_entry (e, struct thread, donor_elem); + if (donor->waiting_lock == lock) + list_remove (e); + } + + thread_recalculate_priority (); + lock->holder = NULL; sema_up (&lock->semaphore); } diff --git a/src/threads/thread.c b/src/threads/thread.c index b7bab5b..ed717e3 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -408,6 +408,13 @@ thread_get_priority (void) return thread_current ()->priority; } +/* Recalculates the effective priority of the current thread. */ +void +thread_recalculate_priority (void) +{ + barrier (); +}; + /* Sets the current thread's nice value to NICE. */ void thread_set_nice (int nice UNUSED) diff --git a/src/threads/thread.h b/src/threads/thread.h index 083a5ab..b3c1006 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -144,6 +144,7 @@ bool priority_more (const struct list_elem *a_, const struct list_elem *b_, void *aux UNUSED); int thread_get_priority (void); void thread_set_priority (int); +void thread_recalculate_priority (void); int thread_get_nice (void); void thread_set_nice (int); -- 2.49.1 From b1dba1a0bd522c2c7ec35eaa184fcae78b35d683 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sun, 20 Oct 2024 20:37:03 +0100 Subject: [PATCH 38/64] Add implementation for recalculate effective priority, w/ T --- src/threads/thread.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index ed717e3..1f2d273 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -389,14 +389,8 @@ thread_set_priority (int new_base_priority) t->base_priority = new_base_priority; t->priority = new_base_priority; - if (!list_empty (&t->donors_list) && new_base_priority < old_priority) { - int max_donated_priority = - list_entry (list_max (&t->donors_list, priority_more, NULL), - struct thread, donor_elem)->priority; - - if(new_base_priority < max_donated_priority) - t->priority = new_base_priority; - } + if (new_base_priority < old_priority) + thread_recalculate_priority (); thread_yield (); } @@ -412,8 +406,17 @@ thread_get_priority (void) void thread_recalculate_priority (void) { - barrier (); -}; + struct thread *t = thread_current (); + + if (!list_empty (&t->donors_list)) { + int max_donated_priority = + list_entry (list_max (&t->donors_list, priority_more, NULL), + struct thread, donor_elem)->priority; + + if(max_donated_priority > t->priority) + t->priority = max_donated_priority; + } +} /* Sets the current thread's nice value to NICE. */ void -- 2.49.1 From afcb12cef0b48755118a61fee0f706c5058b7a0d Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 20:38:28 +0100 Subject: [PATCH 39/64] Reformat thread priority changing functions to follow style w/ S --- src/threads/thread.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 1f2d273..d85e05a 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -385,7 +385,6 @@ thread_set_priority (int new_base_priority) if (new_base_priority == old_base_priority) return; - t->base_priority = new_base_priority; t->priority = new_base_priority; @@ -413,7 +412,7 @@ thread_recalculate_priority (void) list_entry (list_max (&t->donors_list, priority_more, NULL), struct thread, donor_elem)->priority; - if(max_donated_priority > t->priority) + if (max_donated_priority > t->priority) t->priority = max_donated_priority; } } -- 2.49.1 From 44de31c0ff26b83d88369e4005e79e8e7e717b7c Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sun, 20 Oct 2024 20:54:48 +0100 Subject: [PATCH 40/64] Fix Bug in Implementation of recalculate priority setting base priority, w/ T --- src/threads/thread.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index d85e05a..b626a96 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -386,10 +386,7 @@ thread_set_priority (int new_base_priority) return; t->base_priority = new_base_priority; - t->priority = new_base_priority; - - if (new_base_priority < old_priority) - thread_recalculate_priority (); + thread_recalculate_priority (); thread_yield (); } @@ -406,6 +403,7 @@ void thread_recalculate_priority (void) { struct thread *t = thread_current (); + t->priority = t->base_priority; if (!list_empty (&t->donors_list)) { int max_donated_priority = -- 2.49.1 From 7f7b1648cd6d31a5c032b6cedbbfc8748b296bcb Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sun, 20 Oct 2024 22:28:29 +0100 Subject: [PATCH 41/64] Fix indentation in recalculate priority to match pintos style, w/ T --- src/threads/thread.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index b626a96..f937aca 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -405,14 +405,15 @@ thread_recalculate_priority (void) struct thread *t = thread_current (); t->priority = t->base_priority; - if (!list_empty (&t->donors_list)) { - int max_donated_priority = - list_entry (list_max (&t->donors_list, priority_more, NULL), - struct thread, donor_elem)->priority; + if (!list_empty (&t->donors_list)) + { + int max_donated_priority = + list_entry (list_max (&t->donors_list, priority_more, NULL), + struct thread, donor_elem)->priority; - if (max_donated_priority > t->priority) - t->priority = max_donated_priority; - } + if (max_donated_priority > t->priority) + t->priority = max_donated_priority; + } } /* Sets the current thread's nice value to NICE. */ -- 2.49.1 From 840df8af78bc6e343cf69fb0866d110fefcda26b Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 22:29:20 +0100 Subject: [PATCH 42/64] Fix bug in donate_priority that wouldn't update the list of donors w/ S --- src/threads/synch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index 027018e..cdfb2dc 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -189,6 +189,8 @@ lock_init (struct lock *lock) static void donate_priority (struct thread *donor, struct thread *donee) { + list_push_back (&donee->donors_list, &donor->donor_elem); + while (donee != NULL) { if (donor->priority <= donee->priority) -- 2.49.1 From dae5b0d097f6424867ecfde3a6a5a3f38f740c36 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Sun, 20 Oct 2024 22:50:31 +0100 Subject: [PATCH 43/64] Update semaphore priority scheduling to use linear search on unordered list w/ S --- src/threads/synch.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index cdfb2dc..b74303d 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -68,8 +68,7 @@ sema_down (struct semaphore *sema) old_level = intr_disable (); while (sema->value == 0) { - list_insert_ordered(&sema->waiters, &thread_current ()->elem, - priority_more, NULL); + list_push_back (&sema->waiters, &thread_current ()->elem); thread_block (); } sema->value--; @@ -114,9 +113,12 @@ sema_up (struct semaphore *sema) ASSERT (sema != NULL); old_level = intr_disable (); - if (!list_empty (&sema->waiters)) - thread_unblock (list_entry (list_pop_front (&sema->waiters), - struct thread, elem)); + if (!list_empty (&sema->waiters)) + { + struct list_elem *e = list_min (&sema->waiters, priority_more, NULL); + list_remove (e); + thread_unblock (list_entry (e, struct thread, elem)); + } sema->value++; intr_set_level (old_level); -- 2.49.1 From f10514f4cc8b8aa810a25472ec1c74859a6bafdf Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 18:59:19 +0100 Subject: [PATCH 44/64] Update priority_more comment description to specify which list_elem member it is compatible with --- src/threads/thread.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index f937aca..ff5686e 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -358,8 +358,8 @@ thread_foreach (thread_action_func *func, void *aux) } /* Function that compares the two threads associated with the provided - list_elem structures. Returns true if the thread associated with a_ has - a higher priority than that of b_. */ + pointers to their 'elem' member. Returns true if the thread associated + with a_ has a higher priority than that of b_. */ bool priority_more (const struct list_elem *a_, const struct list_elem *b_, void *aux UNUSED) -- 2.49.1 From a19d40bcca62abe891e3f18b9de9c02aad097c41 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 19:01:55 +0100 Subject: [PATCH 45/64] Reformat priority_more to obey code style --- src/threads/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index ff5686e..379c6d7 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -362,7 +362,7 @@ thread_foreach (thread_action_func *func, void *aux) with a_ has a higher priority than that of b_. */ bool priority_more (const struct list_elem *a_, const struct list_elem *b_, - void *aux UNUSED) + void *aux UNUSED) { struct thread *a = list_entry (a_, struct thread, elem); struct thread *b = list_entry (b_, struct thread, elem); -- 2.49.1 From d9b957263140170fb38b41d8dccd35e593ce2711 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 22 Oct 2024 19:49:53 +0100 Subject: [PATCH 46/64] Fix Bug in recalculating priority, uses 'elem' instead of 'donor_elem', w/ T --- src/threads/thread.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 379c6d7..c4722a9 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -70,6 +70,8 @@ static void *alloc_frame (struct thread *, size_t size); static void schedule (void); void thread_schedule_tail (struct thread *prev); static tid_t allocate_tid (void); +static bool donor_priority_less (const struct list_elem *a_, + const struct list_elem *b_, void *aux UNUSED); /* Initializes the threading system by transforming the code that's currently running into a thread. This can't work in @@ -370,6 +372,19 @@ priority_more (const struct list_elem *a_, const struct list_elem *b_, return a->priority > b->priority; } +/* Function that compares the two threads associated with the provided + pointers to their 'donor_elem' member. Returns true if the thread associated + with a_ has a lower priority than that of b_. */ +static bool +donor_priority_less (const struct list_elem *a_, const struct list_elem *b_, + void *aux UNUSED) +{ + struct thread *a = list_entry (a_, struct thread, donor_elem); + struct thread *b = list_entry (b_, struct thread, donor_elem); + + return a->priority < b->priority; +} + /* Sets the current thread's base priority to new_base_priority. Updates the current thread's effective priority if necessary. */ void @@ -408,7 +423,7 @@ thread_recalculate_priority (void) if (!list_empty (&t->donors_list)) { int max_donated_priority = - list_entry (list_max (&t->donors_list, priority_more, NULL), + list_entry (list_max (&t->donors_list, donor_priority_less, NULL), struct thread, donor_elem)->priority; if (max_donated_priority > t->priority) -- 2.49.1 From 21cbfc9fe0dfa22f20380f2258b0031cbfc2065a Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 20:06:21 +0100 Subject: [PATCH 47/64] Implement transfer of orphaned donors when releasing lock w/ S --- src/threads/synch.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index b74303d..4ec2266 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -270,15 +270,53 @@ lock_release (struct lock *lock) ASSERT (lock_held_by_current_thread (lock)); struct thread *current_thread = thread_current (); + struct thread *max_donor = NULL; + + struct list orphan_list; + list_init (&orphan_list); + + /* 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); - for (struct list_elem *e = list_begin (¤t_thread->donors_list); - e != tail; e = e->next) + 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); + + /* Identify highest priority donor. */ + if (max_donor == NULL || donor->priority > max_donor->priority) + max_donor = donor; + } + + 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) + { + tail = list_tail (&orphan_list); + e = list_begin (&orphan_list); + while (e != tail) + { + struct list_elem *next = list_next (e); + list_push_back (&max_donor->donors_list, e); + + e = next; + } + } + + /* Removal of donors to this thread may change its effective priority, + so recalculate. */ thread_recalculate_priority (); lock->holder = NULL; -- 2.49.1 From 244db41434d6f627bb471188f95bfbe278d57145 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 22 Oct 2024 20:25:13 +0100 Subject: [PATCH 48/64] Update condvar to use linear search due to changes in priority from donations, w/ T --- src/threads/synch.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 4ec2266..73dceba 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -413,8 +413,7 @@ cond_wait (struct condition *cond, struct lock *lock) ASSERT (lock_held_by_current_thread (lock)); sema_init (&waiter.semaphore, 0); - list_insert_ordered (&cond->waiters, &waiter.elem, sema_priority_more, - &thread_current ()->elem); + list_push_back (&cond->waiters, &waiter.elem); lock_release (lock); sema_down (&waiter.semaphore); lock_acquire (lock); @@ -435,9 +434,13 @@ cond_signal (struct condition *cond, struct lock *lock UNUSED) ASSERT (!intr_context ()); ASSERT (lock_held_by_current_thread (lock)); - if (!list_empty (&cond->waiters)) - sema_up (&list_entry (list_pop_front (&cond->waiters), - struct semaphore_elem, elem)->semaphore); + if (!list_empty (&cond->waiters)) + { + struct list_elem *e = list_min (&cond->waiters, sema_priority_more, NULL); + list_remove (e); + sema_up (&list_entry (e, struct semaphore_elem, elem)->semaphore); + } + } /* Wakes up all threads, if any, waiting on COND (protected by -- 2.49.1 From fc1691f9945990826d73f043d06b784cddb6a8d8 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 20:36:28 +0100 Subject: [PATCH 49/64] Refactor thread.h to remove superfluous thread priority comparison function w/ S --- src/threads/thread.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/threads/thread.h b/src/threads/thread.h index b3c1006..de9df61 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -153,7 +153,4 @@ int thread_get_load_avg (void); void ready_list_reorder (void); -/* Returns true iff the priority of the first list element's thread is greater - than that of the second list element's thread. */ -list_less_func thread_priority_greater; #endif /* threads/thread.h */ -- 2.49.1 From 6983ccdd3b2161426590e6b3d92d7a670b609235 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 20:41:44 +0100 Subject: [PATCH 50/64] Update thread_get_priority description comment to be more specific w/ S --- src/threads/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index c4722a9..1cf40af 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -406,7 +406,7 @@ thread_set_priority (int new_base_priority) thread_yield (); } -/* Returns the current thread's priority. */ +/* Returns the current thread's effective priority. */ int thread_get_priority (void) { -- 2.49.1 From bf6104200ce5539d34257c9b74fe7c7982fd63aa Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 22 Oct 2024 20:47:34 +0100 Subject: [PATCH 51/64] Refactor thread set priority to remove unused variable and add comment, w/ T --- src/threads/thread.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index 1cf40af..79dd339 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -395,9 +395,8 @@ thread_set_priority (int new_base_priority) struct thread *t = thread_current (); - int old_base_priority = t->base_priority; - int old_priority = thread_get_priority (); - if (new_base_priority == old_base_priority) + /* If the base priority is unchanged, do nothing. */ + if (new_base_priority == t->base_priority) return; t->base_priority = new_base_priority; -- 2.49.1 From 5549b9c0cb73d2c652566f737674e23bd61d5f44 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 22 Oct 2024 20:52:52 +0100 Subject: [PATCH 52/64] Refactor thread recalculate priority to add comments for clarity, w/ T --- src/threads/thread.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 79dd339..ff66100 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -419,12 +419,16 @@ thread_recalculate_priority (void) struct thread *t = thread_current (); t->priority = t->base_priority; + /* If there are no donors to the current thread, then the effective + priority is just the base priority. */ if (!list_empty (&t->donors_list)) { int max_donated_priority = list_entry (list_max (&t->donors_list, donor_priority_less, NULL), struct thread, donor_elem)->priority; + /* The effective priority is the max donated priority if this is + higher than the base priority. */ if (max_donated_priority > t->priority) t->priority = max_donated_priority; } -- 2.49.1 From 48104b3a410862b4a942d6c1e2e089988b52b247 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 20:57:18 +0100 Subject: [PATCH 53/64] Refactor cond_signal to add comment clarifying the logic w/ S --- src/threads/synch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 73dceba..655e014 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -436,11 +436,12 @@ cond_signal (struct condition *cond, struct lock *lock UNUSED) if (!list_empty (&cond->waiters)) { + /* Enforce wake-up of highest priority thread within the singleton + semaphores waiting for condvar. */ struct list_elem *e = list_min (&cond->waiters, sema_priority_more, NULL); list_remove (e); sema_up (&list_entry (e, struct semaphore_elem, elem)->semaphore); } - } /* Wakes up all threads, if any, waiting on COND (protected by -- 2.49.1 From 78c6fd36e3db13cbb2db8586d69636ddff09a727 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 22 Oct 2024 21:04:14 +0100 Subject: [PATCH 54/64] Refactor sema_up to add comments for clarity, w/ T --- src/threads/synch.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 655e014..9900748 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -106,7 +106,7 @@ sema_try_down (struct semaphore *sema) This function may be called from an interrupt handler. */ void -sema_up (struct semaphore *sema) +sema_up (struct semaphore *sema) { enum intr_level old_level; @@ -114,14 +114,19 @@ sema_up (struct semaphore *sema) old_level = intr_disable (); if (!list_empty (&sema->waiters)) - { - struct list_elem *e = list_min (&sema->waiters, priority_more, NULL); - list_remove (e); - thread_unblock (list_entry (e, struct thread, elem)); - } + { + /* Enforces wake-up of the highest priority thread waiting for the + semaphore. */ + struct list_elem *e = list_min (&sema->waiters, priority_more, NULL); + list_remove (e); + thread_unblock (list_entry (e, struct thread, elem)); + } sema->value++; intr_set_level (old_level); + /* Yields the CPU in case the thread that has been woken up has a higher + priority that the current running thread, including the case when called + within an interrupt handler. */ if (intr_context ()) intr_yield_on_return (); else -- 2.49.1 From 7aec2e6862d74a7e864063d504097e3c278f1fea Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 21:15:30 +0100 Subject: [PATCH 55/64] Refactor donate_priority to include comments explaining its purpose and logic w/ S --- src/threads/synch.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index 9900748..3dc15cd 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -194,16 +194,25 @@ lock_init (struct lock *lock) sema_init (&lock->semaphore, 1); } +/* Allows for the donor to donate its priority to donee, iteratively + propagating the donation in the case of chains in the wait-for graph. + Also keeps track of the donation by updating the donors list. */ static void donate_priority (struct thread *donor, struct thread *donee) { list_push_back (&donee->donors_list, &donor->donor_elem); while (donee != NULL) { + /* Stop propagation of donation once a donee is reached that has + a higher effective priority (as its donees can't have less + priority than that being donated). */ if (donor->priority <= donee->priority) break; donee->priority = donor->priority; + + /* Also stop propagation of donation once a donee is reached with + no donees of its own (sink node in WFG). */ if (donee->waiting_lock == NULL) donee = NULL; else -- 2.49.1 From d82176a2e25013281e949abd949849959440c2c2 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Tue, 22 Oct 2024 22:52:29 +0100 Subject: [PATCH 56/64] Refactor lock release to follow PintOS indent style and use list functoins, w/ T --- src/threads/synch.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 3dc15cd..1123249 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -302,14 +302,14 @@ lock_release (struct lock *lock) /* 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); + { + 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; } @@ -317,17 +317,10 @@ lock_release (struct lock *lock) /* 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) - { - tail = list_tail (&orphan_list); - e = list_begin (&orphan_list); - while (e != tail) - { - struct list_elem *next = list_next (e); - list_push_back (&max_donor->donors_list, e); - - e = next; - } - } + { + while (!list_empty (&orphan_list)) + list_push_back (&max_donor->donors_list, list_pop_front (&orphan_list)); + } /* Removal of donors to this thread may change its effective priority, so recalculate. */ -- 2.49.1 From a875d5fcb4eec1aeb97b5ab47ae963a9f8f3e5ae Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 23 Oct 2024 13:29:45 +0100 Subject: [PATCH 57/64] Update donate_priority to only attempt to sort position of the donee that isn't waiting for a lock --- src/threads/synch.c | 11 ++++++++--- src/threads/thread.c | 18 +++++++++++++++--- src/threads/thread.h | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 1123249..462bda7 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -214,12 +214,17 @@ donate_priority (struct thread *donor, struct thread *donee) { /* Also stop propagation of donation once a donee is reached with no donees of its own (sink node in WFG). */ if (donee->waiting_lock == NULL) - donee = NULL; + { + + /* Only the sink node of the WFG isn't waiting for a lock and + could be on the ready list. Thus, as its priority changed, + it must be reinserted into the list. */ + ready_list_reinsert (donee); + donee = NULL; + } else donee = donee->waiting_lock->holder; } - - ready_list_reorder (); } /* Acquires LOCK, sleeping until it becomes available if diff --git a/src/threads/thread.c b/src/threads/thread.c index ff66100..178cdf9 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -465,10 +465,22 @@ thread_get_recent_cpu (void) return 0; } +/* Reinsert thread t into the ready list at its correct position + in descending order of priority. Used when this thread's priority + may have changed. */ void -ready_list_reorder (void) +ready_list_reinsert (struct thread *t) { - list_sort (&ready_list, priority_more, NULL); + enum intr_level old_level = intr_disable (); + + /* If the thread isn't ready to run, do nothing. */ + if (t->status == THREAD_READY) + { + list_remove (&t->elem); + list_insert_ordered (&ready_list, &t->elem, priority_more, NULL); + } + + intr_set_level (old_level); } /* Idle thread. Executes when no other thread is ready to run. @@ -558,7 +570,7 @@ init_thread (struct thread *t, const char *name, int priority) t->stack = (uint8_t *) t + PGSIZE; t->base_priority = priority; t->magic = THREAD_MAGIC; - + list_init (&t->donors_list); t->priority = t->base_priority; t->waiting_lock = NULL; diff --git a/src/threads/thread.h b/src/threads/thread.h index de9df61..ffeb2b3 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -151,6 +151,6 @@ void thread_set_nice (int); int thread_get_recent_cpu (void); int thread_get_load_avg (void); -void ready_list_reorder (void); +void ready_list_reinsert (struct thread *t); #endif /* threads/thread.h */ -- 2.49.1 From 2cd4da17a4e158a3023790aa3d14f01ffb1bfbc0 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 23 Oct 2024 13:42:36 +0100 Subject: [PATCH 58/64] Refactor donate_priority to only allow for the current thread to donate its priority --- src/threads/synch.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 462bda7..0649772 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -194,11 +194,12 @@ lock_init (struct lock *lock) sema_init (&lock->semaphore, 1); } -/* Allows for the donor to donate its priority to donee, iteratively +/* Current thread donates its priority to donee, iteratively propagating the donation in the case of chains in the wait-for graph. Also keeps track of the donation by updating the donors list. */ static void -donate_priority (struct thread *donor, struct thread *donee) { +donate_priority (struct thread *donee) { + struct thread *donor = thread_current (); list_push_back (&donee->donors_list, &donor->donor_elem); while (donee != NULL) @@ -249,7 +250,7 @@ lock_acquire (struct lock *lock) if (lock->holder != NULL) { t->waiting_lock = lock; - donate_priority (t, lock->holder); + donate_priority (lock->holder); } sema_down (&lock->semaphore); -- 2.49.1 From b0074c80f014ca24763dc2f561bd185f62b6c983 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 23 Oct 2024 13:51:07 +0100 Subject: [PATCH 59/64] Refactor ready_list_reinsert to require being called with interrupts disabled --- src/threads/synch.c | 2 ++ src/threads/thread.c | 14 ++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 0649772..7dc6eaa 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -220,7 +220,9 @@ donate_priority (struct thread *donee) { /* Only the sink node of the WFG isn't waiting for a lock and could be on the ready list. Thus, as its priority changed, it must be reinserted into the list. */ + enum intr_level old_level = intr_disable (); ready_list_reinsert (donee); + intr_set_level (old_level); donee = NULL; } else diff --git a/src/threads/thread.c b/src/threads/thread.c index 178cdf9..8731b3b 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -467,20 +467,18 @@ thread_get_recent_cpu (void) /* Reinsert thread t into the ready list at its correct position in descending order of priority. Used when this thread's priority - may have changed. */ + may have changed. Must be called with interrupts disabled. */ void ready_list_reinsert (struct thread *t) { - enum intr_level old_level = intr_disable (); + ASSERT (intr_get_level () == INTR_OFF); /* If the thread isn't ready to run, do nothing. */ - if (t->status == THREAD_READY) - { - list_remove (&t->elem); - list_insert_ordered (&ready_list, &t->elem, priority_more, NULL); - } + if (t->status != THREAD_READY) + return; - intr_set_level (old_level); + list_remove (&t->elem); + list_insert_ordered (&ready_list, &t->elem, priority_more, NULL); } /* Idle thread. Executes when no other thread is ready to run. -- 2.49.1 From 5f8dea21befb9bf5688383796eb510770ddb2d0b Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 23 Oct 2024 14:10:48 +0100 Subject: [PATCH 60/64] Fix donate_priority to disable interrupts for entire update of possibly-ready donatee's priority --- src/threads/synch.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 7dc6eaa..b99332e 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -210,23 +210,25 @@ donate_priority (struct thread *donee) { if (donor->priority <= donee->priority) break; - donee->priority = donor->priority; - /* Also stop propagation of donation once a donee is reached with no donees of its own (sink node in WFG). */ if (donee->waiting_lock == NULL) { - /* Only the sink node of the WFG isn't waiting for a lock and could be on the ready list. Thus, as its priority changed, it must be reinserted into the list. */ enum intr_level old_level = intr_disable (); + donee->priority = donor->priority; ready_list_reinsert (donee); intr_set_level (old_level); + donee = NULL; } else - donee = donee->waiting_lock->holder; + { + donee->priority = donor->priority; + donee = donee->waiting_lock->holder; + } } } -- 2.49.1 From f9d82c92dec012832f16113269b11e0bdfe09d05 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 23 Oct 2024 16:16:25 +0100 Subject: [PATCH 61/64] Update thread_recalculate_priority to disable interrupts preventing race conditions for access to donors and priorities w/ S --- src/threads/thread.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/threads/thread.c b/src/threads/thread.c index 8731b3b..dd594d9 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -417,6 +417,8 @@ void thread_recalculate_priority (void) { struct thread *t = thread_current (); + + enum intr_level old_level = intr_disable (); t->priority = t->base_priority; /* If there are no donors to the current thread, then the effective @@ -432,6 +434,7 @@ thread_recalculate_priority (void) if (max_donated_priority > t->priority) t->priority = max_donated_priority; } + intr_set_level (old_level); } /* Sets the current thread's nice value to NICE. */ -- 2.49.1 From 6223846fdeabaa5028c0d06c1ac2fd69ea4b8911 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 23 Oct 2024 16:30:38 +0100 Subject: [PATCH 62/64] Update lock_acquire to disable interrupts to eliminate race-conditions, w/ T --- src/threads/synch.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index b99332e..7831774 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -248,15 +248,16 @@ lock_acquire (struct lock *lock) ASSERT (!lock_held_by_current_thread (lock)); struct thread *t = thread_current (); + enum intr_level old_level = intr_disable (); - /* TODO: If a high-priority thread holding a lock sleeps, this may cause a - race condition here or break the assumption that donation must occur. */ if (lock->holder != NULL) { t->waiting_lock = lock; donate_priority (lock->holder); } + intr_set_level (old_level); + sema_down (&lock->semaphore); lock->holder = thread_current (); t->waiting_lock = NULL; -- 2.49.1 From 4879775d0b07f3d86af6d7b579e86bb01a7cc61c Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 23 Oct 2024 16:32:40 +0100 Subject: [PATCH 63/64] Update donate priority to add an assertion that intrrupts are disabled, w/ T --- src/threads/synch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index 7831774..940faa5 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -196,9 +196,12 @@ lock_init (struct lock *lock) /* Current thread donates its priority to donee, iteratively propagating the donation in the case of chains in the wait-for graph. - Also keeps track of the donation by updating the donors list. */ + Also keeps track of the donation by updating the donors list. Expects + interrupts to be disabled. */ static void donate_priority (struct thread *donee) { + ASSERT (intr_get_level () == INTR_OFF); + struct thread *donor = thread_current (); list_push_back (&donee->donors_list, &donor->donor_elem); -- 2.49.1 From 95386971e2dd07bd20ee1280d47e85a8c85eccfa Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Wed, 23 Oct 2024 16:45:42 +0100 Subject: [PATCH 64/64] Update lock_release to disable interrupts in critical sections w/ S --- src/threads/synch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/threads/synch.c b/src/threads/synch.c index 940faa5..1246206 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -303,6 +303,7 @@ lock_release (struct lock *lock) 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. */ @@ -336,6 +337,7 @@ lock_release (struct lock *lock) 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 (); -- 2.49.1