set_core_timer() now takes a periodic flag
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 4 May 2011 23:03:32 +0000 (16:03 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:02 +0000 (17:36 -0700)
So far the only use of set_core_timer() uses a one-shot timer.  The old
periodic style was resulting in a lot of confusing interrupts and
anomalous events, especially in KVM.  Regardless, I want a one-shot
timer.

Note that most people should never call set_core_timer().  If you do,
you'll conflict with the alarm code.  Just use the alarm stuff.

kern/arch/i686/apic.c
kern/arch/sparc/timer.c
kern/include/trap.h
kern/src/alarm.c
kern/src/blockdev.c
kern/src/syscall.c

index 8f3b4e9..4cd92e8 100644 (file)
@@ -90,10 +90,10 @@ void lapic_set_timer(uint32_t usec, bool periodic)
                          LAPIC_TIMER_DEFAULT_DIVISOR);
 }
 
-void set_core_timer(uint32_t usec)
+void set_core_timer(uint32_t usec, bool periodic)
 {
        if (usec)
-               lapic_set_timer(usec, TRUE);
+               lapic_set_timer(usec, periodic);
        else
                lapic_disable_timer();
 }
index 4bee962..0a30dc1 100644 (file)
@@ -18,8 +18,10 @@ timer_init(void)
        cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
 }
 
+/* Warning!  Sparc is unable to do a one-shot timer, so all timers are periodic,
+ * though that is not normally what we want. */
 void
-set_core_timer(uint32_t usec)
+set_core_timer(uint32_t usec, bool periodic)
 {
        set_timer(usec);
 }
index c45afce..8315e8e 100644 (file)
@@ -34,7 +34,7 @@ void print_trapframe(trapframe_t *tf);
 void page_fault_handler(trapframe_t *tf);
 /* Generic per-core timer interrupt handler.  set_percore_timer() will fire the
  * timer_interrupt(). */
-void set_core_timer(uint32_t usec);
+void set_core_timer(uint32_t usec, bool periodic);
 void timer_interrupt(struct trapframe *tf, void *data);
 
 void sysenter_init(void);
index da03cc9..9b6809f 100644 (file)
@@ -245,12 +245,12 @@ void set_pcpu_alarm_interrupt(uint64_t time, struct timer_chain *tchain)
                       "tchain %08p\n", time, now, rel_usec, pcpui_tchain);
                /* Note that sparc doesn't honor the one-shot setting, so you might get
                 * spurious interrupts. */
-               set_core_timer(rel_usec);       /* TODO: Want this to be one-shot */
+               set_core_timer(rel_usec, FALSE);
                /* Make sure the caller is setting the right tchain */
                assert(pcpui_tchain == tchain);
        } else  {
                /* Disarm */
-               set_core_timer(0);
+               set_core_timer(0, FALSE);
        }
 }
 
index 336a7d9..1e9b1ca 100644 (file)
@@ -124,7 +124,7 @@ int bdev_submit_request(struct block_device *bdev, struct block_request *breq)
        init_awaiter(waiter, breq_handler);
        /* Stitch things up, so we know how to find things later */
        waiter->data = breq;
-       /* Set for 5ms.  The time might not be accurate in KVM. */
+       /* Set for 5ms. */
        set_awaiter_rel(waiter, 5000);
        set_alarm(tchain, waiter);
 #else
@@ -141,9 +141,8 @@ void generic_breq_done(struct block_request *breq)
 #ifdef __i386__        /* Sparc can't restart kthreads yet */
        struct kthread *sleeper = __up_sem(&breq->sem);
        if (!sleeper) {
-               /* this is odd, but happened a lot with kvm, probably due to the ghetto
-                * lack of a one-shot per-core timer.  keeping this just in case. */
-               printk("[kernel] no one waiting on breq %08p\n", breq);
+               /* This shouldn't happen anymore.  Let brho know if it does. */
+               warn("[kernel] no one waiting on breq %08p", breq);
                return;
        }
        kthread_runnable(sleeper);
index 01360f6..71b672a 100644 (file)
@@ -101,8 +101,8 @@ static int sys_block(void)
        struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
        struct alarm_waiter a_waiter;
        init_awaiter(&a_waiter, 0);
-       /* Block for 5ms.  The time might not be accurate in KVM.  Note printing
-        * takes a few ms, so your printds won't be perfect. */
+       /* Block for 5ms.  Note printing takes a few ms, so your printds won't be
+        * perfect. */
        printd("[kernel] sys_block(), sleeping at %llu\n", read_tsc());
        set_awaiter_rel(&a_waiter, 5000);
        set_alarm(tchain, &a_waiter);