From: Tomas Hruby Date: Wed, 15 Sep 2010 14:11:06 +0000 (+0000) Subject: SMP - Single shot local timer X-Git-Tag: v3.2.0~845 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/Bv9ARM.ch10.html?a=commitdiff_plain;h=e2701da5a9e70d49276c15565ac6336c0cd766f8;p=minix.git SMP - Single shot local timer - 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 --- diff --git a/kernel/arch/i386/apic.c b/kernel/arch/i386/apic.c index 3a3b90ae7..53bad419c 100644 --- a/kernel/arch/i386/apic.c +++ b/kernel/arch/i386/apic.c @@ -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) diff --git a/kernel/arch/i386/arch_clock.c b/kernel/arch/i386/arch_clock.c index 36c28b10d..e7aae786e 100644 --- a/kernel/arch/i386/arch_clock.c +++ b/kernel/arch/i386/arch_clock.c @@ -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) diff --git a/kernel/arch/i386/arch_smp.c b/kernel/arch/i386/arch_smp.c index abde96569..4f1445742 100644 --- a/kernel/arch/i386/arch_smp.c +++ b/kernel/arch/i386/arch_smp.c @@ -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); diff --git a/kernel/clock.c b/kernel/clock.c index e8920098b..bd0c2dc6d 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -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; } diff --git a/kernel/clock.h b/kernel/clock.h index 48f9c8493..10813de79 100644 --- a/kernel/clock.h +++ b/kernel/clock.h @@ -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)); diff --git a/kernel/main.c b/kernel/main.c index 8b3de2509..3c049c29a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -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); } diff --git a/kernel/proc.c b/kernel/proc.c index afa58cd23..7f36fc728 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -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 */ diff --git a/kernel/smp.c b/kernel/smp.c index e915c0dbb..b11e0738c 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -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(); }