summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2010-05-24 11:40:49 +0000
committermav <mav@FreeBSD.org>2010-05-24 11:40:49 +0000
commit48198e3ddd922d3260be990c8ecc8fc16f27d470 (patch)
treeba159db619ea3e7bf5e0ee0418e43865078c742f
parent598285f6f9f5354c0c6d341c1c8cd78e9981c0f5 (diff)
downloadFreeBSD-src-48198e3ddd922d3260be990c8ecc8fc16f27d470.zip
FreeBSD-src-48198e3ddd922d3260be990c8ecc8fc16f27d470.tar.gz
- 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.
-rw-r--r--sys/amd64/amd64/mp_machdep.c3
-rw-r--r--sys/amd64/include/apicvar.h3
-rw-r--r--sys/amd64/include/clock.h1
-rw-r--r--sys/i386/i386/mp_machdep.c3
-rw-r--r--sys/i386/include/apicvar.h6
-rw-r--r--sys/i386/include/clock.h1
-rw-r--r--sys/kern/kern_clock.c52
-rw-r--r--sys/pc98/cbus/clock.c21
-rw-r--r--sys/sys/kernel.h2
-rw-r--r--sys/sys/systm.h2
-rw-r--r--sys/x86/isa/clock.c66
-rw-r--r--sys/x86/x86/local_apic.c33
12 files changed, 85 insertions, 108 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index 337c028..4a44aba 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -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);
}
/*
diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h
index 91bba99..8dc04a9 100644
--- a/sys/amd64/include/apicvar.h
+++ b/sys/amd64/include/apicvar.h
@@ -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. */
diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h
index 8af699e..d2d421f 100644
--- a/sys/amd64/include/clock.h
+++ b/sys/amd64/include/clock.h
@@ -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.
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 716c25e..0dfb357 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -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);
}
/*
diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h
index bcb84a0..adfc1e8 100644
--- a/sys/i386/include/apicvar.h
+++ b/sys/i386/include/apicvar.h
@@ -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. */
diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h
index c0c55ed..7a4a081 100644
--- a/sys/i386/include/clock.h
+++ b/sys/i386/include/clock.h
@@ -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.
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index da05cc1..a35e43b 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -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
diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c
index 8c5a7d2..2f2c08c 100644
--- a/sys/pc98/cbus/clock.c
+++ b/sys/pc98/cbus/clock.c
@@ -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();
}
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index 1a9cb5c..53cf079 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -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 */
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 1d861f0..8d245a3 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -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 *);
diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c
index 36dc36e..b0d49d5 100644
--- a/sys/x86/isa/clock.c
+++ b/sys/x86/isa/clock.c
@@ -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);
-#endif
- hardclockintr(frame);
- } else {
- if (--pscnt <= 0) {
- pscnt = psratio;
#ifdef SMP
- if (smp_started)
- ipi_all_but_self(IPI_STATCLOCK);
+ if (smp_started)
+ ipi_all_but_self(IPI_HARDCLOCK);
#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);
-#endif
- statclockintr(frame);
- } else {
-#ifdef SMP
- if (smp_started)
- ipi_all_but_self(IPI_PROFCLOCK);
+ if (smp_started)
+ ipi_all_but_self(IPI_STATCLOCK);
#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
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 29b078e..f40026b 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -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();
}
OpenPOWER on IntegriCloud