Skip to content

Commit b40b02a

Browse files
terminusKernel Patches Daemon
authored andcommitted
cpuidle/poll_state: Poll via smp_cond_load_relaxed_timeout()
The inner loop in poll_idle() polls over the thread_info flags, waiting to see if the thread has TIF_NEED_RESCHED set. The loop exits once the condition is met, or if the poll time limit has been exceeded. To minimize the number of instructions executed in each iteration, the time check is done only intermittently (once every POLL_IDLE_RELAX_COUNT iterations). In addition, each loop iteration executes cpu_relax() which on certain platforms provides a hint to the pipeline that the loop busy-waits, allowing the processor to reduce power consumption. This is close to what smp_cond_load_relaxed_timeout() provides. So, restructure the loop and fold the loop condition and the timeout check in smp_cond_load_relaxed_timeout(). Cc: "Rafael J. Wysocki" <[email protected]> Cc: Daniel Lezcano <[email protected]> Signed-off-by: Ankur Arora <[email protected]>
1 parent 1952a07 commit b40b02a

File tree

1 file changed

+8
-21
lines changed

1 file changed

+8
-21
lines changed

drivers/cpuidle/poll_state.c

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,22 @@
88
#include <linux/sched/clock.h>
99
#include <linux/sched/idle.h>
1010

11-
#define POLL_IDLE_RELAX_COUNT 200
12-
1311
static int __cpuidle poll_idle(struct cpuidle_device *dev,
1412
struct cpuidle_driver *drv, int index)
1513
{
16-
u64 time_start;
17-
18-
time_start = local_clock_noinstr();
14+
u64 time_end;
15+
u32 flags = 0;
1916

2017
dev->poll_time_limit = false;
2118

19+
time_end = local_clock_noinstr() + cpuidle_poll_time(drv, dev);
20+
2221
raw_local_irq_enable();
2322
if (!current_set_polling_and_test()) {
24-
unsigned int loop_count = 0;
25-
u64 limit;
26-
27-
limit = cpuidle_poll_time(drv, dev);
28-
29-
while (!need_resched()) {
30-
cpu_relax();
31-
if (loop_count++ < POLL_IDLE_RELAX_COUNT)
32-
continue;
33-
34-
loop_count = 0;
35-
if (local_clock_noinstr() - time_start > limit) {
36-
dev->poll_time_limit = true;
37-
break;
38-
}
39-
}
23+
flags = smp_cond_load_relaxed_timeout(&current_thread_info()->flags,
24+
(VAL & _TIF_NEED_RESCHED),
25+
(local_clock_noinstr() >= time_end));
26+
dev->poll_time_limit = !(flags & _TIF_NEED_RESCHED);
4027
}
4128
raw_local_irq_disable();
4229

0 commit comments

Comments
 (0)