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));
}
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)

View 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)

View 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);

View 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;
}

View 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));

View 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);
}

View 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 */

View 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();
}