- Implement MI helper functions, dividing one or two timer interrupts with

arbitrary frequencies into hardclock(), statclock() and profclock() calls.
Same code with minor variations duplicated several times over the tree for
different timer drivers and architectures.
- Switch all x86 archs to new functions, simplifying the code and removing
extra logic from timer drivers. Other archs are also welcome.
This commit is contained in:
mav 2010-05-24 11:40:49 +00:00
parent 598285f6f9
commit 48198e3ddd
12 changed files with 85 additions and 108 deletions

View File

@ -1112,9 +1112,6 @@ ipi_bitmap_handler(struct trapframe frame)
if (ipi_bitmap & (1 << IPI_STATCLOCK))
statclockintr(&frame);
if (ipi_bitmap & (1 << IPI_PROFCLOCK))
profclockintr(&frame);
}
/*

View File

@ -123,8 +123,7 @@
#define IPI_PREEMPT 1
#define IPI_HARDCLOCK 2
#define IPI_STATCLOCK 3
#define IPI_PROFCLOCK 4
#define IPI_BITMAP_LAST IPI_PROFCLOCK
#define IPI_BITMAP_LAST IPI_STATCLOCK
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */

View File

@ -27,7 +27,6 @@ struct trapframe;
int hardclockintr(struct trapframe *frame);
int statclockintr(struct trapframe *frame);
int profclockintr(struct trapframe *frame);
/*
* Driver to clock driver interface.

View File

@ -1279,9 +1279,6 @@ ipi_bitmap_handler(struct trapframe frame)
if (ipi_bitmap & (1 << IPI_STATCLOCK))
statclockintr(&frame);
if (ipi_bitmap & (1 << IPI_PROFCLOCK))
profclockintr(&frame);
}
/*

View File

@ -124,8 +124,7 @@
#define IPI_PREEMPT 1
#define IPI_HARDCLOCK 2
#define IPI_STATCLOCK 3
#define IPI_PROFCLOCK 4
#define IPI_BITMAP_LAST IPI_PROFCLOCK
#define IPI_BITMAP_LAST IPI_STATCLOCK
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */
@ -152,8 +151,7 @@
#define IPI_PREEMPT 1
#define IPI_HARDCLOCK 2
#define IPI_STATCLOCK 3
#define IPI_PROFCLOCK 4
#define IPI_BITMAP_LAST IPI_PROFCLOCK
#define IPI_BITMAP_LAST IPI_STATCLOCK
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */

View File

