summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pintos-progos/devices/timer.c40
-rw-r--r--pintos-progos/threads/thread.h10
-rw-r--r--proj0.txt11
3 files changed, 40 insertions, 21 deletions
diff --git a/pintos-progos/devices/timer.c b/pintos-progos/devices/timer.c
index bf78351..3533fe7 100644
--- a/pintos-progos/devices/timer.c
+++ b/pintos-progos/devices/timer.c
@@ -30,16 +30,16 @@ static void busy_wait (int64_t loops);
30static void real_time_sleep (int64_t num, int32_t denom); 30static void real_time_sleep (int64_t num, int32_t denom);
31static void real_time_delay (int64_t num, int32_t denom); 31static void real_time_delay (int64_t num, int32_t denom);
32 32
33/* list of processes waiting for an alarm event 33/* list of processes waiting for an wakeup event
34 * and currently put to sleep */ 34 * and currently put to sleep */
35static struct list alarm_list; 35static struct list wakeup_list;
36 36
37/* Sets up the timer to interrupt TIMER_FREQ times per second, 37/* Sets up the timer to interrupt TIMER_FREQ times per second,
38 and registers the corresponding interrupt. */ 38 and registers the corresponding interrupt. */
39void 39void
40timer_init (void) 40timer_init (void)
41{ 41{
42 list_init (&alarm_list); 42 list_init (&wakeup_list);
43 pit_configure_channel (0, 2, TIMER_FREQ); 43 pit_configure_channel (0, 2, TIMER_FREQ);
44 intr_register_ext (0x20, timer_interrupt, "8254 Timer"); 44 intr_register_ext (0x20, timer_interrupt, "8254 Timer");
45} 45}
@@ -89,6 +89,16 @@ timer_elapsed (int64_t then)
89 return timer_ticks () - then; 89 return timer_ticks () - then;
90} 90}
91 91
92/* Comparison function for our ascending ordered wakeup list. */
93static bool
94wakeup_list_cmp_less(const struct list_elem *a, const struct list_elem *b,
95 void *AUX UNUSED)
96{
97 struct thread *t1 = list_entry (a, struct thread, elem);
98 struct thread *t2 = list_entry (b, struct thread, elem);
99 return (t1->wakeup_tick < t2->wakeup_tick);
100}
101
92/* Sleeps for approximately TICKS timer ticks. Interrupts must 102/* Sleeps for approximately TICKS timer ticks. Interrupts must
93 be turned on. */ 103 be turned on. */
94void 104void
@@ -97,20 +107,22 @@ timer_sleep (int64_t ticks)
97 struct thread *t = thread_current (); 107 struct thread *t = thread_current ();
98 enum intr_level old_level; 108 enum intr_level old_level;
99 109
110 ASSERT (intr_get_level () == INTR_ON);
111
100 /* nothing to sleep here */ 112 /* nothing to sleep here */
101 if (ticks <= 0) 113 if (ticks <= 0)
102 return; 114 return;
103 115
104 t->alarm_tick = timer_ticks () + ticks; 116 t->wakeup_tick = timer_ticks () + ticks;
105 117
106 /* add thread to alarm list 118 /* add thread to sorted wakeup list
107 * disable interrupts as this is critical */ 119 * disable interrupts as this is critical */
108 old_level = intr_disable (); 120 old_level = intr_disable ();
109 ASSERT (t->status == THREAD_RUNNING); 121 ASSERT (t->status == THREAD_RUNNING);
110 list_push_back (&alarm_list, &t->elem); 122 list_insert_ordered (&wakeup_list, &t->elem, &wakeup_list_cmp_less, NULL);
111 123
112 /* block the thread */ 124 /* block the thread */
113 thread_block(); 125 thread_block ();
114 126
115 /* restore interrupt */ 127 /* restore interrupt */
116 intr_set_level (old_level); 128 intr_set_level (old_level);
@@ -195,19 +207,21 @@ timer_interrupt (struct intr_frame *args UNUSED)
195 ticks++; 207 ticks++;
196 thread_tick (); 208 thread_tick ();
197 209
198 /* check for threads waiting for an alarm event */ 210 /* Check threads waiting to get woken up/unblocked.
199 for (el = list_begin (&alarm_list); el != list_end (&alarm_list); el = next) 211 * Since this is an ordered list we can bail out as soon
212 * as the first element doesn't need to get unblocked. */
213 for (el = list_begin (&wakeup_list); el != list_end (&wakeup_list); el = next)
200 { 214 {
201 struct thread *t = list_entry (el, struct thread, elem); 215 struct thread *t = list_entry (el, struct thread, elem);
202 if (t->alarm_tick == timer_ticks ()) 216 if (t->wakeup_tick == timer_ticks ())
203 { 217 {
204 next = list_remove (el); 218 next = list_remove (el);
205 /* unblock must be called AFTER removing, 219 /* unblock must be called AFTER removing,
206 * as thread_unblock() will reuse thread.elem */ 220 * as thread_unblock() will reuse t.elem */
207 thread_unblock (t); 221 thread_unblock (t);
222 continue;
208 } 223 }
209 else 224 break;
210 next = list_next (el);
211 } 225 }
212} 226}
213 227
diff --git a/pintos-progos/threads/thread.h b/pintos-progos/threads/thread.h
index 9cc5ef7..4ba5ef2 100644
--- a/pintos-progos/threads/thread.h
+++ b/pintos-progos/threads/thread.h
@@ -77,12 +77,12 @@ typedef int tid_t;
77 value, triggering the assertion. */ 77 value, triggering the assertion. */
78/* The `elem' member has a dual purpose. It can be an element in 78/* The `elem' member has a dual purpose. It can be an element in
79 the run queue (thread.c), it can be an element in a semaphore 79 the run queue (thread.c), it can be an element in a semaphore
80 wait list (synch.c), or it can be an element in the alarm sleep 80 wait list (synch.c), or it can be an element in the timer/alarm sleep
81 list (timer.c). It can be used these two ways only because they 81 list (timer.c). It can be used these three ways only because they
82 are mutually exclusive: only a thread in the ready state is on 82 are mutually exclusive: only a thread in the ready state is on
83 the run queue, only a thread in the blocked state is on a semaphore 83 the run queue, only a thread in the blocked state is on a semaphore
84 wait list, whereas only a thread waiting for an alarm event is on 84 wait list, whereas only a thread waiting for an timer/alarm event is on
85 the alarm sleep list. */ 85 the timer/alarm sleep list. */
86struct thread 86struct thread
87 { 87 {
88 /* Owned by thread.c. */ 88 /* Owned by thread.c. */
@@ -106,7 +106,7 @@ struct thread
106 /* Owned by thread.c. */ 106 /* Owned by thread.c. */
107 unsigned magic; /* Detects stack overflow. */ 107 unsigned magic; /* Detects stack overflow. */
108 108
109 int64_t alarm_tick; /* absolute tick when to trigger an alarm event */ 109 int64_t wakeup_tick; /* absolute tick when to wake up the thread */
110 }; 110 };
111 111
112/* If false (default), use round-robin scheduler. 112/* If false (default), use round-robin scheduler.
diff --git a/proj0.txt b/proj0.txt
index 8cdfb49..7284b9e 100644
--- a/proj0.txt
+++ b/proj0.txt
@@ -32,19 +32,24 @@ TODO
32>> enumeration. Identify the purpose of each in 25 words or less. 32>> enumeration. Identify the purpose of each in 25 words or less.
33 33
34struct thread: 34struct thread:
35int64_t alarm_tick ...absolute tick when to trigger an alarm event 35int64_t wakeup_tick ...absolute tick when to wake up the thread
36 36
37---- ALGORITHMS ---- 37---- ALGORITHMS ----
38 38
39>> A2: Briefly describe what happens in a call to timer_sleep(), 39>> A2: Briefly describe what happens in a call to timer_sleep(),
40>> including the effects of the timer interrupt handler. 40>> including the effects of the timer interrupt handler.
41 41
42TODO 42In case of a positive tick value we calculate the tick when to awake the
43current thread and store that inside the per thread structure. Afterwards
44we disable interrupts and insert the thread into our wakup list which is
45sorted by wakeup-tick in ascending order. Finally we block the thread
46and restore the interrupt value.
43 47
44>> A3: What steps are taken to minimize the amount of time spent in 48>> A3: What steps are taken to minimize the amount of time spent in
45>> the timer interrupt handler? 49>> the timer interrupt handler?
46 50
47TODO 51We sort our alarm/wake-up list by wakeup-tick value in ascending order.
52Thus we can return as soon as the first thread doesn't need to get unblocked.
48 53
49---- SYNCHRONIZATION ---- 54---- SYNCHRONIZATION ----
50 55