aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/timer.c33
-rw-r--r--src/devices/timer.h5
-rw-r--r--src/threads/init.c15
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;