Fix comment.
[pintos-anon] / solutions / p1.patch
1 Index: src/devices/timer.c
2 diff -u src/devices/timer.c~ src/devices/timer.c
3 --- src/devices/timer.c~
4 +++ src/devices/timer.c
5 @@ -23,6 +23,9 @@ static volatile int64_t ticks;
6     Initialized by timer_calibrate(). */
7  static unsigned loops_per_tick;
8  
9 +/* Threads waiting in timer_sleep(). */
10 +static struct list wait_list;
11 +
12  static intr_handler_func timer_interrupt;
13  static bool too_many_loops (unsigned loops);
14  static void busy_wait (int64_t loops);
15 @@ -43,6 +46,8 @@ timer_init (void) 
16    outb (0x40, count >> 8);
17  
18    intr_register_ext (0x20, timer_interrupt, "8254 Timer");
19 +
20 +  list_init (&wait_list);
21  }
22  
23  /* Calibrates loops_per_tick, used to implement brief delays. */
24 @@ -87,15 +92,36 @@ timer_elapsed (int64_t then) 
25    return timer_ticks () - then;
26  }
27  
28 +/* Compares two threads based on their wake-up times. */
29 +static bool
30 +compare_threads_by_wakeup_time (const struct list_elem *a_,
31 +                                const struct list_elem *b_,
32 +                                void *aux UNUSED) 
33 +{
34 +  const struct thread *a = list_entry (a_, struct thread, timer_elem);
35 +  const struct thread *b = list_entry (b_, struct thread, timer_elem);
36 +
37 +  return a->wakeup_time < b->wakeup_time;
38 +}
39 +
40  /* Suspends execution for approximately TICKS timer ticks. */
41  void
42  timer_sleep (int64_t ticks) 
43  {
44 -  int64_t start = timer_ticks ();
45 +  struct thread *t = thread_current ();
46 +
47 +  /* Schedule our wake-up time. */
48 +  t->wakeup_time = timer_ticks () + ticks;
49  
50 +  /* Atomically insert the current thread into the wait list. */
51    ASSERT (intr_get_level () == INTR_ON);
52 -  while (timer_elapsed (start) < ticks) 
53 -    thread_yield ();
54 +  intr_disable ();
55 +  list_insert_ordered (&wait_list, &t->timer_elem,
56 +                       compare_threads_by_wakeup_time, NULL);
57 +  intr_enable ();
58 +
59 +  /* Wait. */
60 +  sema_down (&t->timer_sema);
61  }
62  
63  /* Suspends execution for approximately MS milliseconds. */
64 @@ -132,6 +158,16 @@ timer_interrupt (struct intr_frame *args
65  {
66    ticks++;
67    thread_tick ();
68 +
69 +  while (!list_empty (&wait_list))
70 +    {
71 +      struct thread *t = list_entry (list_front (&wait_list),
72 +                                     struct thread, timer_elem);
73 +      if (ticks < t->wakeup_time) 
74 +        break;
75 +      sema_up (&t->timer_sema);
76 +      list_pop_front (&wait_list);
77 +    }
78  }
79  
80  /* Returns true if LOOPS iterations waits for more than one timer
81 Index: src/threads/fixed-point.h
82 diff -u src/threads/fixed-point.h~ src/threads/fixed-point.h
83 --- src/threads/fixed-point.h~
84 +++ src/threads/fixed-point.h
85 @@ -0,0 +1,120 @@
86 +#ifndef THREADS_FIXED_POINT_H
87 +#define THREADS_FIXED_POINT_H
88 +
89 +#include <debug.h>
90 +
91 +/* Parameters. */
92 +#define FIX_BITS 32             /* Total bits per fixed-point number. */
93 +#define FIX_P 16                /* Number of integer bits. */
94 +#define FIX_Q 16                /* Number of fractional bits. */
95 +#define FIX_F (1 << FIX_Q)      /* pow(2, FIX_Q). */
96 +
97 +#define FIX_MIN_INT (-FIX_MAX_INT)      /* Smallest representable integer. */
98 +#define FIX_MAX_INT ((1 << FIX_P) - 1)  /* Largest representable integer. */
99 +
100 +/* A fixed-point number. */
101 +typedef struct 
102 +  {
103 +    int f;
104 +  }
105 +fixed_point_t;
106 +
107 +/* Returns a fixed-point number with F as its internal value. */
108 +static inline fixed_point_t
109 +__mk_fix (int f) 
110 +{
111 +  fixed_point_t x;
112 +  x.f = f;
113 +  return x;
114 +}
115 +
116 +/* Returns fixed-point number corresponding to integer N. */
117 +static inline fixed_point_t
118 +fix_int (int n) 
119 +{
120 +  ASSERT (n >= FIX_MIN_INT && n <= FIX_MAX_INT);
121 +  return __mk_fix (n * FIX_F);
122 +}
123 +
124 +/* Returns fixed-point number corresponding to N divided by D. */
125 +static inline fixed_point_t
126 +fix_frac (int n, int d) 
127 +{
128 +  ASSERT (d != 0);
129 +  ASSERT (n / d >= FIX_MIN_INT && n / d <= FIX_MAX_INT);
130 +  return __mk_fix ((long long) n * FIX_F / d);
131 +}
132 +
133 +/* Returns X rounded to the nearest integer. */
134 +static inline int
135 +fix_round (fixed_point_t x) 
136 +{
137 +  return (x.f + FIX_F / 2) / FIX_F;
138 +}
139 +
140 +/* Returns X truncated down to the nearest integer. */
141 +static inline int
142 +fix_trunc (fixed_point_t x) 
143 +{
144 +  return x.f / FIX_F;
145 +}
146 +
147 +/* Returns X + Y. */
148 +static inline fixed_point_t
149 +fix_add (fixed_point_t x, fixed_point_t y) 
150 +{
151 +  return __mk_fix (x.f + y.f);
152 +}
153 +
154 +/* Returns X - Y. */
155 +static inline fixed_point_t
156 +fix_sub (fixed_point_t x, fixed_point_t y) 
157 +{
158 +  return __mk_fix (x.f - y.f);
159 +}
160 +
161 +/* Returns X * Y. */
162 +static inline fixed_point_t
163 +fix_mul (fixed_point_t x, fixed_point_t y) 
164 +{
165 +  return __mk_fix ((long long) x.f * y.f / FIX_F);
166 +}
167 +
168 +/* Returns X * N. */
169 +static inline fixed_point_t
170 +fix_scale (fixed_point_t x, int n) 
171 +{
172 +  ASSERT (n >= 0);
173 +  return __mk_fix (x.f * n);
174 +}
175 +
176 +/* Returns X / Y. */
177 +static inline fixed_point_t
178 +fix_div (fixed_point_t x, fixed_point_t y) 
179 +{
180 +  return __mk_fix ((long long) x.f * FIX_F / y.f);
181 +}
182 +
183 +/* Returns X / N. */
184 +static inline fixed_point_t
185 +fix_unscale (fixed_point_t x, int n) 
186 +{
187 +  ASSERT (n > 0);
188 +  return __mk_fix (x.f / n);
189 +}
190 +
191 +/* Returns 1 / X. */
192 +static inline fixed_point_t
193 +fix_inv (fixed_point_t x) 
194 +{
195 +  return fix_div (fix_int (1), x);
196 +}
197 +
198 +/* Returns -1 if X < Y, 0 if X == Y, 1 if X > Y. */
199 +static inline int
200 +fix_compare (fixed_point_t x, fixed_point_t y) 
201 +{
202 +  return x.f < y.f ? -1 : x.f > y.f;
203 +}
204 +
205 +#endif /* threads/fixed-point.h */
206 Index: src/threads/synch.c
207 diff -u src/threads/synch.c~ src/threads/synch.c
208 --- src/threads/synch.c~
209 +++ src/threads/synch.c
210 @@ -114,10 +114,28 @@ sema_up (struct semaphore *sema) 
211    ASSERT (sema != NULL);
212  
213    old_level = intr_disable ();
214 -  if (!list_empty (&sema->waiters)) 
215 -    thread_unblock (list_entry (list_pop_front (&sema->waiters),
216 -                                struct thread, elem));
217    sema->value++;
218 +  if (!list_empty (&sema->waiters)) 
219 +    {
220 +      /* Find highest-priority waiting thread. */
221 +      struct thread *max = list_entry (list_max (&sema->waiters,
222 +                                                 thread_lower_priority, NULL),
223 +                                       struct thread, elem);
224 +
225 +      /* Remove `max' from wait list and unblock. */
226 +      list_remove (&max->elem);
227 +      thread_unblock (max);
228 +
229 +      /* Yield to a higher-priority thread, if we're running in a
230 +         context where it makes sense to do so.
231 +         
232 +         Kind of a funny interaction with donation here.
233 +         We only support donation for locks, and locks turn off
234 +         interrupts before calling us, so we automatically don't
235 +         do the yield here, delegating to lock_release(). */
236 +      if (!intr_context () && old_level == INTR_ON)
237 +        thread_yield_to_higher_priority ();
238 +    }
239    intr_set_level (old_level);
240  }
241  
242 @@ -200,8 +218,29 @@ lock_acquire (struct lock *lock)
243  lock_acquire (struct lock *lock)
244  {
245 +  enum intr_level old_level;
246 +
247    ASSERT (lock != NULL);
248    ASSERT (!intr_context ());
249    ASSERT (!lock_held_by_current_thread (lock));
250  
251 +  old_level = intr_disable ();
252 +
253 +  if (lock->holder != NULL) 
254 +    {
255 +      /* Donate our priority to the thread holding the lock.
256 +         First, update the data structures. */
257 +      struct thread *donor = thread_current ();
258 +      donor->want_lock = lock;
259 +      donor->donee = lock->holder;
260 +      list_push_back (&lock->holder->donors, &donor->donor_elem);
261 +      
262 +      /* Now implement the priority donation itself
263 +         by recomputing the donee's priority
264 +         and cascading the donation as far as necessary. */
265 +      if (donor->donee != NULL)
266 +        thread_recompute_priority (donor->donee);
267 +    }
268 +
269    sema_down (&lock->semaphore);
270    lock->holder = thread_current ();
271 +  intr_set_level (old_level);
272 @@ -238,9 +273,37 @@ void
273  lock_release (struct lock *lock) 
274  {
275 +  enum intr_level old_level;
276 +  struct thread *t = thread_current ();
277 +  struct list_elem *e;
278 +
279    ASSERT (lock != NULL);
280    ASSERT (lock_held_by_current_thread (lock));
281  
282 +  old_level = intr_disable ();
283 +
284 +  /* Return donations to threads that want this lock. */
285 +  for (e = list_begin (&t->donors); e != list_end (&t->donors); ) 
286 +    {
287 +      struct thread *donor = list_entry (e, struct thread, donor_elem);
288 +      if (donor->want_lock == lock) 
289 +        {
290 +          donor->donee = NULL;
291 +          e = list_remove (e);
292 +        }
293 +      else
294 +        e = list_next (e);
295 +    }
296 +
297 +  /* Release lock. */
298    lock->holder = NULL;
299    sema_up (&lock->semaphore);
300 +
301 +  /* Recompute our priority based on our remaining donations,
302 +     then yield to a higher-priority ready thread if one now
303 +     exists. */
304 +  thread_recompute_priority (t);
305 +  thread_yield_to_higher_priority ();
306 +
307 +  intr_set_level (old_level);
308  }
309  
310 @@ -264,6 +323,7 @@ struct semaphore_elem 
311    {
312      struct list_elem elem;              /* List element. */
313      struct semaphore semaphore;         /* This semaphore. */
314 +    struct thread *thread;              /* Thread. */
315    };
316  
317  /* Initializes condition variable COND.  A condition variable
318 @@ -308,12 +368,26 @@ cond_wait (struct condition *cond, struc
319    ASSERT (lock_held_by_current_thread (lock));
320    
321    sema_init (&waiter.semaphore, 0);
322 +  waiter.thread = thread_current ();
323    list_push_back (&cond->waiters, &waiter.elem);
324    lock_release (lock);
325    sema_down (&waiter.semaphore);
326    lock_acquire (lock);
327  }
328  
329 +static bool
330 +semaphore_elem_lower_priority (const struct list_elem *a_,
331 +                               const struct list_elem *b_,
332 +                               void *aux UNUSED) 
333 +{
334 +  const struct semaphore_elem *a
335 +    = list_entry (a_, struct semaphore_elem, elem);
336 +  const struct semaphore_elem *b
337 +    = list_entry (b_, struct semaphore_elem, elem);
338 +
339 +  return a->thread->priority < b->thread->priority;
340 +}
341 +
342  /* If any threads are waiting on COND (protected by LOCK), then
343     this function signals one of them to wake up from its wait.
344     LOCK must be held before calling this function.
345 @@ -330,8 +404,12 @@ cond_signal (struct condition *cond, str
346    ASSERT (lock_held_by_current_thread (lock));
347  
348    if (!list_empty (&cond->waiters)) 
349 -    sema_up (&list_entry (list_pop_front (&cond->waiters),
350 -                          struct semaphore_elem, elem)->semaphore);
351 +    {
352 +      struct list_elem *max
353 +        = list_max (&cond->waiters, semaphore_elem_lower_priority, NULL);
354 +      list_remove (max);
355 +      sema_up (&list_entry (max, struct semaphore_elem, elem)->semaphore); 
356 +    }
357  }
358  
359  /* Wakes up all threads, if any, waiting on COND (protected by
360 Index: src/threads/thread.c
361 diff -u src/threads/thread.c~ src/threads/thread.c
362 --- src/threads/thread.c~
363 +++ src/threads/thread.c
364 @@ -5,12 +5,14 @@
365  #include <stdio.h>
366  #include <string.h>
367  #include "threads/flags.h"
368 +#include "threads/init.h"
369  #include "threads/interrupt.h"
370  #include "threads/intr-stubs.h"
371  #include "threads/palloc.h"
372  #include "threads/switch.h"
373  #include "threads/synch.h"
374 +#include "devices/timer.h"
375  #include "threads/vaddr.h"
376  #ifdef USERPROG
377  #include "userprog/process.h"
378  #endif
379 @@ -24,6 +26,9 @@
380     that are ready to run but not actually running. */
381  static struct list ready_list;
382  
383 +/* List of all threads. */
384 +static struct list all_threads_list;
385 +
386  /* Idle thread. */
387  static struct thread *idle_thread;
388  
389 @@ -49,6 +54,7 @@ static long long user_ticks;    /* # of 
390  /* Scheduling. */
391  #define TIME_SLICE 4            /* # of timer ticks to give each thread. */
392  static unsigned thread_ticks;   /* # of timer ticks since last yield. */
393 +static fixed_point_t load_avg;  /* Load average. */
394  
395  static void kernel_thread (thread_func *, void *aux);
396  
397 @@ -79,12 +85,15 @@ thread_init (void) 
398  
399    lock_init (&tid_lock);
400    list_init (&ready_list);
401 +  list_init (&all_threads_list);
402 +  load_avg = fix_int (0);
403  
404    /* Set up a thread structure for the running thread. */
405    initial_thread = running_thread ();
406    init_thread (initial_thread, "main", PRI_DEFAULT);
407    initial_thread->status = THREAD_RUNNING;
408    initial_thread->tid = allocate_tid ();
409 +  list_push_front (&all_threads_list, &initial_thread->all_elem);
410  }
411  
412  /* Starts preemptive thread scheduling by enabling interrupts.
413 @@ -101,9 +110,48 @@ void
414    else
415      kernel_ticks++;
416  
417 -  /* Enforce preemption. */
418 -  if (++thread_ticks >= TIME_SLICE)
419 -    intr_yield_on_return ();
420 +  if (enable_mlfqs) 
421 +    {
422 +      /* Update load average. */
423 +      if (timer_ticks () % TIMER_FREQ == 0) 
424 +        {
425 +          size_t ready_threads = list_size (&ready_list);
426 +          if (t != idle_thread)
427 +            ready_threads++;
428 +
429 +          load_avg = fix_add (fix_mul (fix_frac (59, 60), load_avg),
430 +                              fix_mul (fix_frac (1, 60), fix_int (ready_threads)));
431 +        }
432 +
433 +      /* Increment running process's recent_cpu. */
434 +      if (t != idle_thread)
435 +        t->recent_cpu = fix_add (t->recent_cpu, fix_int (1));
436 +
437 +      /* Update recent_cpu and thread priorities once per second. */
438 +      if (timer_ticks () % TIMER_FREQ == 0) 
439 +        {
440 +          struct list_elem *e;
441 +          fixed_point_t twice_load = fix_scale (load_avg, 2);
442 +          fixed_point_t twice_load_plus_1 = fix_add (twice_load, fix_int (1));
443 +          fixed_point_t load_factor = fix_div (twice_load, twice_load_plus_1);
444 +          for (e = list_begin (&all_threads_list);
445 +               e != list_end (&all_threads_list); e = list_next (e)) 
446 +            {
447 +              struct thread *t = list_entry (e, struct thread, all_elem);
448 +              t->recent_cpu = fix_add (fix_mul (load_factor, t->recent_cpu),
449 +                                       fix_int (t->nice));
450 +              thread_recompute_priority (t);
451 +            }
452 +        }
453 +    }
454 +
455 +  /* Switch threads if time slice has expired. */
456 +  if (++thread_ticks >= TIME_SLICE) 
457 +    {
458 +      if (enable_mlfqs)
459 +        thread_recompute_priority (thread_current ());
460 +      intr_yield_on_return (); 
461 +    }
462  }
463  
464  /* Prints thread statistics. */
465 @@ -143,10 +191,12 @@ tid_t
466  thread_create (const char *name, int priority,
467                 thread_func *function, void *aux) 
468  {
469 +  struct thread *cur = thread_current ();
470    struct thread *t;
471    struct kernel_thread_frame *kf;
472    struct switch_entry_frame *ef;
473    struct switch_threads_frame *sf;
474 +  enum intr_level old_level;
475    tid_t tid;
476  
477    ASSERT (function != NULL);
478 @@ -157,8 +207,10 @@ thread_create (const char *name, int pri
479      return TID_ERROR;
480  
481    /* Initialize thread. */
482 -  init_thread (t, name, priority);
483 +  init_thread (t, name, enable_mlfqs ? cur->priority : priority);
484    tid = t->tid = allocate_tid ();
485 +  t->nice = cur->nice;
486 +  t->recent_cpu = cur->recent_cpu;
487  
488    /* Stack frame for kernel_thread(). */
489    kf = alloc_frame (t, sizeof *kf);
490 @@ -174,8 +226,15 @@ thread_create (const char *name, int pri
491    sf = alloc_frame (t, sizeof *sf);
492    sf->eip = switch_entry;
493  
494 +  /* Add to list of all threads. */
495 +  old_level = intr_disable ();
496 +  list_push_front (&all_threads_list, &t->all_elem);
497 +  intr_set_level (old_level);
498 +
499    /* Add to run queue. */
500    thread_unblock (t);
501 +  if (priority > thread_get_priority ())
502 +    thread_yield ();
503  
504    return tid;
505  }
506 @@ -196,6 +255,19 @@ thread_block (void) 
507    schedule ();
508  }
509  
510 +/* Returns true if A has lower priority than B,
511 +   within a list of threads. */
512 +bool
513 +thread_lower_priority (const struct list_elem *a_,
514 +                        const struct list_elem *b_,
515 +                        void *aux UNUSED) 
516 +{
517 +  const struct thread *a = list_entry (a_, struct thread, elem);
518 +  const struct thread *b = list_entry (b_, struct thread, elem);
519 +
520 +  return a->priority < b->priority;
521 +}
522 +
523  /* Transitions a blocked thread T to the ready-to-run state.
524     This is an error if T is not blocked.  (Use thread_yield() to
525     make the running thread ready.) */
526 @@ -260,6 +332,7 @@ thread_exit (void) 
527    /* Just set our status to dying and schedule another process.
528       We will be destroyed during the call to schedule_tail(). */
529    intr_disable ();
530 +  list_remove (&thread_current ()->all_elem);
531    thread_current ()->status = THREAD_DYING;
532    schedule ();
533    NOT_REACHED ();
534 @@ -282,11 +355,26 @@ thread_yield (void) 
535    intr_set_level (old_level);
536  }
537  
538 -/* Sets the current thread's priority to NEW_PRIORITY. */
539 +static void
540 +recompute_priority_chain (void) 
541 +{
542 +  enum intr_level old_level = intr_disable ();
543 +  thread_recompute_priority (thread_current ());
544 +  thread_yield_to_higher_priority ();
545 +  intr_set_level (old_level);
546 +}
547 +
548 +/* Sets the current thread's priority to PRIORITY. */
549  void
550 -thread_set_priority (int new_priority) 
551 +thread_set_priority (int priority) 
552  {
553 -  thread_current ()->priority = new_priority;
554 +  if (!enable_mlfqs) 
555 +    {
556 +      struct thread *t = thread_current ();
557 +
558 +      t->normal_priority = priority;
559 +      recompute_priority_chain ();
560 +    }
561  }
562  
563  /* Returns the current thread's priority. */
564 @@ -298,33 +386,93 @@ thread_get_priority (void) 
565  
566  /* Sets the current thread's nice value to NICE. */
567  void
568 -thread_set_nice (int nice UNUSED) 
569 +thread_set_nice (int nice) 
570  {
571 -  /* Not yet implemented. */
572 +  thread_current ()->nice = nice;
573 +  recompute_priority_chain ();
574  }
575  
576  /* Returns the current thread's nice value. */
577  int
578  thread_get_nice (void) 
579  {
580 -  /* Not yet implemented. */
581 -  return 0;
582 +  return thread_current ()->nice;
583  }
584  
585 -/* Returns 100 times the system load average. */
586  int
587  thread_get_load_avg (void) 
588  {
589 -  /* Not yet implemented. */
590 -  return 0;
591 +  int load_avg_int;
592 +  enum intr_level level = intr_disable ();
593 +  load_avg_int = fix_round (fix_scale (load_avg, 100));
594 +  intr_set_level (level);
595 +  return load_avg_int;
596  }
597  
598 -/* Returns 100 times the current thread's recent_cpu value. */
599  int
600  thread_get_recent_cpu (void) 
601  {
602 -  /* Not yet implemented. */
603 -  return 0;
604 +  int recent_cpu_int;
605 +  enum intr_level level = intr_disable ();
606 +  recent_cpu_int = fix_round (fix_scale (thread_current ()->recent_cpu, 100));
607 +  intr_set_level (level);
608 +  return recent_cpu_int;
609 +}
610 +
611 +/* Returns true if thread A has lower priority than thread B,
612 +   within a list of donors. */
613 +static bool
614 +donated_lower_priority (const struct list_elem *a_,
615 +                        const struct list_elem *b_,
616 +                        void *aux UNUSED) 
617 +{
618 +  const struct thread *a = list_entry (a_, struct thread, donor_elem);
619 +  const struct thread *b = list_entry (b_, struct thread, donor_elem);
620 +
621 +  return a->priority < b->priority;
622 +}
623 +
624 +/* Recomputes T's priority in terms of its normal priority and
625 +   its donors' priorities, if any,
626 +   and cascades the donation as necessary. */
627 +void
628 +thread_recompute_priority (struct thread *t) 
629 +{
630 +  int old_priority = t->priority;
631 +  int default_priority = t->normal_priority;
632 +  int donation = PRI_MIN;
633 +  if (enable_mlfqs) 
634 +    {
635 +      default_priority = PRI_MAX - fix_round (t->recent_cpu) / 4 - t->nice * 2;
636 +      if (default_priority < PRI_MIN)
637 +        default_priority = PRI_MIN;
638 +      else if (default_priority > PRI_MAX)
639 +        default_priority = PRI_MAX; 
640 +    }
641 +  if (!list_empty (&t->donors))
642 +    donation = list_entry (list_max (&t->donors, donated_lower_priority, NULL),
643 +                           struct thread, donor_elem)->priority;
644 +  t->priority = donation > default_priority ? donation : default_priority;
645 +  if (t->priority > old_priority && t->donee != NULL)
646 +    thread_recompute_priority (t->donee);
647 +}
648 +
649 +/* If the ready list contains a thread with a higher priority,
650 +   yields to it. */
651 +void
652 +thread_yield_to_higher_priority (void)
653 +{
654 +  enum intr_level old_level = intr_disable ();
655 +  if (!list_empty (&ready_list)) 
656 +    {
657 +      struct thread *cur = thread_current ();
658 +      struct thread *max = list_entry (list_max (&ready_list,
659 +                                                 thread_lower_priority, NULL),
660 +                                       struct thread, elem);
661 +      if (max->priority > cur->priority)
662 +        thread_yield (); 
663 +    }
664 +  intr_set_level (old_level);
665  }
666  \f
667  /* Idle thread.  Executes when no other thread is ready to run. */
668 @@ -399,8 +547,10 @@ init_thread (struct thread *t, const cha
669    t->status = THREAD_BLOCKED;
670    strlcpy (t->name, name, sizeof t->name);
671    t->stack = (uint8_t *) t + PGSIZE;
672 -  t->priority = priority;
673 +  t->priority = t->normal_priority = priority;
674    t->magic = THREAD_MAGIC;
675 +  sema_init (&t->timer_sema, 0);
676 +  list_init (&t->donors);
677  }
678  
679  /* Allocates a SIZE-byte frame at the top of thread T's stack and
680 @@ -426,8 +576,14 @@ next_thread_to_run (void) 
681  {
682    if (list_empty (&ready_list))
683      return idle_thread;
684 -  else
685 -    return list_entry (list_pop_front (&ready_list), struct thread, elem);
686 +  else 
687 +    {
688 +      struct thread *max
689 +        = list_entry (list_max (&ready_list, thread_lower_priority, NULL),
690 +                      struct thread, elem);
691 +      list_remove (&max->elem);
692 +      return max;
693 +    }
694  }
695  
696  /* Completes a thread switch by activating the new thread's page
697 Index: src/threads/thread.h
698 diff -u src/threads/thread.h~ src/threads/thread.h
699 --- src/threads/thread.h~
700 +++ src/threads/thread.h
701 @@ -4,6 +4,8 @@
702  #include <debug.h>
703  #include <list.h>
704  #include <stdint.h>
705 +#include "threads/synch.h"
706 +#include "threads/fixed-point.h"
707  
708  /* States in a thread's life cycle. */
709  enum thread_status
710 @@ -87,11 +89,26 @@ struct thread
711      enum thread_status status;          /* Thread state. */
712      char name[16];                      /* Name (for debugging purposes). */
713      uint8_t *stack;                     /* Saved stack pointer. */
714 -    int priority;                       /* Priority. */
715 +
716 +    /* Scheduler data. */
717 +    int priority;                       /* Priority, including donations. */
718 +    int normal_priority;                /* Priority, without donations. */
719 +    struct list donors;                 /* Threads donating priority to us. */
720 +    struct list_elem donor_elem;        /* Element in donors list. */
721 +    struct thread *donee;               /* Thread we're donating to. */
722 +    struct lock *want_lock;             /* Lock we're waiting to acquire. */
723 +    int nice;                           /* Niceness. */
724 +    fixed_point_t recent_cpu;           /* Recent amount of CPU time. */    
725 +    struct list_elem all_elem;          /* all_threads list element. */
726  
727      /* Shared between thread.c and synch.c. */
728      struct list_elem elem;              /* List element. */
729  
730 +    /* Alarm clock. */
731 +    int64_t wakeup_time;                /* Time to wake this thread up. */
732 +    struct list_elem timer_elem;        /* Element in wait_list. */
733 +    struct semaphore timer_sema;        /* Semaphore. */
734 +
735  #ifdef USERPROG
736      /* Owned by userprog/process.c. */
737      uint32_t *pagedir;                  /* Page directory. */
738 @@ -118,6 +135,10 @@ const char *thread_name (void);
739  
740  void thread_exit (void) NO_RETURN;
741  void thread_yield (void);
742 +void thread_yield_to_higher_priority (void);
743 +void thread_recompute_priority (struct thread *);
744 +bool thread_lower_priority (const struct list_elem *, const struct list_elem *,
745 +                            void *aux);
746  
747  int thread_get_priority (void);
748  void thread_set_priority (int);