summaryrefslogtreecommitdiffstats
path: root/pintos-progos/devices/timer.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-03-26 20:18:23 +0200
committermanuel <manuel@mausz.at>2012-03-26 20:18:23 +0200
commit11c1519a12cdae1ce05d31a6e389a103259c6c93 (patch)
treede8b4a9c5ae617098c274733d1b3562f1a89d680 /pintos-progos/devices/timer.c
parentb5f0874cd96ee2a62aabc645b9626c2749cb6a01 (diff)
downloadprogos-11c1519a12cdae1ce05d31a6e389a103259c6c93.tar.gz
progos-11c1519a12cdae1ce05d31a6e389a103259c6c93.tar.bz2
progos-11c1519a12cdae1ce05d31a6e389a103259c6c93.zip
first timer alarm implementation
Diffstat (limited to 'pintos-progos/devices/timer.c')
-rw-r--r--pintos-progos/devices/timer.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/pintos-progos/devices/timer.c b/pintos-progos/devices/timer.c
index befaaae..bf78351 100644
--- a/pintos-progos/devices/timer.c
+++ b/pintos-progos/devices/timer.c
@@ -30,11 +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
34 * and currently put to sleep */
35static struct list alarm_list;
36
33/* Sets up the timer to interrupt TIMER_FREQ times per second, 37/* Sets up the timer to interrupt TIMER_FREQ times per second,
34 and registers the corresponding interrupt. */ 38 and registers the corresponding interrupt. */
35void 39void
36timer_init (void) 40timer_init (void)
37{ 41{
42 list_init (&alarm_list);
38 pit_configure_channel (0, 2, TIMER_FREQ); 43 pit_configure_channel (0, 2, TIMER_FREQ);
39 intr_register_ext (0x20, timer_interrupt, "8254 Timer"); 44 intr_register_ext (0x20, timer_interrupt, "8254 Timer");
40} 45}
@@ -89,11 +94,26 @@ timer_elapsed (int64_t then)
89void 94void
90timer_sleep (int64_t ticks) 95timer_sleep (int64_t ticks)
91{ 96{
92 int64_t start = timer_ticks (); 97 struct thread *t = thread_current ();
98 enum intr_level old_level;
93 99
94 ASSERT (intr_get_level () == INTR_ON); 100 /* nothing to sleep here */
95 while (timer_elapsed (start) < ticks) 101 if (ticks <= 0)
96 thread_yield (); 102 return;
103
104 t->alarm_tick = timer_ticks () + ticks;
105
106 /* add thread to alarm list
107 * disable interrupts as this is critical */
108 old_level = intr_disable ();
109 ASSERT (t->status == THREAD_RUNNING);
110 list_push_back (&alarm_list, &t->elem);
111
112 /* block the thread */
113 thread_block();
114
115 /* restore interrupt */
116 intr_set_level (old_level);
97} 117}
98 118
99/* Sleeps for approximately MS milliseconds. Interrupts must be 119/* Sleeps for approximately MS milliseconds. Interrupts must be
@@ -170,8 +190,25 @@ timer_print_stats (void)
170static void 190static void
171timer_interrupt (struct intr_frame *args UNUSED) 191timer_interrupt (struct intr_frame *args UNUSED)
172{ 192{
193 struct list_elem *el, *next;
194
173 ticks++; 195 ticks++;
174 thread_tick (); 196 thread_tick ();
197
198 /* check for threads waiting for an alarm event */
199 for (el = list_begin (&alarm_list); el != list_end (&alarm_list); el = next)
200 {
201 struct thread *t = list_entry (el, struct thread, elem);
202 if (t->alarm_tick == timer_ticks ())
203 {
204 next = list_remove (el);
205 /* unblock must be called AFTER removing,
206 * as thread_unblock() will reuse thread.elem */
207 thread_unblock (t);
208 }
209 else
210 next = list_next (el);
211 }
175} 212}
176 213
177/* Returns true if LOOPS iterations waits for more than one timer 214/* Returns true if LOOPS iterations waits for more than one timer