summaryrefslogtreecommitdiffstats
path: root/threads/synch.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-05-07 18:01:20 +0200
committermanuel <manuel@mausz.at>2012-05-07 18:01:20 +0200
commit158ea87fba909161a084c29feff29a168725fe4e (patch)
treece580f0fec9f4d5105e817ae11fded8015817574 /threads/synch.c
parent3d1e18466b44b2de06dd7c00a85e78ed9340906d (diff)
downloadprogos-158ea87fba909161a084c29feff29a168725fe4e.tar.gz
progos-158ea87fba909161a084c29feff29a168725fe4e.tar.bz2
progos-158ea87fba909161a084c29feff29a168725fe4e.zip
first priority donation implementation
Diffstat (limited to 'threads/synch.c')
-rw-r--r--threads/synch.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/threads/synch.c b/threads/synch.c
index 317c68a..1f15bb9 100644
--- a/threads/synch.c
+++ b/threads/synch.c
@@ -32,6 +32,9 @@
32#include "threads/interrupt.h" 32#include "threads/interrupt.h"
33#include "threads/thread.h" 33#include "threads/thread.h"
34 34
35static bool lock_list_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b,
36 void *AUX UNUSED);
37
35/* Initializes semaphore SEMA to VALUE. A semaphore is a 38/* Initializes semaphore SEMA to VALUE. A semaphore is a
36 nonnegative integer along with two atomic operators for 39 nonnegative integer along with two atomic operators for
37 manipulating it: 40 manipulating it:
@@ -68,7 +71,8 @@ sema_down (struct semaphore *sema)
68 old_level = intr_disable (); 71 old_level = intr_disable ();
69 while (sema->value == 0) 72 while (sema->value == 0)
70 { 73 {
71 list_push_back (&sema->waiters, &thread_current ()->elem); 74 /* add thread to our ordered waiters list */
75 list_insert_ordered (&sema->waiters, &thread_current ()->elem, &priority_list_cmp_greater, NULL);
72 thread_block (); 76 thread_block ();
73 } 77 }
74 sema->value--; 78 sema->value--;
@@ -181,6 +185,17 @@ lock_init (struct lock *lock)
181 sema_init (&lock->semaphore, 1); 185 sema_init (&lock->semaphore, 1);
182} 186}
183 187
188/* comparison function for our descending ordered lock list. */
189static bool
190lock_list_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b,
191 void *AUX UNUSED)
192{
193 struct lock *l1 = list_entry (a, struct lock, elem);
194 struct lock *l2 = list_entry (b, struct lock, elem);
195 /* descending order - put newer in front */
196 return (l1->priority >= l2->priority);
197}
198
184/* Acquires LOCK, sleeping until it becomes available if 199/* Acquires LOCK, sleeping until it becomes available if
185 necessary. The lock must not already be held by the current 200 necessary. The lock must not already be held by the current
186 thread. 201 thread.
@@ -192,12 +207,41 @@ lock_init (struct lock *lock)
192void 207void
193lock_acquire (struct lock *lock) 208lock_acquire (struct lock *lock)
194{ 209{
210 struct thread *cur = thread_current ();
211
195 ASSERT (lock != NULL); 212 ASSERT (lock != NULL);
196 ASSERT (!intr_context ()); 213 ASSERT (!intr_context ());
197 ASSERT (!lock_held_by_current_thread (lock)); 214 ASSERT (!lock_held_by_current_thread (lock));
198 215
216 if (lock->holder != NULL)
217 {
218 //printf("[%d] acquire: lock=%p prio=%d\n", cur->tid, lock, cur->priority);
219
220 /* check for a possible priority donation */
221 if (cur->priority > lock->priority)
222 {
223 /* the new priority of this lock is our own priority */
224 lock->priority = cur->priority;
225
226 /* the lock priority changed so we need to sort the lock list of the lock holder */
227 list_remove (&lock->elem);
228 list_insert_ordered (&lock->holder->locks, &lock->elem,
229 lock_list_priority_cmp_greater, NULL);
230
231 /* finally donate our priority */
232 thread_donate_priority (cur, lock->holder);
233 }
234 }
235
199 sema_down (&lock->semaphore); 236 sema_down (&lock->semaphore);
200 lock->holder = thread_current (); 237 lock->holder = cur;
238
239 /* the priority of this lock is our own priority */
240 lock->priority = cur->priority;
241
242 /* save the locks we hold in descending order of their priority */
243 list_insert_ordered (&lock->holder->locks, &lock->elem,
244 lock_list_priority_cmp_greater, NULL);
201} 245}
202 246
203/* Tries to acquires LOCK and returns true if successful or false 247/* Tries to acquires LOCK and returns true if successful or false
@@ -228,11 +272,31 @@ lock_try_acquire (struct lock *lock)
228void 272void
229lock_release (struct lock *lock) 273lock_release (struct lock *lock)
230{ 274{
275 struct thread *cur = thread_current ();
276
231 ASSERT (lock != NULL); 277 ASSERT (lock != NULL);
232 ASSERT (lock_held_by_current_thread (lock)); 278 ASSERT (lock_held_by_current_thread (lock));
233 279
234 lock->holder = NULL; 280 lock->holder = NULL;
281 //lock->priority = we don't care as the next lock_acquire ()-call does
235 sema_up (&lock->semaphore); 282 sema_up (&lock->semaphore);
283
284 /* we don't hold the lock any longer so remove it from the lock list */
285 list_remove (&lock->elem);
286
287 if (list_empty (&cur->locks))
288 {
289 //printf("[%d] restoring prio from %d to %d\n", cur->tid, cur->priority, cur->saved_priority);
290 /* we don't hold another lock so restore our base priority */
291 thread_donation_pass_back ();
292 }
293 else
294 {
295 /* we still hold at least one lock so change our priority to the priority of the lock */
296 struct lock *lock2 = list_entry (list_front (&cur->locks), struct lock, elem);
297 /* (forced) priority change */
298 thread_other_set_priority (cur, lock2->priority);
299 }
236} 300}
237 301
238/* Returns true if the current thread holds LOCK, false 302/* Returns true if the current thread holds LOCK, false
@@ -295,7 +359,8 @@ cond_wait (struct condition *cond, struct lock *lock)
295 ASSERT (lock_held_by_current_thread (lock)); 359 ASSERT (lock_held_by_current_thread (lock));
296 360
297 sema_init (&waiter.semaphore, 0); 361 sema_init (&waiter.semaphore, 0);
298 list_push_back (&cond->waiters, &waiter.elem); 362 /* add thread to our ordered waiters list */
363 list_insert_ordered (&cond->waiters, &waiter.elem, &priority_list_cmp_greater, NULL);
299 lock_release (lock); 364 lock_release (lock);
300 sema_down (&waiter.semaphore); 365 sema_down (&waiter.semaphore);
301 lock_acquire (lock); 366 lock_acquire (lock);