SMP - Only a single APIC timer handler
- bsp_timer_int_handler() and ap_timer_int_handler() unified into timer_int_handler() - global realtime updated only on BSP
This commit is contained in:
parent
85cca7096f
commit
b7aed08e65
@ -484,6 +484,7 @@ PRIVATE void apic_calibrate_clocks(unsigned cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
intr_disable();
|
intr_disable();
|
||||||
|
BKL_LOCK();
|
||||||
|
|
||||||
/* remove the probe */
|
/* remove the probe */
|
||||||
rm_irq_handler(&calib_clk);
|
rm_irq_handler(&calib_clk);
|
||||||
@ -613,6 +614,8 @@ PRIVATE int lapic_enable_in_msr(void)
|
|||||||
|
|
||||||
ia32_msr_read(IA32_APIC_BASE, &msr.hi, &msr.lo);
|
ia32_msr_read(IA32_APIC_BASE, &msr.hi, &msr.lo);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*FIXME this is a problem on AP */
|
||||||
/*
|
/*
|
||||||
* FIXME if the location is different (unlikely) then the one we expect,
|
* FIXME if the location is different (unlikely) then the one we expect,
|
||||||
* update it
|
* update it
|
||||||
@ -625,6 +628,7 @@ PRIVATE int lapic_enable_in_msr(void)
|
|||||||
}
|
}
|
||||||
lapic_addr = phys2vir(msr.lo & ~((1 << 12) - 1));
|
lapic_addr = phys2vir(msr.lo & ~((1 << 12) - 1));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
msr.lo |= (1 << IA32_APIC_BASE_ENABLE_BIT);
|
msr.lo |= (1 << IA32_APIC_BASE_ENABLE_BIT);
|
||||||
ia32_msr_write(IA32_APIC_BASE, msr.hi, msr.lo);
|
ia32_msr_write(IA32_APIC_BASE, msr.hi, msr.lo);
|
||||||
@ -825,7 +829,6 @@ PUBLIC void apic_idt_init(const int reset)
|
|||||||
|
|
||||||
/* Set up idt tables for smp mode.
|
/* Set up idt tables for smp mode.
|
||||||
*/
|
*/
|
||||||
vir_bytes local_timer_intr_handler;
|
|
||||||
int is_bsp = is_boot_apic(apicid());
|
int is_bsp = is_boot_apic(apicid());
|
||||||
|
|
||||||
if (reset) {
|
if (reset) {
|
||||||
@ -861,16 +864,12 @@ PUBLIC void apic_idt_init(const int reset)
|
|||||||
|
|
||||||
/* configure the timer interupt handler */
|
/* configure the timer interupt handler */
|
||||||
if (is_bsp) {
|
if (is_bsp) {
|
||||||
local_timer_intr_handler = (vir_bytes) lapic_bsp_timer_int_handler;
|
BOOT_VERBOSE(printf("Initiating APIC timer handler\n"));
|
||||||
BOOT_VERBOSE(printf("Initiating BSP timer handler\n"));
|
/* register the timer interrupt handler for this CPU */
|
||||||
} else {
|
int_gate(APIC_TIMER_INT_VECTOR, (vir_bytes) lapic_timer_int_handler,
|
||||||
local_timer_intr_handler = (vir_bytes) lapic_ap_timer_int_handler;
|
PRESENT | INT_GATE_TYPE | (INTR_PRIVILEGE << DPL_SHIFT));
|
||||||
BOOT_VERBOSE(printf("Initiating AP timer handler\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register the timer interrupt handler for this CPU */
|
|
||||||
int_gate(APIC_TIMER_INT_VECTOR, (vir_bytes) local_timer_intr_handler,
|
|
||||||
PRESENT | INT_GATE_TYPE | (INTR_PRIVILEGE << DPL_SHIFT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE int acpi_get_ioapics(struct io_apic * ioa, unsigned * nioa, unsigned max)
|
PRIVATE int acpi_get_ioapics(struct io_apic * ioa, unsigned * nioa, unsigned max)
|
||||||
|
@ -64,11 +64,8 @@ ENTRY(apic_hwint##irq) \
|
|||||||
iret ;
|
iret ;
|
||||||
|
|
||||||
/* apic timer tick handlers */
|
/* apic timer tick handlers */
|
||||||
ENTRY(lapic_bsp_timer_int_handler)
|
ENTRY(lapic_timer_int_handler)
|
||||||
lapic_intr(_C_LABEL(bsp_timer_int_handler))
|
lapic_intr(_C_LABEL(timer_int_handler))
|
||||||
|
|
||||||
ENTRY(lapic_ap_timer_int_handler)
|
|
||||||
lapic_intr(_C_LABEL(ap_timer_int_handler))
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#include "arch_smp.h"
|
#include "arch_smp.h"
|
||||||
|
@ -71,8 +71,7 @@ _PROTOTYPE( void apic_hwint62, (void) );
|
|||||||
_PROTOTYPE( void apic_hwint63, (void) );
|
_PROTOTYPE( void apic_hwint63, (void) );
|
||||||
|
|
||||||
/* The local APIC timer tick handlers */
|
/* The local APIC timer tick handlers */
|
||||||
_PROTOTYPE(void lapic_bsp_timer_int_handler, (void));
|
_PROTOTYPE(void lapic_timer_int_handler, (void));
|
||||||
_PROTOTYPE(void lapic_ap_timer_int_handler, (void));
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef __CLOCK_X86_H__
|
#ifndef __CLOCK_X86_H__
|
||||||
#define __CLOCK_X86_H__
|
#define __CLOCK_X86_H__
|
||||||
|
|
||||||
|
#include "../apic_asm.h"
|
||||||
|
|
||||||
_PROTOTYPE(int init_8253A_timer, (unsigned freq));
|
_PROTOTYPE(int init_8253A_timer, (unsigned freq));
|
||||||
_PROTOTYPE(void stop_8253A_timer, (void));
|
_PROTOTYPE(void stop_8253A_timer, (void));
|
||||||
|
|
||||||
|
182
kernel/clock.c
182
kernel/clock.c
@ -35,7 +35,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_WATCHDOG
|
#ifdef CONFIG_WATCHDOG
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
@ -63,30 +62,87 @@ PRIVATE clock_t realtime = 0; /* real time clock */
|
|||||||
* The boot processos timer interrupt handler. In addition to non-boot cpus it
|
* The boot processos timer interrupt handler. In addition to non-boot cpus it
|
||||||
* keeps real time and notifies the clock task if need be
|
* keeps real time and notifies the clock task if need be
|
||||||
*/
|
*/
|
||||||
extern unsigned ooq_msg;
|
PUBLIC int timer_int_handler(void)
|
||||||
PUBLIC int bsp_timer_int_handler(void)
|
|
||||||
{
|
{
|
||||||
unsigned ticks;
|
/* Update user and system accounting times. Charge the current process
|
||||||
|
* for user time. If the current process is not billable, that is, if a
|
||||||
|
* non-user process is running, charge the billable process for system
|
||||||
|
* time as well. Thus the unbillable process' user time is the billable
|
||||||
|
* user's system time.
|
||||||
|
*/
|
||||||
|
|
||||||
if(minix_panicing)
|
struct proc * p, * billp;
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Get number of ticks and update realtime. */
|
/* FIXME watchdog for slave cpus! */
|
||||||
ticks = lost_ticks + 1;
|
#ifdef CONFIG_WATCHDOG
|
||||||
lost_ticks = 0;
|
/*
|
||||||
realtime += ticks;
|
* we need to know whether local timer ticks are happening or whether
|
||||||
|
* the kernel is locked up. We don't care about overflows as we only
|
||||||
|
* need to know that it's still ticking or not
|
||||||
|
*/
|
||||||
|
watchdog_local_timer_ticks++;
|
||||||
|
#endif
|
||||||
|
|
||||||
ap_timer_int_handler();
|
if (cpu_is_bsp(cpuid))
|
||||||
|
realtime++;
|
||||||
|
|
||||||
/* if a timer expired, notify the clock task */
|
/* Update user and system accounting times. Charge the current process
|
||||||
if ((next_timeout <= realtime)) {
|
* for user time. If the current process is not billable, that is, if a
|
||||||
tmrs_exptimers(&clock_timers, realtime, NULL);
|
* non-user process is running, charge the billable process for system
|
||||||
next_timeout = (clock_timers == NULL) ?
|
* time as well. Thus the unbillable process' user time is the billable
|
||||||
TMR_NEVER : clock_timers->tmr_exp_time;
|
* user's system time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
p = get_cpulocal_var(proc_ptr);
|
||||||
|
billp = get_cpulocal_var(bill_ptr);
|
||||||
|
|
||||||
|
p->p_user_time++;
|
||||||
|
|
||||||
|
if (! (priv(p)->s_flags & BILLABLE)) {
|
||||||
|
billp->p_sys_time++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_serial_debug)
|
/* Decrement virtual timers, if applicable. We decrement both the
|
||||||
do_ser_debug();
|
* virtual and the profile timer of the current process, and if the
|
||||||
|
* current process is not billable, the timer of the billed process as
|
||||||
|
* well. If any of the timers expire, do_clocktick() will send out
|
||||||
|
* signals.
|
||||||
|
*/
|
||||||
|
if ((p->p_misc_flags & MF_VIRT_TIMER)){
|
||||||
|
p->p_virt_left--;
|
||||||
|
}
|
||||||
|
if ((p->p_misc_flags & MF_PROF_TIMER)){
|
||||||
|
p->p_prof_left--;
|
||||||
|
}
|
||||||
|
if (! (priv(p)->s_flags & BILLABLE) &&
|
||||||
|
(billp->p_misc_flags & MF_PROF_TIMER)){
|
||||||
|
billp->p_prof_left--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a process-virtual timer expired. Check current process, but
|
||||||
|
* also bill_ptr - one process's user time is another's system time, and
|
||||||
|
* the profile timer decreases for both!
|
||||||
|
*/
|
||||||
|
vtimer_check(p);
|
||||||
|
|
||||||
|
if (p != billp)
|
||||||
|
vtimer_check(billp);
|
||||||
|
|
||||||
|
/* Update load average. */
|
||||||
|
load_update();
|
||||||
|
|
||||||
|
if (cpu_is_bsp(cpuid)) {
|
||||||
|
/* if a timer expired, notify the clock task */
|
||||||
|
if ((next_timeout <= realtime)) {
|
||||||
|
tmrs_exptimers(&clock_timers, realtime, NULL);
|
||||||
|
next_timeout = (clock_timers == NULL) ?
|
||||||
|
TMR_NEVER : clock_timers->tmr_exp_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_serial_debug)
|
||||||
|
do_ser_debug();
|
||||||
|
}
|
||||||
|
|
||||||
return(1); /* reenable interrupts */
|
return(1); /* reenable interrupts */
|
||||||
}
|
}
|
||||||
@ -152,9 +208,11 @@ PRIVATE void load_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cumulation. How many processes are ready now? */
|
/* Cumulation. How many processes are ready now? */
|
||||||
for(q = 0; q < NR_SCHED_QUEUES; q++)
|
for(q = 0; q < NR_SCHED_QUEUES; q++) {
|
||||||
for(p = rdy_head[q]; p; p = p->p_nextready)
|
for(p = rdy_head[q]; p != NULL; p = p->p_nextready) {
|
||||||
enqueued++;
|
enqueued++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kloadinfo.proc_load_history[slot] += enqueued;
|
kloadinfo.proc_load_history[slot] += enqueued;
|
||||||
|
|
||||||
@ -162,90 +220,20 @@ PRIVATE void load_update(void)
|
|||||||
kloadinfo.last_clock = realtime;
|
kloadinfo.last_clock = realtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Timer interupt handler. This is the only thing executed on non boot
|
|
||||||
* processors. It is called by bsp_timer_int_handler() on the boot processor
|
|
||||||
*/
|
|
||||||
PUBLIC int ap_timer_int_handler(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Update user and system accounting times. Charge the current process
|
|
||||||
* for user time. If the current process is not billable, that is, if a
|
|
||||||
* non-user process is running, charge the billable process for system
|
|
||||||
* time as well. Thus the unbillable process' user time is the billable
|
|
||||||
* user's system time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const unsigned ticks = 1;
|
|
||||||
struct proc * p, * billp;
|
|
||||||
|
|
||||||
#ifdef CONFIG_WATCHDOG
|
|
||||||
/*
|
|
||||||
* we need to know whether local timer ticks are happening or whether
|
|
||||||
* the kernel is locked up. We don't care about overflows as we only
|
|
||||||
* need to know that it's still ticking or not
|
|
||||||
*/
|
|
||||||
watchdog_local_timer_ticks++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Update user and system accounting times. Charge the current process
|
|
||||||
* for user time. If the current process is not billable, that is, if a
|
|
||||||
* non-user process is running, charge the billable process for system
|
|
||||||
* time as well. Thus the unbillable process' user time is the billable
|
|
||||||
* user's system time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
p = get_cpulocal_var(proc_ptr);
|
|
||||||
billp = get_cpulocal_var(bill_ptr);
|
|
||||||
|
|
||||||
p->p_user_time += ticks;
|
|
||||||
|
|
||||||
/* FIXME make this ms too */
|
|
||||||
if (! (priv(p)->s_flags & BILLABLE)) {
|
|
||||||
billp->p_sys_time += ticks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrement virtual timers, if applicable. We decrement both the
|
|
||||||
* virtual and the profile timer of the current process, and if the
|
|
||||||
* current process is not billable, the timer of the billed process as
|
|
||||||
* well. If any of the timers expire, do_clocktick() will send out
|
|
||||||
* signals.
|
|
||||||
*/
|
|
||||||
if ((p->p_misc_flags & MF_VIRT_TIMER)){
|
|
||||||
p->p_virt_left -= ticks;
|
|
||||||
}
|
|
||||||
if ((p->p_misc_flags & MF_PROF_TIMER)){
|
|
||||||
p->p_prof_left -= ticks;
|
|
||||||
}
|
|
||||||
if (! (priv(p)->s_flags & BILLABLE) &&
|
|
||||||
(billp->p_misc_flags & MF_PROF_TIMER)){
|
|
||||||
billp->p_prof_left -= ticks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if a process-virtual timer expired. Check current process, but
|
|
||||||
* also bill_ptr - one process's user time is another's system time, and
|
|
||||||
* the profile timer decreases for both!
|
|
||||||
*/
|
|
||||||
vtimer_check(p);
|
|
||||||
|
|
||||||
if (p != billp)
|
|
||||||
vtimer_check(billp);
|
|
||||||
|
|
||||||
/* Update load average. */
|
|
||||||
load_update();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PUBLIC int boot_cpu_init_timer(unsigned freq)
|
PUBLIC int boot_cpu_init_timer(unsigned freq)
|
||||||
{
|
{
|
||||||
if (arch_init_local_timer(freq))
|
if (arch_init_local_timer(freq))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (arch_register_local_timer_handler(
|
if (arch_register_local_timer_handler(
|
||||||
(irq_handler_t) bsp_timer_int_handler))
|
(irq_handler_t) timer_int_handler))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUBLIC int app_cpu_init_timer(unsigned freq)
|
||||||
|
{
|
||||||
|
if (arch_init_local_timer(freq))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#include "arch_clock.h"
|
#include "arch_clock.h"
|
||||||
|
|
||||||
_PROTOTYPE(int boot_cpu_init_timer, (unsigned freq));
|
_PROTOTYPE(int boot_cpu_init_timer, (unsigned freq));
|
||||||
|
_PROTOTYPE(int app_cpu_init_timer, (unsigned freq));
|
||||||
|
|
||||||
_PROTOTYPE(int bsp_timer_int_handler, (void));
|
_PROTOTYPE(int timer_int_handler, (void));
|
||||||
_PROTOTYPE(int ap_timer_int_handler, (void));
|
|
||||||
|
|
||||||
_PROTOTYPE(int arch_init_local_timer, (unsigned freq));
|
_PROTOTYPE(int arch_init_local_timer, (unsigned freq));
|
||||||
_PROTOTYPE(void arch_stop_local_timer, (void));
|
_PROTOTYPE(void arch_stop_local_timer, (void));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user