Our scheduler has 64 priorities and thus 64 ready queues, numbered 0
(@code{PRI_MIN}) through 63 (@code{PRI_MAX}). Lower numbers correspond
-to @emph{higher} priorities, so that priority 0 is the highest priority
-and priority 63 is the lowest. Thread priority is calculated initially
+to lower priorities, so that priority 0 is the lowest priority
+and priority 63 is the highest. Thread priority is calculated initially
at thread initialization. It is also recalculated once every fourth
clock tick, for every thread. In either case, it is determined by
the formula
-@center @t{@var{priority} = (@var{recent_cpu} / 4) + (@var{nice} * 2)},
+@center @t{@var{priority} = @code{PRI_MAX} - (@var{recent_cpu} / 4) - (@var{nice} * 2)},
@noindent where @var{recent_cpu} is an estimate of the CPU time the
thread has used recently (see below) and @var{nice} is the thread's
Every thread has a @var{nice} value between -20 and 20 directly under
its control. Each thread also has a priority, between 0
(@code{PRI_MIN}) through 63 (@code{PRI_MAX}), which is recalculated
-using the following formula whenever the value of either term changes:
+using the following formula whenever the value of either variable term
+changes:
-@center @t{@var{priority} = (@var{recent_cpu} / 4) + (@var{nice} * 2)}.
+@center @t{@var{priority} = @code{PRI_MAX} - (@var{recent_cpu} / 4) - (@var{nice} * 2)}.
@var{recent_cpu} measures the amount of CPU time a thread has received
``recently.'' On each timer tick, the running thread's @var{recent_cpu}
to immediately yield the CPU.
Thread priorities range from @code{PRI_MIN} (0) to @code{PRI_MAX} (63).
-Lower numbers correspond to @emph{higher} priorities, so that priority 0
-is the highest priority and priority 63 is the lowest.
+Lower numbers correspond to lower priorities, so that priority 0
+is the lowest priority and priority 63 is the highest.
The initial thread priority is passed as an argument to
@func{thread_create}. If there's no reason to choose another
priority, use @code{PRI_DEFAULT} (31). The @code{PRI_} macros are
Priority donation only changes the priority of the donee
thread. The donor thread's priority is unchanged.
-Priority donation is not additive: if thread @var{A} (with priority 3) donates
-to thread @var{B} (with priority 5), then @var{B}'s new priority is 3, not 8.
+Priority donation is not additive: if thread @var{A} (with priority 5) donates
+to thread @var{B} (with priority 3), then @var{B}'s new priority is 5, not 8.
@item Can a thread's priority change while it is on the ready queue?
@deftypecv {Member} {@struct{thread}} {int} priority
A thread priority, ranging from @code{PRI_MIN} (0) to @code{PRI_MAX}
-(63). Lower numbers correspond to @emph{higher} priorities, so that
-priority 0 is the highest priority and priority 63 is the lowest.
+(63). Lower numbers correspond to lower priorities, so that
+priority 0 is the lowest priority and priority 63 is the highest.
Pintos as provided ignores thread priorities, but you will implement
priority scheduling in project 1 (@pxref{Priority Scheduling}).
@end deftypecv
+ const struct semaphore_elem *b
+ = list_entry (b_, struct semaphore_elem, elem);
+
-+ return a->thread->priority > b->thread->priority;
++ return a->thread->priority < b->thread->priority;
+}
+
/* If any threads are waiting on COND (protected by LOCK), then
+
/* Add to run queue. */
thread_unblock (t);
-+ if (priority < thread_get_priority ())
++ if (priority > thread_get_priority ())
+ thread_yield ();
return tid;
+ const struct thread *a = list_entry (a_, struct thread, elem);
+ const struct thread *b = list_entry (b_, struct thread, elem);
+
-+ return a->priority > b->priority;
++ return a->priority < b->priority;
+}
+
/* Transitions a blocked thread T to the ready-to-run state.
+ const struct thread *a = list_entry (a_, struct thread, donor_elem);
+ const struct thread *b = list_entry (b_, struct thread, donor_elem);
+
-+ return a->priority > b->priority;
++ return a->priority < b->priority;
+}
+
+/* Recomputes T's priority in terms of its normal priority and
+{
+ int old_priority = t->priority;
+ int default_priority = t->normal_priority;
-+ int donation = PRI_MAX;
++ int donation = PRI_MIN;
+ if (enable_mlfqs)
+ {
-+ default_priority = fix_round (t->recent_cpu) / 4 + t->nice * 2;
++ default_priority = PRI_MAX - fix_round (t->recent_cpu) / 4 - t->nice * 2;
+ if (default_priority < PRI_MIN)
+ default_priority = PRI_MIN;
+ else if (default_priority > PRI_MAX)
+ if (!list_empty (&t->donors))
+ donation = list_entry (list_max (&t->donors, donated_lower_priority, NULL),
+ struct thread, donor_elem)->priority;
-+ t->priority = donation < default_priority ? donation : default_priority;
-+ if (t->priority < old_priority && t->donee != NULL)
++ t->priority = donation > default_priority ? donation : default_priority;
++ if (t->priority > old_priority && t->donee != NULL)
+ thread_recompute_priority (t->donee);
+}
+
+ struct thread *max = list_entry (list_max (&ready_list,
+ thread_lower_priority, NULL),
+ struct thread, elem);
-+ if (max->priority < cur->priority)
++ if (max->priority > cur->priority)
+ thread_yield ();
+ }
+ intr_set_level (old_level);
for (i = 0; i < 10; i++)
{
- int priority = (i + 5) % 10 + PRI_DEFAULT + 1;
+ int priority = PRI_DEFAULT - (i + 5) % 10 - 1;
char name[16];
snprintf (name, sizeof name, "priority %d", priority);
thread_create (name, priority, alarm_priority_thread, NULL);
}
- thread_set_priority (PRI_MAX);
+ thread_set_priority (PRI_MIN);
for (i = 0; i < 10; i++)
sema_down (&wait_sema);
use tests::tests;
check_expected ([<<'EOF']);
(alarm-priority) begin
-(alarm-priority) Thread priority 32 woke up.
-(alarm-priority) Thread priority 33 woke up.
-(alarm-priority) Thread priority 34 woke up.
-(alarm-priority) Thread priority 35 woke up.
-(alarm-priority) Thread priority 36 woke up.
-(alarm-priority) Thread priority 37 woke up.
-(alarm-priority) Thread priority 38 woke up.
-(alarm-priority) Thread priority 39 woke up.
-(alarm-priority) Thread priority 40 woke up.
-(alarm-priority) Thread priority 41 woke up.
+(alarm-priority) Thread priority 30 woke up.
+(alarm-priority) Thread priority 29 woke up.
+(alarm-priority) Thread priority 28 woke up.
+(alarm-priority) Thread priority 27 woke up.
+(alarm-priority) Thread priority 26 woke up.
+(alarm-priority) Thread priority 25 woke up.
+(alarm-priority) Thread priority 24 woke up.
+(alarm-priority) Thread priority 23 woke up.
+(alarm-priority) Thread priority 22 woke up.
+(alarm-priority) Thread priority 21 woke up.
(alarm-priority) end
EOF
ASSERT (!enable_mlfqs);
msg ("Creating a high-priority thread 2.");
- thread_create ("thread 2", PRI_DEFAULT - 1, changing_thread, NULL);
+ thread_create ("thread 2", PRI_DEFAULT + 1, changing_thread, NULL);
msg ("Thread 2 should have just lowered its priority.");
- thread_set_priority (PRI_DEFAULT + 2);
+ thread_set_priority (PRI_DEFAULT - 2);
msg ("Thread 2 should have just exited.");
}
changing_thread (void *aux UNUSED)
{
msg ("Thread 2 now lowering priority.");
- thread_set_priority (PRI_DEFAULT + 1);
+ thread_set_priority (PRI_DEFAULT - 1);
msg ("Thread 2 exiting.");
}
lock_init (&lock);
cond_init (&condition);
- thread_set_priority (PRI_MAX);
+ thread_set_priority (PRI_MIN);
for (i = 0; i < 10; i++)
{
- int priority = (i + 7) % 10 + PRI_DEFAULT + 1;
+ int priority = PRI_DEFAULT - (i + 7) % 10 - 1;
char name[16];
snprintf (name, sizeof name, "priority %d", priority);
thread_create (name, priority, priority_condvar_thread, NULL);
use tests::tests;
check_expected ([<<'EOF']);
(priority-condvar) begin
-(priority-condvar) Thread priority 39 starting.
-(priority-condvar) Thread priority 40 starting.
-(priority-condvar) Thread priority 41 starting.
-(priority-condvar) Thread priority 32 starting.
-(priority-condvar) Thread priority 33 starting.
-(priority-condvar) Thread priority 34 starting.
-(priority-condvar) Thread priority 35 starting.
-(priority-condvar) Thread priority 36 starting.
-(priority-condvar) Thread priority 37 starting.
-(priority-condvar) Thread priority 38 starting.
+(priority-condvar) Thread priority 23 starting.
+(priority-condvar) Thread priority 22 starting.
+(priority-condvar) Thread priority 21 starting.
+(priority-condvar) Thread priority 30 starting.
+(priority-condvar) Thread priority 29 starting.
+(priority-condvar) Thread priority 28 starting.
+(priority-condvar) Thread priority 27 starting.
+(priority-condvar) Thread priority 26 starting.
+(priority-condvar) Thread priority 25 starting.
+(priority-condvar) Thread priority 24 starting.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 32 woke up.
+(priority-condvar) Thread priority 30 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 33 woke up.
+(priority-condvar) Thread priority 29 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 34 woke up.
+(priority-condvar) Thread priority 28 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 35 woke up.
+(priority-condvar) Thread priority 27 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 36 woke up.
+(priority-condvar) Thread priority 26 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 37 woke up.
+(priority-condvar) Thread priority 25 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 38 woke up.
+(priority-condvar) Thread priority 24 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 39 woke up.
+(priority-condvar) Thread priority 23 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 40 woke up.
+(priority-condvar) Thread priority 22 woke up.
(priority-condvar) Signaling...
-(priority-condvar) Thread priority 41 woke up.
+(priority-condvar) Thread priority 21 woke up.
(priority-condvar) end
EOF
lock_acquire (&a);
lock_acquire (&b);
- thread_create ("a", PRI_DEFAULT - 1, a_thread_func, &a);
+ thread_create ("a", PRI_DEFAULT + 1, a_thread_func, &a);
msg ("Main thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 1, thread_get_priority ());
+ PRI_DEFAULT + 1, thread_get_priority ());
- thread_create ("b", PRI_DEFAULT - 2, b_thread_func, &b);
+ thread_create ("b", PRI_DEFAULT + 2, b_thread_func, &b);
msg ("Main thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 2, thread_get_priority ());
+ PRI_DEFAULT + 2, thread_get_priority ());
lock_release (&b);
msg ("Thread b should have just finished.");
msg ("Main thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 1, thread_get_priority ());
+ PRI_DEFAULT + 1, thread_get_priority ());
lock_release (&a);
msg ("Thread a should have just finished.");
use tests::tests;
check_expected ([<<'EOF']);
(priority-donate-multiple) begin
-(priority-donate-multiple) Main thread should have priority 30. Actual priority: 30.
-(priority-donate-multiple) Main thread should have priority 29. Actual priority: 29.
+(priority-donate-multiple) Main thread should have priority 32. Actual priority: 32.
+(priority-donate-multiple) Main thread should have priority 33. Actual priority: 33.
(priority-donate-multiple) Thread b acquired lock b.
(priority-donate-multiple) Thread b finished.
(priority-donate-multiple) Thread b should have just finished.
-(priority-donate-multiple) Main thread should have priority 30. Actual priority: 30.
+(priority-donate-multiple) Main thread should have priority 32. Actual priority: 32.
(priority-donate-multiple) Thread a acquired lock a.
(priority-donate-multiple) Thread a finished.
(priority-donate-multiple) Thread a should have just finished.
locks.a = &a;
locks.b = &b;
- thread_create ("medium", PRI_DEFAULT - 1, medium_thread_func, &locks);
+ thread_create ("medium", PRI_DEFAULT + 1, medium_thread_func, &locks);
thread_yield ();
msg ("Low thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 1, thread_get_priority ());
+ PRI_DEFAULT + 1, thread_get_priority ());
- thread_create ("high", PRI_DEFAULT - 2, high_thread_func, &b);
+ thread_create ("high", PRI_DEFAULT + 2, high_thread_func, &b);
thread_yield ();
msg ("Low thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 2, thread_get_priority ());
+ PRI_DEFAULT + 2, thread_get_priority ());
lock_release (&a);
thread_yield ();
lock_acquire (locks->a);
msg ("Medium thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 2, thread_get_priority ());
+ PRI_DEFAULT + 2, thread_get_priority ());
msg ("Medium thread got the lock.");
lock_release (locks->a);
use tests::tests;
check_expected ([<<'EOF']);
(priority-donate-nest) begin
-(priority-donate-nest) Low thread should have priority 30. Actual priority: 30.
-(priority-donate-nest) Low thread should have priority 29. Actual priority: 29.
-(priority-donate-nest) Medium thread should have priority 29. Actual priority: 29.
+(priority-donate-nest) Low thread should have priority 32. Actual priority: 32.
+(priority-donate-nest) Low thread should have priority 33. Actual priority: 33.
+(priority-donate-nest) Medium thread should have priority 33. Actual priority: 33.
(priority-donate-nest) Medium thread got the lock.
(priority-donate-nest) High thread got the lock.
(priority-donate-nest) High thread finished.
lock_init (&lock);
lock_acquire (&lock);
- thread_create ("acquire1", PRI_DEFAULT - 1, acquire1_thread_func, &lock);
+ thread_create ("acquire1", PRI_DEFAULT + 1, acquire1_thread_func, &lock);
msg ("This thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 1, thread_get_priority ());
- thread_create ("acquire2", PRI_DEFAULT - 2, acquire2_thread_func, &lock);
+ PRI_DEFAULT + 1, thread_get_priority ());
+ thread_create ("acquire2", PRI_DEFAULT + 2, acquire2_thread_func, &lock);
msg ("This thread should have priority %d. Actual priority: %d.",
- PRI_DEFAULT - 2, thread_get_priority ());
+ PRI_DEFAULT + 2, thread_get_priority ());
lock_release (&lock);
msg ("acquire2, acquire1 must already have finished, in that order.");
msg ("This should be the last line before finishing this test.");
use tests::tests;
check_expected ([<<'EOF']);
(priority-donate-one) begin
-(priority-donate-one) This thread should have priority 30. Actual priority: 30.
-(priority-donate-one) This thread should have priority 29. Actual priority: 29.
+(priority-donate-one) This thread should have priority 32. Actual priority: 32.
+(priority-donate-one) This thread should have priority 33. Actual priority: 33.
(priority-donate-one) acquire2: got the lock
(priority-donate-one) acquire2: done
(priority-donate-one) acquire1: got the lock
ASSERT (output != NULL);
lock_init (&lock);
- thread_set_priority (PRI_DEFAULT - 2);
+ thread_set_priority (PRI_DEFAULT + 2);
for (i = 0; i < THREAD_CNT; i++)
{
char name[16];
d->iterations = 0;
d->lock = &lock;
d->op = &op;
- thread_create (name, PRI_DEFAULT - 1, simple_thread_func, d);
+ thread_create (name, PRI_DEFAULT + 1, simple_thread_func, d);
}
thread_set_priority (PRI_DEFAULT);
/* Make sure our priority is the default. */
ASSERT (thread_get_priority () == PRI_DEFAULT);
- thread_create ("high-priority", PRI_DEFAULT - 1, simple_thread_func, NULL);
+ thread_create ("high-priority", PRI_DEFAULT + 1, simple_thread_func, NULL);
msg ("The high-priority thread should have already completed.");
}
ASSERT (!enable_mlfqs);
sema_init (&sema, 0);
- thread_set_priority (PRI_MAX);
+ thread_set_priority (PRI_MIN);
for (i = 0; i < 10; i++)
{
- int priority = (i + 3) % 10 + PRI_DEFAULT + 1;
+ int priority = PRI_DEFAULT - (i + 3) % 10 - 1;
char name[16];
snprintf (name, sizeof name, "priority %d", priority);
thread_create (name, priority, priority_sema_thread, NULL);
use tests::tests;
check_expected ([<<'EOF']);
(priority-sema) begin
-(priority-sema) Thread priority 32 woke up.
+(priority-sema) Thread priority 30 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 33 woke up.
+(priority-sema) Thread priority 29 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 34 woke up.
+(priority-sema) Thread priority 28 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 35 woke up.
+(priority-sema) Thread priority 27 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 36 woke up.
+(priority-sema) Thread priority 26 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 37 woke up.
+(priority-sema) Thread priority 25 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 38 woke up.
+(priority-sema) Thread priority 24 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 39 woke up.
+(priority-sema) Thread priority 23 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 40 woke up.
+(priority-sema) Thread priority 22 woke up.
(priority-sema) Back in main thread.
-(priority-sema) Thread priority 41 woke up.
+(priority-sema) Thread priority 21 woke up.
(priority-sema) Back in main thread.
(priority-sema) end
EOF
void
thread_start (void)
{
- thread_create ("idle", PRI_MAX, idle, NULL);
+ thread_create ("idle", PRI_MIN, idle, NULL);
intr_enable ();
}
#define TID_ERROR ((tid_t) -1) /* Error value for tid_t. */
/* Thread priorities. */
-#define PRI_MIN 0 /* Highest priority. */
+#define PRI_MIN 0 /* Lowest priority. */
#define PRI_DEFAULT 31 /* Default priority. */
-#define PRI_MAX 63 /* Lowest priority. */
+#define PRI_MAX 63 /* Highest priority. */
/* A kernel thread or user process.