summaryrefslogtreecommitdiffstats
path: root/threads/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'threads/thread.c')
-rw-r--r--threads/thread.c86
1 files changed, 74 insertions, 12 deletions
diff --git a/threads/thread.c b/threads/thread.c
index 3fefbd8..17d21bd 100644
--- a/threads/thread.c
+++ b/threads/thread.c
@@ -71,9 +71,9 @@ static void schedule (void);
71void thread_schedule_tail (struct thread *prev); 71void thread_schedule_tail (struct thread *prev);
72static tid_t allocate_tid (void); 72static tid_t allocate_tid (void);
73 73
74//TODO: should take donated priority into account 74/* comparison function for our descending ordered ready list. */
75static bool 75bool
76ready_list_cmp_less(const struct list_elem *a, const struct list_elem *b, 76priority_list_cmp_greater(const struct list_elem *a, const struct list_elem *b,
77 void *AUX UNUSED) 77 void *AUX UNUSED)
78{ 78{
79 struct thread *t1 = list_entry (a, struct thread, elem); 79 struct thread *t1 = list_entry (a, struct thread, elem);
@@ -222,7 +222,10 @@ thread_create (const char *name, int priority,
222 222
223 /* Add to run queue. */ 223 /* Add to run queue. */
224 thread_unblock (t); 224 thread_unblock (t);
225 thread_yield (); 225
226 /* and yield the cpu in case we have a higher priority */
227 if (t->priority > thread_current ()->priority)
228 thread_yield ();
226 229
227 return tid; 230 return tid;
228} 231}
@@ -261,7 +264,7 @@ thread_unblock (struct thread *t)
261 old_level = intr_disable (); 264 old_level = intr_disable ();
262 ASSERT (t->status == THREAD_BLOCKED); 265 ASSERT (t->status == THREAD_BLOCKED);
263 /* add thread to our ordered ready_list */ 266 /* add thread to our ordered ready_list */
264 list_insert_ordered (&ready_list, &t->elem, &ready_list_cmp_less, NULL); 267 list_insert_ordered (&ready_list, &t->elem, &priority_list_cmp_greater, NULL);
265 t->status = THREAD_READY; 268 t->status = THREAD_READY;
266 intr_set_level (old_level); 269 intr_set_level (old_level);
267} 270}
@@ -332,7 +335,7 @@ thread_yield (void)
332 335
333 old_level = intr_disable (); 336 old_level = intr_disable ();
334 if (cur != idle_thread) 337 if (cur != idle_thread)
335 list_insert_ordered (&ready_list, &cur->elem, &ready_list_cmp_less, NULL); 338 list_insert_ordered (&ready_list, &cur->elem, &priority_list_cmp_greater, NULL);
336 cur->status = THREAD_READY; 339 cur->status = THREAD_READY;
337 schedule (); 340 schedule ();
338 intr_set_level (old_level); 341 intr_set_level (old_level);
@@ -359,14 +362,71 @@ thread_foreach (thread_action_func *func, void *aux)
359void 362void
360thread_set_priority (int new_priority) 363thread_set_priority (int new_priority)
361{ 364{
362 thread_current ()->priority = new_priority; 365 struct thread *cur = thread_current ();
366 if (cur->priority == new_priority)
367 return;
368
369 if (cur->is_donated)
370 {
371 cur->saved_priority = new_priority;
372 /* make sure we don't lower a donated priority */
373 if (new_priority < cur->priority)
374 return;
375 }
376 thread_other_set_priority (cur, new_priority);
377}
363 378
364 /* compare priority with the highest priority in the list */ 379void
365 if (!list_empty (&ready_list)) 380thread_other_set_priority (struct thread *t, int new_priority)
381{
382 ASSERT (is_thread (t));
383
384 if (t->priority == new_priority)
385 return;
386
387 t->priority = new_priority;
388
389 if (t->status == THREAD_READY)
390 {
391 /* sort our ordered list */
392 list_remove (&t->elem);
393 list_insert_ordered (&ready_list, &t->elem, &priority_list_cmp_greater, NULL);
394 }
395 else if (t->status == THREAD_RUNNING && !list_empty (&ready_list))
396 {
397 /* compare priority with the highest priority in the list */
398 struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem);
399 if (t2->priority > t->priority)
400 thread_yield ();
401 }
402}
403
404void
405thread_donate_priority (struct thread *donator, struct thread *donee)
406{
407 ASSERT (is_thread (donator));
408 ASSERT (is_thread (donee));
409
410 /* make sure we don't lower a donated priority */
411 if (donator->priority < donee->priority)
412 return;
413
414 /* store our base priority */
415 if (!donee->is_donated)
416 {
417 donee->saved_priority = donee->priority;
418 donee->is_donated = true;
419 }
420 thread_other_set_priority (donee, donator->priority);
421}
422
423void
424thread_donation_pass_back (void)
425{
426 if (thread_current ()->is_donated)
366 { 427 {
367 struct thread *t = list_entry (list_front (&ready_list), struct thread, elem); 428 thread_current ()->is_donated = false;
368 if (t->priority > thread_current ()->priority) 429 thread_set_priority (thread_current ()->saved_priority);
369 thread_yield();
370 } 430 }
371} 431}
372 432
@@ -497,6 +557,8 @@ init_thread (struct thread *t, const char *name, int priority)
497#ifdef USERPROG 557#ifdef USERPROG
498 list_init(&t->children); 558 list_init(&t->children);
499#endif 559#endif
560 t->is_donated = false;
561 list_init (&t->locks);
500} 562}
501 563
502/* Allocates a SIZE-byte frame at the top of thread T's stack and 564/* Allocates a SIZE-byte frame at the top of thread T's stack and