diff --git a/src/devices/timer.c b/src/devices/timer.c index f3bf93b5917a6453ac6d87c527e0ce107dd6759a..443fd6f14e7a95a3b12c345b7ce65701c21d6733 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -7,6 +7,7 @@ #include "threads/io.h" #include "threads/synch.h" #include "threads/thread.h" +#include "lib/kernel/list.h" /* See [8254] for hardware details of the 8254 timer chip. */ @@ -24,11 +25,30 @@ static int64_t ticks; Initialized by timer_calibrate(). */ static unsigned loops_per_tick; +//Sleep queue +static struct list sleep_q; + +struct sleep_elem{ +struct list_elem elem; +struct thread *sleep_thread; +int64_t sleep; + +}; + static intr_handler_func timer_interrupt; static bool too_many_loops (unsigned loops); static void busy_wait (int64_t loops); static void real_time_sleep (int64_t num, int32_t denom); + + + /* data */ + + + + + + /* Sets up the 8254 Programmable Interval Timer (PIT) to interrupt PIT_FREQ times per second, and registers the corresponding interrupt. */ @@ -44,6 +64,8 @@ timer_init (void) outb (0x40, count >> 8); intr_register_ext (0x20, timer_interrupt, "8254 Timer"); + + list_init(&sleep_q); } /* Calibrates loops_per_tick, used to implement brief delays. */ @@ -96,11 +118,28 @@ timer_elapsed (int64_t then) void timer_sleep (int64_t ticks) { - int64_t start = timer_ticks (); + + + int64_t interrupt_ticks = timer_ticks() + ticks; + + if(ticks <= 0){ + return; + } + + enum intr_level old_level; ASSERT (intr_get_level () == INTR_ON); - /*while (timer_elapsed (start) < ticks) - thread_yield ();*/ + old_level = intr_disable(); + + struct sleep_elem *p = malloc(sizeof(struct sleep_elem)); + p->sleep = interrupt_ticks; + + p->sleep_thread = thread_current(); + list_push_back(&sleep_q, &(p->elem)); + thread_block(); + free(p); + intr_set_level(old_level); + } /* Suspends execution for approximately MS milliseconds. */ @@ -135,8 +174,27 @@ timer_print_stats (void) static void timer_interrupt (struct intr_frame *args UNUSED) { + enum intr_level old_level; ticks++; thread_tick (); + + //Method for waking up sleeping threads that should be woken + old_level = intr_disable(); + struct list_elem *p; + + for(p = list_begin(&sleep_q); p != list_end(&sleep_q); p = list_next(p)){ + + struct sleep_elem *wakey = list_entry(p, struct sleep_elem, elem); + + if(ticks >= wakey->sleep){ + thread_unblock(wakey->sleep_thread); + list_remove(p); + } + + + } + + intr_set_level(old_level); } /* Returns true if LOOPS iterations waits for more than one timer