[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] CPUIDLE: re-implement mwait wakeup process
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1272973708 -3600 # Node ID 121275282095711a4dc2fa4f2e84e66209d7f1b0 # Parent 57d36cd633c3d38676cbd24af363faae118a1c8b CPUIDLE: re-implement mwait wakeup process It MWAITs on a completely new flag field, avoiding the IPI-avoidance semantics of softirq_pending. It also does wakeup-waiting checks on timer_deadline_start, that being the field that initiates wakeup via the MONITORed memory region. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx> --- xen/arch/x86/acpi/cpu_idle.c | 33 +++++++++++++++++++-------------- xen/include/asm-x86/hardirq.h | 1 + xen/include/xen/irq_cpustat.h | 1 + 3 files changed, 21 insertions(+), 14 deletions(-) diff -r 57d36cd633c3 -r 121275282095 xen/arch/x86/acpi/cpu_idle.c --- a/xen/arch/x86/acpi/cpu_idle.c Tue May 04 12:46:56 2010 +0100 +++ b/xen/arch/x86/acpi/cpu_idle.c Tue May 04 12:48:28 2010 +0100 @@ -153,40 +153,45 @@ static void acpi_safe_halt(void) /* * The bit is set iff cpu use monitor/mwait to enter C state * with this flag set, CPU can be waken up from C state - * by writing to specific memory address, instead of sending IPI + * by writing to specific memory address, instead of sending an IPI. */ static cpumask_t cpuidle_mwait_flags; void cpuidle_wakeup_mwait(cpumask_t *mask) { cpumask_t target; - int cpu; + unsigned int cpu; cpus_and(target, *mask, cpuidle_mwait_flags); - /* cpu is 'mwait'ing at softirq_pending, - writing to it will wake up CPU */ + /* CPU is MWAITing on the cpuidle_mwait_wakeup flag. */ for_each_cpu_mask(cpu, target) - set_bit(TIMER_SOFTIRQ, &softirq_pending(cpu)); - - cpus_andnot(*mask, *mask, cpuidle_mwait_flags); + mwait_wakeup(cpu) = 0; + + cpus_andnot(*mask, *mask, target); } static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) { - int cpu = smp_processor_id(); - - __monitor((void *)&softirq_pending(cpu), 0, 0); - + unsigned int cpu = smp_processor_id(); + s_time_t expires = per_cpu(timer_deadline_start, cpu); + + __monitor((void *)&mwait_wakeup(cpu), 0, 0); smp_mb(); - if (!softirq_pending(cpu)) + + /* + * Timer deadline passing is the event on which we will be woken via + * cpuidle_mwait_wakeup. So check it now that the location is armed. + */ + if ( expires > NOW() || expires == 0 ) { cpu_set(cpu, cpuidle_mwait_flags); - __mwait(eax, ecx); - cpu_clear(cpu, cpuidle_mwait_flags); } + + if ( expires <= NOW() && expires > 0 ) + raise_softirq(TIMER_SOFTIRQ); } static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) diff -r 57d36cd633c3 -r 121275282095 xen/include/asm-x86/hardirq.h --- a/xen/include/asm-x86/hardirq.h Tue May 04 12:46:56 2010 +0100 +++ b/xen/include/asm-x86/hardirq.h Tue May 04 12:48:28 2010 +0100 @@ -8,6 +8,7 @@ typedef struct { unsigned long __softirq_pending; unsigned int __local_irq_count; unsigned int __nmi_count; + bool_t __mwait_wakeup; } __cacheline_aligned irq_cpustat_t; #include <xen/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ diff -r 57d36cd633c3 -r 121275282095 xen/include/xen/irq_cpustat.h --- a/xen/include/xen/irq_cpustat.h Tue May 04 12:46:56 2010 +0100 +++ b/xen/include/xen/irq_cpustat.h Tue May 04 12:48:28 2010 +0100 @@ -26,5 +26,6 @@ extern irq_cpustat_t irq_stat[]; #define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending) #define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count) #define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count) +#define mwait_wakeup(cpu) __IRQ_STAT((cpu), __mwait_wakeup) #endif /* __irq_cpustat_h */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |