]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - Single shot local timer
authorTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:11:06 +0000 (14:11 +0000)
committerTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:11:06 +0000 (14:11 +0000)
- APIC timer always reprogrammed if expired

- timer tick never happens when in kernel => never immediate return
  from userspace to kernel because of a buffered interrupt

- renamed argument to lapic_set_timer_one_shot()

- removed arch_ prefix from timer functions

kernel/arch/i386/apic.c
kernel/arch/i386/arch_clock.c
kernel/arch/i386/arch_smp.c
kernel/clock.c
kernel/clock.h
kernel/main.c
kernel/proc.c
kernel/smp.c

index 3a3b90ae76da38cdf7f1954b41486429d01d0e97..53bad419cf66a7afb07c8223145e12217a3b41cb 100644 (file)
@@ -499,7 +499,7 @@ PRIVATE void apic_calibrate_clocks(unsigned cpu)
        BOOT_VERBOSE(cpu_print_freq(cpuid));
 }
 
-PUBLIC void lapic_set_timer_one_shot(const u32_t value)
+PUBLIC void lapic_set_timer_one_shot(const u32_t usec)
 {
        /* sleep in micro seconds */
        u32_t lvtt;
@@ -508,7 +508,6 @@ PUBLIC void lapic_set_timer_one_shot(const u32_t value)
 
        ticks_per_us = lapic_bus_freq[cpu] / 1000000;
 
-       /* calculate divisor and count from value */
        lvtt = APIC_TDCR_1;
        lapic_write(LAPIC_TIMER_DCR, lvtt);
 
@@ -516,7 +515,7 @@ PUBLIC void lapic_set_timer_one_shot(const u32_t value)
        lvtt = APIC_TIMER_INT_VECTOR;
        lapic_write(LAPIC_LVTTR, lvtt);
 
-       lapic_write(LAPIC_TIMER_ICR, value * ticks_per_us);
+       lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us);
 }
 
 PUBLIC void lapic_set_timer_periodic(const unsigned freq)
@@ -543,13 +542,16 @@ PUBLIC void lapic_stop_timer(void)
        u32_t lvtt;
        lvtt = lapic_read(LAPIC_LVTTR);
        lapic_write(LAPIC_LVTTR, lvtt | APIC_LVTT_MASK);
+       /* zero the current counter so it can be restarted again */
+       lapic_write(LAPIC_TIMER_ICR, 0);
+       lapic_write(LAPIC_TIMER_CCR, 0);
 }
 
 PUBLIC void lapic_restart_timer(void)
 {
-       u32_t lvtt;
-       lvtt = lapic_read(LAPIC_LVTTR);
-       lapic_write(LAPIC_LVTTR, lvtt & ~APIC_LVTT_MASK);
+       /* restart the timer only if the counter reached zero, i.e. expired */
+       if (lapic_read(LAPIC_TIMER_CCR) == 0)
+               lapic_set_timer_one_shot(1000000/system_hz);
 }
 
 PUBLIC void lapic_microsec_sleep(unsigned count)
index 36c28b10d0a53f689600601df4d846d9e967f4d9..e7aae786e916be5fd241139773a82d5f681ad5b9 100644 (file)
@@ -117,7 +117,7 @@ PRIVATE void estimate_cpu_freq(void)
        BOOT_VERBOSE(cpu_print_freq(cpuid));
 }
 
-PUBLIC int arch_init_local_timer(unsigned freq)
+PUBLIC int init_local_timer(unsigned freq)
 {
 #ifdef CONFIG_APIC
        /* if we know the address, lapic is enabled and we should use it */
@@ -140,7 +140,7 @@ PUBLIC int arch_init_local_timer(unsigned freq)
        return 0;
 }
 
-PUBLIC void arch_stop_local_timer(void)
+PUBLIC void stop_local_timer(void)
 {
 #ifdef CONFIG_APIC
        if (lapic_addr) {
@@ -153,19 +153,16 @@ PUBLIC void arch_stop_local_timer(void)
        }
 }
 
-PUBLIC void arch_restart_local_timer(void)
+PUBLIC void restart_local_timer(void)
 {
 #ifdef CONFIG_APIC
        if (lapic_addr) {
                lapic_restart_timer();
-       } else
-#endif
-       {
-               init_8253A_timer(system_hz);
        }
+#endif
 }
 
-PUBLIC int arch_register_local_timer_handler(const irq_handler_t handler)
+PUBLIC int register_local_timer_handler(const irq_handler_t handler)
 {
 #ifdef CONFIG_APIC
        if (lapic_addr) {
@@ -269,7 +266,7 @@ PUBLIC void context_stop_idle(void)
        context_stop(get_cpulocal_var_ptr(idle_proc));
 
        if (is_idle)
-               arch_restart_local_timer();
+               restart_local_timer();
 }
 
 PUBLIC u64_t ms_2_cpu_time(unsigned ms)
index abde9656995801a5e08eeb5718867c8f08210d31..4f1445742e9e5c4cd0995e1e2cc2527509ccdb6b 100644 (file)
@@ -238,7 +238,6 @@ PRIVATE void ap_finish_booting(void)
                panic("FATAL : failed to initialize timer interrupts CPU %d, "
                                "cannot continue without any clock source!", cpu);
        }
-       printf("CPU %d local APIC timer is ticking\n", cpu);
 
        /* FIXME assign CPU local idle structure */
        get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc);
index e8920098b32826c61d78bc76b2803f6d9b59411f..bd0c2dc6de192b2d0f3078b4f46417923ed0bf26 100644 (file)
@@ -224,10 +224,10 @@ PRIVATE void load_update(void)
 
 PUBLIC int boot_cpu_init_timer(unsigned freq)
 {
-       if (arch_init_local_timer(freq))
+       if (init_local_timer(freq))
                return -1;
 
-       if (arch_register_local_timer_handler(
+       if (register_local_timer_handler(
                                (irq_handler_t) timer_int_handler))
                return -1;
 
@@ -236,6 +236,6 @@ PUBLIC int boot_cpu_init_timer(unsigned freq)
 
 PUBLIC int app_cpu_init_timer(unsigned freq)
 {
-       if (arch_init_local_timer(freq))
+       if (init_local_timer(freq))
                return -1;
 }
index 48f9c849388e27a05c5e867e5d13a9237ed8b6b7..10813de79614f1718213d3f1248f22b196901338 100644 (file)
@@ -9,12 +9,12 @@ _PROTOTYPE(int app_cpu_init_timer, (unsigned freq));
 
 _PROTOTYPE(int timer_int_handler, (void));
 
-_PROTOTYPE(int arch_init_local_timer, (unsigned freq));
+_PROTOTYPE(int init_local_timer, (unsigned freq));
 /* sto p the local timer ticking */
-_PROTOTYPE(void arch_stop_local_timer, (void));
+_PROTOTYPE(void stop_local_timer, (void));
 /* let the time tick again with the original settings after it was stopped */
-_PROTOTYPE(void arch_restart_local_timer, (void));
-_PROTOTYPE(int arch_register_local_timer_handler, (irq_handler_t handler));
+_PROTOTYPE(void restart_local_timer, (void));
+_PROTOTYPE(int register_local_timer_handler, (irq_handler_t handler));
 
 _PROTOTYPE( u64_t ms_2_cpu_time, (unsigned ms));
 
index 8b3de25096a06c52fadf08e4e8617f48eefcf6fa..3c049c29aa5381a6f16e43effb1524cc581e2521 100644 (file)
@@ -376,8 +376,8 @@ PUBLIC void minix_shutdown(timer_t *tp)
   if (ncpus > 1)
          smp_shutdown_aps();
 #endif
-  arch_stop_local_timer();
   hw_intr_disable_all();
+  stop_local_timer();
   intr_init(INTS_ORIG, 0);
   arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC);
 }
index afa58cd231728e8f709c051b7fc4e18117b545b4..7f36fc728bf097a9ebb4316fed164993eb26dc71 100644 (file)
@@ -191,7 +191,7 @@ PRIVATE void idle(void)
 #ifdef CONFIG_SMP
        /* we don't need to keep time on APs as it is handled on the BSP */
        if (cpuid != bsp_cpu_id)
-               arch_stop_local_timer();
+               stop_local_timer();
        get_cpulocal_var(cpu_is_idle) = 1;
 #endif
 
@@ -338,10 +338,11 @@ check_misc_flags:
        p->p_schedules++;
 #endif
 
-
        p = arch_finish_switch_to_user();
        assert(!is_zero64(p->p_cpu_time_left));
 
+       restart_local_timer();
+       
        context_stop(proc_addr(KERNEL));
 
        /* If the process isn't the owner of FPU, enable the FPU exception */
index e915c0dbbcda8a9af2655c0e47711cd056c92da9..b11e0738c7716895ff6554ab9437fa3ae087dcdf 100644 (file)
@@ -30,7 +30,7 @@ PUBLIC void ap_boot_finished(unsigned cpu)
 PUBLIC void smp_ipi_halt_handler(void)
 {
        ipi_ack();
-       arch_stop_local_timer();
+       stop_local_timer();
        arch_smp_halt_cpu();
 }