@ -27,7 +27,6 @@ struct trapframe;
int hardclockintr(struct trapframe *frame);
int statclockintr(struct trapframe *frame);
int profclockintr(struct trapframe *frame);
/*
* Driver to clock driver interface.

View File

@ -374,6 +374,12 @@ int profprocs;
int ticks;
int psratio;
int timer1hz;
int timer2hz;
static DPCPU_DEFINE(u_int, hard_cnt);
static DPCPU_DEFINE(u_int, stat_cnt);
static DPCPU_DEFINE(u_int, prof_cnt);
/*
* Initialize clock frequencies and start both clocks running.
*/
@ -403,6 +409,52 @@ initclocks(dummy)
#endif
}
void
timer1clock(int usermode, uintfptr_t pc)
{
u_int *cnt;
cnt = DPCPU_PTR(hard_cnt);
*cnt += hz;
if (*cnt >= timer1hz) {
*cnt -= timer1hz;
if (*cnt >= timer1hz)
*cnt = 0;
if (PCPU_GET(cpuid) == 0)
hardclock(usermode, pc);
else
hardclock_cpu(usermode);
}
if (timer2hz == 0)
timer2clock(usermode, pc);
}
void
timer2clock(int usermode, uintfptr_t pc)
{
u_int *cnt;
int t2hz = timer2hz ? timer2hz : timer1hz;
cnt = DPCPU_PTR(stat_cnt);
*cnt += stathz;
if (*cnt >= t2hz) {
*cnt -= t2hz;
if (*cnt >= t2hz)
*cnt = 0;
statclock(usermode);
}
if (profprocs == 0)
return;
cnt = DPCPU_PTR(prof_cnt);
*cnt += profhz;
if (*cnt >= t2hz) {
*cnt -= t2hz;
if (*cnt >= t2hz)
*cnt = 0;
profclock(usermode, pc);
}
}
/*
* Each time the real-time timer fires, this function is called on all CPUs.
* Note that hardclock() calls hardclock_cpu() for the boot CPU, so only

View File

@ -129,10 +129,7 @@ int
hardclockintr(struct trapframe *frame)
{
if (PCPU_GET(cpuid) == 0)
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
else
hardclock_cpu(TRAPF_USERMODE(frame));
timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
return (FILTER_HANDLED);
}
@ -143,13 +140,6 @@ statclockintr(struct trapframe *frame)
return (FILTER_HANDLED);
}
int
profclockintr(struct trapframe *frame)
{
return (FILTER_HANDLED);
}
static int
clkintr(struct trapframe *frame)
{
@ -448,6 +438,7 @@ cpu_initclocks()
* timecounter to user a simpler algorithm.
*/
if (using_lapic_timer == LAPIC_CLOCK_NONE) {
timer1hz = hz;
intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
NULL, INTR_TYPE_CLK, NULL);
i8254_intsrc = intr_lookup_source(0);
@ -460,6 +451,14 @@ cpu_initclocks()
i8254_timecounter.tc_counter_mask = 0xffff;
set_i8254_freq(i8254_freq, hz);
}
if (using_lapic_timer != LAPIC_CLOCK_ALL) {
profhz = hz;
if (hz < 128)
stathz = hz;
else
stathz = hz / (hz / 128);
}
timer2hz = 0;
init_TSC_tc();
}

View File

@ -64,6 +64,8 @@ extern int stathz; /* statistics clock's frequency */
extern int profhz; /* profiling clock's frequency */
extern int profprocs; /* number of process's profiling */
extern int ticks;
extern int timer1hz; /* timer 1 frequency */
extern int timer2hz; /* timer 2 frequency */
#endif /* _KERNEL */

View File

@ -240,6 +240,8 @@ void hardclock_cpu(int usermode);
void softclock(void *);
void statclock(int usermode);
void profclock(int usermode, uintfptr_t pc);
void timer1clock(int usermode, uintfptr_t pc);
void timer2clock(int usermode, uintfptr_t pc);
void startprofclock(struct proc *);
void stopprofclock(struct proc *);

View File

