diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/timer.c | 33 | ||||
| -rw-r--r-- | src/devices/timer.h | 5 | ||||
| -rw-r--r-- | src/threads/init.c | 15 |
3 files changed, 33 insertions, 20 deletions
diff --git a/src/devices/timer.c b/src/devices/timer.c index 5bf8b27..750ac4c 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -10,13 +10,6 @@ /* See [8254] for hardware details of the 8254 timer chip. */ -#if TIMER_FREQ < 19 -#error 8254 timer requires TIMER_FREQ >= 19 -#endif -#if TIMER_FREQ > 1000 -#error TIMER_FREQ <= 1000 recommended -#endif - /* Number of timer ticks since OS booted. */ static int64_t ticks; @@ -24,6 +17,9 @@ static int64_t ticks; Initialized by timer_calibrate(). */ static unsigned loops_per_tick; +/* Interrupts per second, writen only by timer_init */ +static uint16_t TIMER_FREQ = 0; + static intr_handler_func timer_interrupt; static bool too_many_loops (unsigned loops); static void busy_wait (int64_t loops); @@ -33,8 +29,13 @@ static void real_time_sleep (int64_t num, int32_t denom); interrupt PIT_FREQ times per second, and registers the corresponding interrupt. */ void -timer_init (void) +timer_init (const uint16_t timer_freq) { + TIMER_FREQ = timer_freq; + + /* 8254 timer requires TIMER_FREQ >= 19 */ + ASSERT (TIMER_FREQ >= 19); + /* 8254 input frequency divided by TIMER_FREQ, rounded to nearest. */ uint16_t count = (1193180 + TIMER_FREQ / 2) / TIMER_FREQ; @@ -53,7 +54,14 @@ timer_calibrate (void) unsigned high_bit, test_bit; ASSERT (intr_get_level () == INTR_ON); - printf ("Calibrating timer... "); + ASSERT (TIMER_FREQ >= 19); + + /* klaar@ida 2016-05-03 (thanks to filst and antsu) + * TIMER_FREQ > 1000 => synchronization errors very rare + * TIMER_FREQ > 5000 => synchronization errors rare + * TIMER_FREQ > 10000 => frequent synch errors (good for testing) + */ + printf ("Calibrating timer... "); /* Approximate loops_per_tick as the largest power-of-two still less than one timer tick. */ @@ -128,6 +136,7 @@ timer_nsleep (int64_t ns) void timer_print_stats (void) { + printf ("Timer: %d interrupts per second\n", TIMER_FREQ); printf ("Timer: %"PRId64" ticks\n", timer_ticks ()); } @@ -174,7 +183,7 @@ busy_wait (int64_t loops) /* Sleep for approximately NUM/DENOM seconds. */ static void -real_time_sleep (int64_t num, int32_t denom) +real_time_sleep (int64_t num, int32_t denom) { /* Convert NUM/DENOM seconds into timer ticks, rounding down. @@ -185,6 +194,7 @@ real_time_sleep (int64_t num, int32_t denom) int64_t ticks = num * TIMER_FREQ / denom; ASSERT (intr_get_level () == INTR_ON); + ASSERT (TIMER_FREQ >= 19); if (ticks > 0) { /* We're waiting for at least one full timer tick. Use @@ -198,7 +208,6 @@ real_time_sleep (int64_t num, int32_t denom) sub-tick timing. We scale the numerator and denominator down by 1000 to avoid the possibility of overflow. */ ASSERT (denom % 1000 == 0); - busy_wait (loops_per_tick * num / 1000 * TIMER_FREQ / (denom / 1000)); + busy_wait (loops_per_tick * num / 1000 * TIMER_FREQ / (denom / 1000)); } } - diff --git a/src/devices/timer.h b/src/devices/timer.h index 38f08df..aee6033 100644 --- a/src/devices/timer.h +++ b/src/devices/timer.h @@ -4,10 +4,7 @@ #include <round.h> #include <stdint.h> -/* Number of timer interrupts per second. */ -#define TIMER_FREQ 1000 - -void timer_init (void); +void timer_init (uint16_t timer_freq); void timer_calibrate (void); int64_t timer_ticks (void); diff --git a/src/threads/init.c b/src/threads/init.c index e4df408..6633d2c 100644 --- a/src/threads/init.c +++ b/src/threads/init.c @@ -48,15 +48,20 @@ static bool format_filesys; /* -q: Power off after kernel tasks complete? */ bool power_off_when_done = false; -/* -Q: Force power off by klaar@ida... */ + +/* Options by klaar@ida */ + +/* -Q: Force power off */ bool force_off_when_done = false; -/* -tcf: Simulate failure in thread_create klaar@ida... */ +/* -F: Set timer frequency */ +static uint16_t init_timer_freq = 1000; +/* -tcf: Simulate failure in thread_create */ int thread_create_limit = 0; /* infinite */ static bool prevent_reqursive_off = false; static void hard_power_off (void) NO_RETURN; - + static void ram_init (void); static void paging_init (void); @@ -105,7 +110,7 @@ main (void) /* Initialize interrupt handlers. */ intr_init (); - timer_init (); + timer_init (init_timer_freq); kbd_init (); input_init (); #ifdef USERPROG @@ -248,6 +253,8 @@ parse_options (char **argv) power_off_when_done = true; else if (!strcmp (name, "-Q")) // klaar@ida power_off_when_done = force_off_when_done = true; + else if (!strcmp (name, "-F")) // klaar@ida + init_timer_freq = atoi (value); #ifdef FILESYS else if (!strcmp (name, "-f")) format_filesys = true; |
