@@ -5,16 +5,31 @@
*/
#include <linux/cpuidle.h>
+#include <linux/tick.h>
#include <linux/sched.h>
#include <linux/sched/idle.h>
static int __cpuidle poll_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
+ unsigned int next_timer_us, i;
+
local_irq_enable();
if (!current_set_polling_and_test()) {
- while (!need_resched())
+ while (!need_resched()){
cpu_relax();
+
+ /* Occasionally check for a new and long expected residency time. */
+ if (!(i++ % 1024)) {
+ local_irq_disable();
+ next_timer_us = ktime_to_us(tick_nohz_get_sleep_length());
+ local_irq_enable();
+ /* need a better way to get threshold, including large margin */
+ /* We are only trying to catch really bad cases here. */
+ if (next_timer_us > 100)
+ break;
+ }
+ }
}
current_clr_polling();