浏览代码

cpuidle: powerpc: no memory barrier after break from idle

A memory barrier is not required after the task wakes up,
only if we clear the polling flag before waking. The case
where we have work to do is the important one, so optimise
for it.

Reviewed-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Nicholas Piggin 8 年之前
父节点
当前提交
7ded429152
共有 2 个文件被更改,包括 18 次插入4 次删除
  1. 9 2
      drivers/cpuidle/cpuidle-powernv.c
  2. 9 2
      drivers/cpuidle/cpuidle-pseries.c

+ 9 - 2
drivers/cpuidle/cpuidle-powernv.c

@@ -59,14 +59,21 @@ static int snooze_loop(struct cpuidle_device *dev,
 	ppc64_runlatch_off();
 	ppc64_runlatch_off();
 	HMT_very_low();
 	HMT_very_low();
 	while (!need_resched()) {
 	while (!need_resched()) {
-		if (likely(snooze_timeout_en) && get_tb() > snooze_exit_time)
+		if (likely(snooze_timeout_en) && get_tb() > snooze_exit_time) {
+			/*
+			 * Task has not woken up but we are exiting the polling
+			 * loop anyway. Require a barrier after polling is
+			 * cleared to order subsequent test of need_resched().
+			 */
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+			smp_mb();
 			break;
 			break;
+		}
 	}
 	}
 
 
 	HMT_medium();
 	HMT_medium();
 	ppc64_runlatch_on();
 	ppc64_runlatch_on();
 	clear_thread_flag(TIF_POLLING_NRFLAG);
 	clear_thread_flag(TIF_POLLING_NRFLAG);
-	smp_mb();
 
 
 	return index;
 	return index;
 }
 }

+ 9 - 2
drivers/cpuidle/cpuidle-pseries.c

@@ -71,13 +71,20 @@ static int snooze_loop(struct cpuidle_device *dev,
 	while (!need_resched()) {
 	while (!need_resched()) {
 		HMT_low();
 		HMT_low();
 		HMT_very_low();
 		HMT_very_low();
-		if (snooze_timeout_en && get_tb() > snooze_exit_time)
+		if (likely(snooze_timeout_en) && get_tb() > snooze_exit_time) {
+			/*
+			 * Task has not woken up but we are exiting the polling
+			 * loop anyway. Require a barrier after polling is
+			 * cleared to order subsequent test of need_resched().
+			 */
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+			smp_mb();
 			break;
 			break;
+		}
 	}
 	}
 
 
 	HMT_medium();
 	HMT_medium();
 	clear_thread_flag(TIF_POLLING_NRFLAG);
 	clear_thread_flag(TIF_POLLING_NRFLAG);
-	smp_mb();
 
 
 	idle_loop_epilog(in_purr);
 	idle_loop_epilog(in_purr);