@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$");
#define TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x))
int clkintr_pending;
static int pscnt = 1;
static int psdiv = 1;
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
#endif
@ -134,10 +132,7 @@ int
hardclockintr(struct trapframe *frame)
{
if (PCPU_GET(cpuid) == 0)
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
else
hardclock_cpu(TRAPF_USERMODE(frame));
timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
return (FILTER_HANDLED);
}
@ -145,19 +140,7 @@ int
statclockintr(struct trapframe *frame)
{
profclockintr(frame);
statclock(TRAPF_USERMODE(frame));
return (FILTER_HANDLED);
}
int
profclockintr(struct trapframe *frame)
{
if (!using_atrtc_timer)
hardclockintr(frame);
if (profprocs != 0)
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
timer2clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
return (FILTER_HANDLED);
}
@ -190,28 +173,11 @@ clkintr(struct trapframe *frame)
(*cyclic_clock_func[cpu])(frame);
#endif
if (using_atrtc_timer) {
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_HARDCLOCK);
if (smp_started)
ipi_all_but_self(IPI_HARDCLOCK);
#endif
hardclockintr(frame);
} else {
if (--pscnt <= 0) {
pscnt = psratio;
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_STATCLOCK);
#endif
statclockintr(frame);
} else {
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_PROFCLOCK);
#endif
profclockintr(frame);
}
}
hardclockintr(frame);
#ifdef DEV_MCA
/* Reset clock interrupt by asserting bit 7 of port 0x61 */
@ -295,20 +261,11 @@ rtcintr(struct trapframe *frame)
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
flag = 1;
if (--pscnt <= 0) {
pscnt = psdiv;
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_STATCLOCK);
if (smp_started)
ipi_all_but_self(IPI_STATCLOCK);
#endif
statclockintr(frame);
} else {
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_PROFCLOCK);
#endif
profclockintr(frame);
}
statclockintr(frame);
}
return(flag ? FILTER_HANDLED : FILTER_STRAY);
}
@ -555,6 +512,7 @@ cpu_initclocks()
* timecounter to user a simpler algorithm.
*/
if (using_lapic_timer == LAPIC_CLOCK_NONE) {
timer1hz = hz;
intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
NULL, INTR_TYPE_CLK, NULL);
i8254_intsrc = intr_lookup_source(0);
@ -577,6 +535,7 @@ cpu_initclocks()
if (using_lapic_timer != LAPIC_CLOCK_ALL) {
using_atrtc_timer = tasc;
if (using_atrtc_timer) {
timer2hz = RTC_NOPROFRATE;
/* Enable periodic interrupts from the RTC. */
intr_add_handler("rtc", 8,
(driver_filter_t *)rtcintr, NULL, NULL,
@ -588,6 +547,7 @@ cpu_initclocks()
stathz = hz;
else
stathz = hz / (hz / 128);
timer2hz = 0;
}
}
@ -601,7 +561,7 @@ cpu_startprofclock(void)
if (using_lapic_timer == LAPIC_CLOCK_ALL || !using_atrtc_timer)
return;
atrtc_rate(RTCSA_PROF);
psdiv = pscnt = psratio;
timer2hz = RTC_PROFRATE;
}
void
@ -611,7 +571,7 @@ cpu_stopprofclock(void)
if (using_lapic_timer == LAPIC_CLOCK_ALL || !using_atrtc_timer)
return;
atrtc_rate(RTCSA_NOPROF);
psdiv = pscnt = 1;
timer2hz = RTC_NOPROFRATE;
}
static int

View File

@ -118,9 +118,6 @@ struct lapic {
u_int la_cluster_id:2;
u_int la_present:1;
u_long *la_timer_count;
u_long la_hard_ticks;
u_long la_stat_ticks;
u_long la_prof_ticks;
/* Include IDT_SYSCALL to make indexing easier. */
int la_ioint_irqs[APIC_NUM_IOINTS + 1];
} static lapics[MAX_APIC_ID + 1];
@ -493,12 +490,14 @@ lapic_setup_clock(enum lapic_clock srcsdes)
} else
lapic_timer_hz = hz;
lapic_timer_period = value / lapic_timer_hz;
timer1hz = lapic_timer_hz;
if (srcsdes == LAPIC_CLOCK_ALL) {
if (lapic_timer_hz < 128)
stathz = lapic_timer_hz;
else
stathz = lapic_timer_hz / (lapic_timer_hz / 128);
profhz = lapic_timer_hz;
timer2hz = 0;
}
/*
@ -790,33 +789,7 @@ lapic_handle_timer(struct trapframe *frame)
(*cyclic_clock_func[cpu])(frame);
#endif
/* Fire hardclock at hz. */
la->la_hard_ticks += hz;
if (la->la_hard_ticks >= lapic_timer_hz) {
la->la_hard_ticks -= lapic_timer_hz;
if (PCPU_GET(cpuid) == 0)
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
else
hardclock_cpu(TRAPF_USERMODE(frame));
}
if (clockcoverage == LAPIC_CLOCK_ALL) {
/* Fire statclock at stathz. */
la->la_stat_ticks += stathz;
if (la->la_stat_ticks >= lapic_timer_hz) {
la->la_stat_ticks -= lapic_timer_hz;
statclock(TRAPF_USERMODE(frame));
}
/* Fire profclock at profhz, but only when needed. */
la->la_prof_ticks += profhz;
if (la->la_prof_ticks >= lapic_timer_hz) {
la->la_prof_ticks -= lapic_timer_hz;
if (profprocs != 0)
profclock(TRAPF_USERMODE(frame),
TRAPF_PC(frame));
}
}
timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
critical_exit();
}