aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2013-09-11 06:43:13 -0400
committerIngo Molnar <mingo@kernel.org>2013-09-25 07:53:10 -0400
commitea8117478918a4734586d35ff530721b682425be (patch)
treeccbaaa51ffd91f34fc0a4f5c5dbad34452ddc354 /drivers/acpi
parent3150398626466c6cc626732f60bc901d58f40677 (diff)
sched, idle: Fix the idle polling state logic
Mike reported that commit 7d1a9417 ("x86: Use generic idle loop") regressed several workloads and caused excessive reschedule interrupts. The patch in question failed to notice that the x86 code had an inverted sense of the polling state versus the new generic code (x86: default polling, generic: default !polling). Fix the two prominent x86 mwait based idle drivers and introduce a few new generic polling helpers (fixing the wrong smp_mb__after_clear_bit usage). Also switch the idle routines to using tif_need_resched() which is an immediate TIF_NEED_RESCHED test as opposed to need_resched which will end up being slightly different. Reported-by: Mike Galbraith <bitbucket@online.de> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: lenb@kernel.org Cc: tglx@linutronix.de Link: http://lkml.kernel.org/n/tip-nc03imb0etuefmzybzj7sprf@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/processor_idle.c46
1 files changed, 10 insertions, 36 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f98dd00b51a9..c7414a545a4f 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -119,17 +119,10 @@ static struct dmi_system_id processor_power_dmi_table[] = {
119 */ 119 */
120static void acpi_safe_halt(void) 120static void acpi_safe_halt(void)
121{ 121{
122 current_thread_info()->status &= ~TS_POLLING; 122 if (!tif_need_resched()) {
123 /*
124 * TS_POLLING-cleared state must be visible before we
125 * test NEED_RESCHED:
126 */
127 smp_mb();
128 if (!need_resched()) {
129 safe_halt(); 123 safe_halt();
130 local_irq_disable(); 124 local_irq_disable();
131 } 125 }
132 current_thread_info()->status |= TS_POLLING;
133} 126}
134 127
135#ifdef ARCH_APICTIMER_STOPS_ON_C3 128#ifdef ARCH_APICTIMER_STOPS_ON_C3
@@ -737,6 +730,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
737 if (unlikely(!pr)) 730 if (unlikely(!pr))
738 return -EINVAL; 731 return -EINVAL;
739 732
733 if (cx->entry_method == ACPI_CSTATE_FFH) {
734 if (current_set_polling_and_test())
735 return -EINVAL;
736 }
737
740 lapic_timer_state_broadcast(pr, cx, 1); 738 lapic_timer_state_broadcast(pr, cx, 1);
741 acpi_idle_do_entry(cx); 739 acpi_idle_do_entry(cx);
742 740
@@ -790,18 +788,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
790 if (unlikely(!pr)) 788 if (unlikely(!pr))
791 return -EINVAL; 789 return -EINVAL;
792 790
793 if (cx->entry_method != ACPI_CSTATE_FFH) { 791 if (cx->entry_method == ACPI_CSTATE_FFH) {
794 current_thread_info()->status &= ~TS_POLLING; 792 if (current_set_polling_and_test())
795 /*
796 * TS_POLLING-cleared state must be visible before we test
797 * NEED_RESCHED:
798 */
799 smp_mb();
800
801 if (unlikely(need_resched())) {
802 current_thread_info()->status |= TS_POLLING;
803 return -EINVAL; 793 return -EINVAL;
804 }
805 } 794 }
806 795
807 /* 796 /*
@@ -819,9 +808,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
819 808
820 sched_clock_idle_wakeup_event(0); 809 sched_clock_idle_wakeup_event(0);
821 810
822 if (cx->entry_method != ACPI_CSTATE_FFH)
823 current_thread_info()->status |= TS_POLLING;
824
825 lapic_timer_state_broadcast(pr, cx, 0); 811 lapic_timer_state_broadcast(pr, cx, 0);
826 return index; 812 return index;
827} 813}
@@ -858,18 +844,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
858 } 844 }
859 } 845 }
860 846
861 if (cx->entry_method != ACPI_CSTATE_FFH) { 847 if (cx->entry_method == ACPI_CSTATE_FFH) {
862 current_thread_info()->status &= ~TS_POLLING; 848 if (current_set_polling_and_test())
863 /*
864 * TS_POLLING-cleared state must be visible before we test
865 * NEED_RESCHED:
866 */
867 smp_mb();
868
869 if (unlikely(need_resched())) {
870 current_thread_info()->status |= TS_POLLING;
871 return -EINVAL; 849 return -EINVAL;
872 }
873 } 850 }
874 851
875 acpi_unlazy_tlb(smp_processor_id()); 852 acpi_unlazy_tlb(smp_processor_id());
@@ -915,9 +892,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
915 892
916 sched_clock_idle_wakeup_event(0); 893 sched_clock_idle_wakeup_event(0);
917 894
918 if (cx->entry_method != ACPI_CSTATE_FFH)
919 current_thread_info()->status |= TS_POLLING;
920
921 lapic_timer_state_broadcast(pr, cx, 0); 895 lapic_timer_state_broadcast(pr, cx, 0);
922 return index; 896 return index;
923} 897}