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
This commit is contained in:
Tomas Hruby 2010-09-15 14:11:06 +00:00
parent e87d29171f
commit e2701da5a9
8 changed files with 26 additions and 27 deletions

View File

@ -499,7 +499,7 @@ PRIVATE void apic_calibrate_clocks(unsigned cpu)
BOOT_VERBOSE(cpu_print_freq(cpuid)); 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 */ /* sleep in micro seconds */
u32_t lvtt; 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; ticks_per_us = lapic_bus_freq[cpu] / 1000000;
/* calculate divisor and count from value */
lvtt = APIC_TDCR_1; lvtt = APIC_TDCR_1;
lapic_write(LAPIC_TIMER_DCR, lvtt); 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; lvtt = APIC_TIMER_INT_VECTOR;
lapic_write(LAPIC_LVTTR, lvtt); 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) PUBLIC void lapic_set_timer_periodic(const unsigned freq)
@ -543,13 +542,16 @@ PUBLIC void lapic_stop_timer(void)
u32_t lvtt; u32_t lvtt;
lvtt = lapic_read(LAPIC_LVTTR); lvtt = lapic_read(LAPIC_LVTTR);
lapic_write(LAPIC_LVTTR, lvtt | APIC_LVTT_MASK); 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) PUBLIC void lapic_restart_timer(void)
{ {
u32_t lvtt; /* restart the timer only if the counter reached zero, i.e. expired */
lvtt = lapic_read(LAPIC_LVTTR); if (lapic_read(LAPIC_TIMER_CCR) == 0)
lapic_write(LAPIC_LVTTR, lvtt & ~APIC_LVTT_MASK); lapic_set_timer_one_shot(1000000/system_hz);
} }
PUBLIC void lapic_microsec_sleep(unsigned count) PUBLIC void lapic_microsec_sleep(unsigned count)

View File

@ -117,7 +117,7 @@ PRIVATE void estimate_cpu_freq(void)
BOOT_VERBOSE(cpu_print_freq(cpuid)); BOOT_VERBOSE(cpu_print_freq(cpuid));
} }
PUBLIC int arch_init_local_timer(unsigned freq) PUBLIC int init_local_timer(unsigned freq)
{ {
#ifdef CONFIG_APIC #ifdef CONFIG_APIC
/* if we know the address, lapic is enabled and we should use it */ /* 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; return 0;
} }
PUBLIC void arch_stop_local_timer(void) PUBLIC void stop_local_timer(void)
{ {
#ifdef CONFIG_APIC #ifdef CONFIG_APIC
if (lapic_addr) { 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 #ifdef CONFIG_APIC
if (lapic_addr) { if (lapic_addr) {
lapic_restart_timer(); 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 #ifdef CONFIG_APIC
if (lapic_addr) { if (lapic_addr) {
@ -269,7 +266,7 @@ PUBLIC void context_stop_idle(void)
context_stop(get_cpulocal_var_ptr(idle_proc)); context_stop(get_cpulocal_var_ptr(idle_proc));
if (is_idle) if (is_idle)
arch_restart_local_timer(); restart_local_timer();
} }
PUBLIC u64_t ms_2_cpu_time(unsigned ms) PUBLIC u64_t ms_2_cpu_time(unsigned ms)

View File

@ -238,7 +238,6 @@ PRIVATE void ap_finish_booting(void)
panic("FATAL : failed to initialize timer interrupts CPU %d, " panic("FATAL : failed to initialize timer interrupts CPU %d, "
"cannot continue without any clock source!", cpu); "cannot continue without any clock source!", cpu);
} }
printf("CPU %d local APIC timer is ticking\n", cpu);
/* FIXME assign CPU local idle structure */ /* FIXME assign CPU local idle structure */
get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc); get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc);

View File

@ -224,10 +224,10 @@ PRIVATE void load_update(void)
PUBLIC int boot_cpu_init_timer(unsigned freq) PUBLIC int boot_cpu_init_timer(unsigned freq)
{ {
if (arch_init_local_timer(freq)) if (init_local_timer(freq))
return -1; return -1;
if (arch_register_local_timer_handler( if (register_local_timer_handler(
(irq_handler_t) timer_int_handler)) (irq_handler_t) timer_int_handler))
return -1; return -1;
@ -236,6 +236,6 @@ PUBLIC int boot_cpu_init_timer(unsigned freq)
PUBLIC int app_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; return -1;
} }

View File

@ -9,12 +9,12 @@ _PROTOTYPE(int app_cpu_init_timer, (unsigned freq));
_PROTOTYPE(int timer_int_handler, (void)); _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 */ /* 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 */ /* let the time tick again with the original settings after it was stopped */
_PROTOTYPE(void arch_restart_local_timer, (void)); _PROTOTYPE(void restart_local_timer, (void));
_PROTOTYPE(int arch_register_local_timer_handler, (irq_handler_t handler)); _PROTOTYPE(int register_local_timer_handler, (irq_handler_t handler));
_PROTOTYPE( u64_t ms_2_cpu_time, (unsigned ms)); _PROTOTYPE( u64_t ms_2_cpu_time, (unsigned ms));

View File

@ -376,8 +376,8 @@ PUBLIC void minix_shutdown(timer_t *tp)
if (ncpus > 1) if (ncpus > 1)
smp_shutdown_aps(); smp_shutdown_aps();
#endif #endif
arch_stop_local_timer();
hw_intr_disable_all(); hw_intr_disable_all();
stop_local_timer();
intr_init(INTS_ORIG, 0); intr_init(INTS_ORIG, 0);
arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC); arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC);
} }

View File

@ -191,7 +191,7 @@ PRIVATE void idle(void)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* we don't need to keep time on APs as it is handled on the BSP */ /* we don't need to keep time on APs as it is handled on the BSP */
if (cpuid != bsp_cpu_id) if (cpuid != bsp_cpu_id)
arch_stop_local_timer(); stop_local_timer();
get_cpulocal_var(cpu_is_idle) = 1; get_cpulocal_var(cpu_is_idle) = 1;
#endif #endif
@ -338,10 +338,11 @@ check_misc_flags:
p->p_schedules++; p->p_schedules++;
#endif #endif
p = arch_finish_switch_to_user(); p = arch_finish_switch_to_user();
assert(!is_zero64(p->p_cpu_time_left)); assert(!is_zero64(p->p_cpu_time_left));
restart_local_timer();
context_stop(proc_addr(KERNEL)); context_stop(proc_addr(KERNEL));
/* If the process isn't the owner of FPU, enable the FPU exception */ /* If the process isn't the owner of FPU, enable the FPU exception */

View File

@ -30,7 +30,7 @@ PUBLIC void ap_boot_finished(unsigned cpu)
PUBLIC void smp_ipi_halt_handler(void) PUBLIC void smp_ipi_halt_handler(void)
{ {
ipi_ack(); ipi_ack();
arch_stop_local_timer(); stop_local_timer();
arch_smp_halt_cpu(); arch_smp_halt_cpu();
} }