X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdevices%2Ftimer.c;h=1706201f4ea8590b54a9bc58792667128bb23cf7;hb=f2f8875638593bd5365cfd6a5ba7c9578e52322f;hp=4adca8989cf1192612a0c009d187f999c2d5e25a;hpb=f8cae751ac2163f5fe73d5b1372c93ada35dc9e3;p=pintos-anon diff --git a/src/devices/timer.c b/src/devices/timer.c index 4adca89..1706201 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -1,16 +1,16 @@ -#include "timer.h" -#include "debug.h" -#include "interrupt.h" -#include "io.h" +#include "devices/timer.h" +#include +#include "threads/interrupt.h" +#include "threads/io.h" -static volatile uint64_t ticks; +#if TIMER_FREQ < 19 +#error 8254 timer requires TIMER_FREQ >= 19 +#endif -static void -irq20_timer (struct intr_frame *args UNUSED) -{ - ticks++; - intr_yield_on_return (); -} +/* Number of timer ticks since OS booted. */ +static volatile int64_t ticks; + +static intr_handler_func timer_interrupt; /* Sets up the 8254 Programmable Interrupt Timer (PIT) to interrupt PIT_FREQ times per second, and registers the @@ -26,28 +26,58 @@ timer_init (void) outb (0x40, count & 0xff); outb (0x40, count >> 8); - intr_register (0x20, 0, IF_OFF, irq20_timer); + intr_register (0x20, 0, INTR_OFF, timer_interrupt, "8254 Timer"); } -uint64_t +/* Returns the number of timer ticks since the OS booted. */ +int64_t timer_ticks (void) { - enum if_level old_level = intr_disable (); - uint64_t t = ticks; + enum intr_level old_level = intr_disable (); + int64_t t = ticks; intr_set_level (old_level); return t; } -uint64_t -timer_elapsed (uint64_t then) +/* Returns the number of timer ticks elapsed since THEN, which + should be a value once returned by timer_ticks(). */ +int64_t +timer_elapsed (int64_t then) +{ + return timer_ticks () - then; +} + +/* Suspends execution for approximately MS milliseconds. */ +void +timer_msleep (int64_t ms) +{ + int64_t ticks = (int64_t) ms * TIMER_FREQ / 1000; + int64_t start = timer_ticks (); + + while (timer_elapsed (start) < ticks) + continue; +} + +/* Suspends execution for approximately US microseconds. + Note: this is ridiculously inaccurate. */ +void +timer_usleep (int64_t us) { - uint64_t now = timer_ticks (); - return now > then ? now - then : ((uint64_t) -1 - then) + now + 1; + timer_msleep (us / 1000 + 1); } -/* Suspends execution for at least DURATION ticks. */ +/* Suspends execution for approximately NS nanoseconds. + Note: this is ridiculously inaccurate. */ void -timer_wait_until (uint64_t duration) +timer_nsleep (int64_t ns) { - /* FIXME */ + timer_msleep (ns / 1000000 + 1); +} + +/* Timer interrupt handler. */ +static void +timer_interrupt (struct intr_frame *args UNUSED) +{ + ticks++; + intr_yield_on_return (); }