summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorariff <ariff@FreeBSD.org>2009-06-09 07:26:52 +0000
committerariff <ariff@FreeBSD.org>2009-06-09 07:26:52 +0000
commitee44c932b29dceb6afcc040b341d3f2a239c2843 (patch)
tree37927ed1c49fbd469c5b2f17cebdb573dd7595cf /sys/amd64
parenta7c40ee1bb97afba57795ab74d3b377c1fc021be (diff)
downloadFreeBSD-src-ee44c932b29dceb6afcc040b341d3f2a239c2843.zip
FreeBSD-src-ee44c932b29dceb6afcc040b341d3f2a239c2843.tar.gz
When using i8254 as the only kernel timer source:
- Interpolate stat/prof clock using clkintr() in a similar fashion to local APIC timer, since statclock usually run slower. - Liberate hardclockintr() from taking the burden of handling both stat and prof clock interrupt. Instead, send IPIs within clkintr() to handle those.
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/isa/clock.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index 129350b2..a35b8fe 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/isa/clock.c
@@ -93,6 +93,9 @@ static int i8254_ticked;
static int using_atrtc_timer;
static int using_lapic_timer;
+static u_int stat_ticks = 0;
+static u_int prof_ticks = 0;
+
/* Values for timerX_state: */
#define RELEASED 0
#define RELEASE_PENDING 1
@@ -122,8 +125,6 @@ hardclockintr(struct trapframe *frame)
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
else
hardclock_cpu(TRAPF_USERMODE(frame));
- if (!using_atrtc_timer)
- statclockintr(frame);
return (FILTER_HANDLED);
}
@@ -131,8 +132,6 @@ int
statclockintr(struct trapframe *frame)
{
- if (profprocs != 0)
- profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
statclock(TRAPF_USERMODE(frame));
return (FILTER_HANDLED);
}
@@ -166,6 +165,30 @@ clkintr(struct trapframe *frame)
ipi_all_but_self(IPI_HARDCLOCK);
#endif
hardclockintr(frame);
+
+ if (!using_atrtc_timer) {
+ prof_ticks += profhz;
+ if (prof_ticks >= hz) {
+ prof_ticks -= hz;
+ if (profprocs != 0) {
+#ifdef SMP
+ if (smp_started)
+ ipi_all_but_self(IPI_PROFCLOCK);
+#endif
+ profclockintr(frame);
+ }
+ }
+ stat_ticks += stathz;
+ if (stat_ticks >= hz) {
+ stat_ticks -= hz;
+#ifdef SMP
+ if (smp_started)
+ ipi_all_but_self(IPI_STATCLOCK);
+#endif
+ statclockintr(frame);
+ }
+ }
+
return (FILTER_HANDLED);
}
@@ -500,7 +523,8 @@ cpu_initclocks()
INTR_TYPE_CLK, NULL);
atrtc_enable_intr();
} else {
- profhz = stathz = hz;
+ profhz = min(RTC_PROFRATE, hz);
+ stathz = min(RTC_NOPROFRATE, hz);
}
}
@@ -511,7 +535,7 @@ void
cpu_startprofclock(void)
{
- if (using_lapic_timer)
+ if (using_lapic_timer || !using_atrtc_clock)
return;
atrtc_rate(RTCSA_PROF);
psdiv = pscnt = psratio;
@@ -521,7 +545,7 @@ void
cpu_stopprofclock(void)
{
- if (using_lapic_timer)
+ if (using_lapic_timer || !using_atrtc_clock)
return;
atrtc_rate(RTCSA_NOPROF);
psdiv = pscnt = 1;
OpenPOWER on IntegriCloud