http://defect.opensolaris.org/bz/show_bug.cgi?id=3291
Bill Holler <bill.holler at sun.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|ACCEPTED |FIXUNDERSTOOD
--- Comment #1 from Bill Holler <bill.holler at sun.com> 2008-10-07 19:20:27
---
Idle threads can check if the LAPIC timer would have expired when
waking up from deep C-State. If so, the idle thread can raise ipl
to CBE_HIGH_PIL, sti, and directly call cyclic_fire(). cyclic_fire()
is a high level interrupt handler which cannot block, so it *should*
be safe to call from the idle thread at CBE_HIGH_PIL (the idle thread
cannot block).
libmicro benchmark showed almost no difference with this fix compared
with the older mechanism that reprograms the LAPIC Timer to cause
the cyclic_fire() interrupt ASAP. The CPU is idle in this case
this bug is attempting to improve.
There were roughly 100 less interrupts per second on a 2-socket
system with this fix. Perhaps it will help power.
bash-3.2$ hg pdiff
Enter passphrase for key '/home/bholler/.ssh/id_dsa':
Enter passphrase for key '/home/bholler/.ssh/id_dsa':
diff -r a342f0f30ded usr/src/uts/i86pc/io/hpet_acpi.c
--- a/usr/src/uts/i86pc/io/hpet_acpi.c Wed Oct 01 18:28:42 2008 -0700
+++ b/usr/src/uts/i86pc/io/hpet_acpi.c Tue Oct 07 19:07:01 2008 -0700
@@ -45,6 +45,9 @@
#include <sys/ksynch.h>
#include <sys/apic.h>
+#include <sys/systm.h>
+#include <sys/spl.h>
+#include <sys/archsystm.h>
@@ -1066,6 +1063,11 @@
* Returns B_TRUE if the HPET was programmed to interrupt by
* required_wakeup_time. B_FLASE is returned if the HPET could not be
* programmed to interrupt before the required time.
+ *
+ * We can use poke_cpu() to wake CPUs at XC_CPUPOKE_PIL instead of
CBE_HIGH_PIL.
+ * The idle CPU wakes up from the poke with interrupts blocked. The poked CPU
+ * raises IPL to CBE_HIGH_PIL before enabling interrupts, and cyclic_fire() is
+ * properly run at CBE_HIGH_PIL before any lower priority interrupts can run.
*/
static boolean_t
hpet_guaranteed_schedule(hrtime_t required_wakeup_time)
@@ -1280,35 +1282,63 @@
}
/*
- * Remove self from list of CPUs using HPET as a proxy local APIC timer.
- * Called by the idle thread with interrupts disabled.
+ * This function is called by the idle loop when returning from deep c-state
+ * before enabling interrupts.
*
- * The ISR cannot be running on a CPU who's idle thread is in this function
- * because this is always called with interrupts disabled.
- * When returning from deep c-state the idle loop calls this before enabling
- * interrupts (before the ISR can run on this CPU).
+ * Remove self from list of CPUs using HPET as a proxy Local APIC timer.
+ * This thread has work to do now; do not reprogram the HPET timer here.
+ * We use a HPET reprogramming lazy policy: let idle CPUs and the ISR
reprogram
+ * the HPET. Chances are another CPU will go idle before the ISR fires.
*
- * Always remove ourself from the list of CPUs using the HPET for proxy intr.
+ * Perform Local APIC fixup if it is not time to
*/
static void
hpet_lapic_deschedule(hrtime_t expire)
{
+ extern void cyclic_fire(cpu_t *cpu);
extern void apic_timer_restart(hrtime_t);
processorid_t cpu_id = CPU->cpu_id;
+ int idle_spl;
hpet_info.lapic_deschedule++;
- /* ASSERT(interrupts disabled); */
+ ASSERT(!interrupts_enabled());
hpet_proxy_users[cpu_id] = CY_INFINITY;
- /*
- * Do not enable a LAPIC Timer than was initially disabled.
- */
- if (expire != CY_INFINITY)
- apic_timer_restart(expire);
+ if (expire != CY_INFINITY) {
+ if (gethrtime() >= expire) {
+ /*
+ * Execute cyclic_fire() inline here. Raise IPL to
+ * CBE_HIGH_PIL before enabling interrupts to allow
+ * cyclic_fire() to run at proper priority.
+ *
+ * apic_timer_restart() does not need to be run because
+ * cyclic_fire() will properly reprogram the LAPIC
+ * counter for the next cyclic.
+ */
- sti();
+ idle_spl = getpil();
+ splx(ipltospl(hpet_proxy_ipl()));
+ sti();
+ cyclic_fire(CPU);
+ splx(idle_spl);
+ } else {
+ /*
+ * The LAPIC Timer would not yet have expire if it
+ * had kept running in Deep C-State. Reprogram
+ * the LAPIC Timer and be on our way.
+ */
+ apic_timer_restart(expire);
+ sti();
+ }
+ } else {
+ /*
+ * Do not enable a LAPIC Timer than was initially disabled.
+ */
+ sti();
+ }
}
--
Configure bugmail: http://defect.opensolaris.org/bz/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.