diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2021-02-16 08:45:27 +0100 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2021-02-16 08:45:27 +0100 |
| commit | 542847ff42dcf6e67a5bd555d450d4f369e5654a (patch) | |
| tree | 51d6ac8ac2b8be8d5ac85e361d22acce8e7ae96d /src/devices/timer.c | |
| parent | 6c0df53eacd6fa9b03ea3f6cfbae1bf69bf3f474 (diff) | |
| download | pintos-542847ff42dcf6e67a5bd555d450d4f369e5654a.tar.gz | |
implement timer_sleep better
Diffstat (limited to 'src/devices/timer.c')
| -rw-r--r-- | src/devices/timer.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/src/devices/timer.c b/src/devices/timer.c index a4521de..5b9e527 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -1,6 +1,7 @@ #include "devices/timer.h" #include <debug.h> #include <inttypes.h> +#include <list.h> #include <round.h> #include <stdio.h> #include "threads/interrupt.h" @@ -17,6 +18,13 @@ #error TIMER_FREQ <= 1000 recommended #endif +struct waiting_thread + { + struct list_elem elem; + struct semaphore sema; + int64_t tick_target; + }; + /* Number of timer ticks since OS booted. */ static int64_t ticks; @@ -24,6 +32,8 @@ static int64_t ticks; Initialized by timer_calibrate(). */ static unsigned loops_per_tick; +static struct list waiting_threads; + static intr_handler_func timer_interrupt; static bool too_many_loops (unsigned loops); static void busy_wait (int64_t loops); @@ -43,6 +53,8 @@ timer_init (void) outb (0x40, count & 0xff); outb (0x40, count >> 8); + list_init (&waiting_threads); + intr_register_ext (0x20, timer_interrupt, "8254 Timer"); } @@ -98,9 +110,13 @@ timer_sleep (int64_t ticks) { int64_t start = timer_ticks (); - ASSERT (intr_get_level () == INTR_ON); - while (timer_elapsed (start) < ticks) - thread_yield (); + struct waiting_thread waiting_thread; + waiting_thread.tick_target = start + ticks; + + sema_init (&waiting_thread.sema, 0); + list_push_back (&waiting_threads, &waiting_thread.elem); + + sema_down (&waiting_thread.sema); } /* Suspends execution for approximately MS milliseconds. */ @@ -137,6 +153,17 @@ timer_interrupt (struct intr_frame *args UNUSED) { ticks++; thread_tick (); + + struct list_elem *e = list_begin (&waiting_threads); + while (e != list_end (&waiting_threads)) { + struct list_elem *next = list_next (e); + struct waiting_thread *waiting_thread = list_entry (e, struct waiting_thread, elem); + if (ticks >= waiting_thread->tick_target) { + sema_up (&waiting_thread->sema); + list_remove (e); + } + e = next; + } } /* Returns true if LOOPS iterations waits for more than one timer |
