Rework r193814:

While general idea of patch was good, it was not working properly due the way
it was implemented. When we are using same timer interrupt for several of
hard/prof/stat purposes we should not send several IPIs same time to other
CPUs. Sending several IPIs same time leads to terrible accounting/profiling
results due to strong synchronization effect, when the second interrupt
handler accounts processing of the first one.
Interlink timer events in a such way, that no more then one IPI is sent for
any original timer interrupt.
This commit is contained in:
Alexander Motin 2009-06-23 21:45:33 +00:00
parent 9801591468
commit 96c5d068d8
2 changed files with 65 additions and 72 deletions

View File

@ -93,9 +93,6 @@ 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
@ -132,6 +129,7 @@ int
statclockintr(struct trapframe *frame)
{
profclockintr(frame);
statclock(TRAPF_USERMODE(frame));
return (FILTER_HANDLED);
}
@ -140,7 +138,10 @@ int
profclockintr(struct trapframe *frame)
{
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
if (!using_atrtc_timer)
hardclockintr(frame);
if (profprocs != 0)
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
return (FILTER_HANDLED);
}
@ -160,32 +161,27 @@ clkintr(struct trapframe *frame)
mtx_unlock_spin(&clock_lock);
}
KASSERT(!using_lapic_timer, ("clk interrupt enabled with lapic timer"));
#ifdef SMP
if (smp_started)
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) {
if (using_atrtc_timer) {
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_PROFCLOCK);
if (smp_started)
ipi_all_but_self(IPI_HARDCLOCK);
#endif
profclockintr(frame);
}
}
stat_ticks += stathz;
if (stat_ticks >= hz) {
stat_ticks -= hz;
hardclockintr(frame);
} else {
if (--pscnt == 0) {
pscnt = psrate;
#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);
}
}
@ -266,21 +262,19 @@ rtcintr(struct trapframe *frame)
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
flag = 1;
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
#ifdef SMP
if (pscnt != psdiv && smp_started)
ipi_all_but_self(IPI_PROFCLOCK);
#endif
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
}
if (pscnt == psdiv) {
if (--pscnt == 0) {
pscnt = psdiv;
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_STATCLOCK);
#endif
statclock(TRAPF_USERMODE(frame));
statclockintr(frame);
} else {
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_PROFCLOCK);
#endif
profclockintr(frame);
}
}
return(flag ? FILTER_HANDLED : FILTER_STRAY);
@ -523,8 +517,11 @@ cpu_initclocks()
INTR_TYPE_CLK, NULL);
atrtc_enable_intr();
} else {
profhz = min(RTC_PROFRATE, hz);
stathz = min(RTC_NOPROFRATE, hz);
profhz = hz;
if (hz < 128)
stathz = hz;
else
stathz = hz / (hz / 128);
}
}

View File

@ -108,9 +108,6 @@ 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
@ -147,6 +144,7 @@ int
statclockintr(struct trapframe *frame)
{
profclockintr(frame);
statclock(TRAPF_USERMODE(frame));
return (FILTER_HANDLED);
}
@ -155,7 +153,10 @@ int
profclockintr(struct trapframe *frame)
{
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
if (!using_atrtc_timer)
hardclockintr(frame);
if (profprocs != 0)
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
return (FILTER_HANDLED);
}
@ -187,32 +188,26 @@ clkintr(struct trapframe *frame)
(*lapic_cyclic_clock_func[cpu])(frame);
#endif
if (using_atrtc_timer) {
#ifdef SMP
if (smp_started)
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);
if (smp_started)
ipi_all_but_self(IPI_HARDCLOCK);
#endif
profclockintr(frame);
}
}
stat_ticks += stathz;
if (stat_ticks >= hz) {
stat_ticks -= hz;
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);
}
}
@ -298,21 +293,19 @@ rtcintr(struct trapframe *frame)
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
flag = 1;
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
if (--pscnt == 0) {
pscnt = psdiv;
#ifdef SMP
if (pscnt != psdiv && smp_started)
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
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
}
if (pscnt == psdiv) {
#ifdef SMP
if (smp_started)
ipi_all_but_self(IPI_STATCLOCK);
#endif
statclock(TRAPF_USERMODE(frame));
profclockintr(frame);
}
}
return(flag ? FILTER_HANDLED : FILTER_STRAY);
@ -572,8 +565,11 @@ cpu_initclocks()
INTR_TYPE_CLK, NULL);
atrtc_enable_intr();
} else {
profhz = min(RTC_PROFRATE, hz);
stathz = min(RTC_NOPROFRATE, hz);
profhz = hz;
if (hz < 128)
stathz = hz;
else
stathz = hz / (hz / 128);
}
}