summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/sched/core.c18
2 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 674989708591..e23f8202c2bd 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1939,6 +1939,7 @@ extern int task_nice(const struct task_struct *p);
extern int can_nice(const struct task_struct *p, const int nice);
extern int task_curr(const struct task_struct *p);
extern int idle_cpu(int cpu);
+extern int idle_cpu_relaxed(int cpu);
extern int sched_setscheduler(struct task_struct *, int,
const struct sched_param *);
extern int sched_setscheduler_nocheck(struct task_struct *, int,
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3bfa39888f70..181767968d6c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -81,6 +81,7 @@
#include <asm/tlb.h>
#include <asm/irq_regs.h>
#include <asm/mutex.h>
+#include <asm/relaxed.h>
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#endif
@@ -3855,6 +3856,23 @@ int idle_cpu(int cpu)
return 1;
}
+int idle_cpu_relaxed(int cpu)
+{
+ struct rq *rq = cpu_rq(cpu);
+
+ if (cpu_relaxed_read_long(&rq->curr) != rq->idle)
+ return 0;
+
+ if (cpu_relaxed_read_long(&rq->nr_running))
+ return 0;
+
+#ifdef CONFIG_SMP
+ if (!llist_empty_relaxed(&rq->wake_list))
+ return 0;
+#endif
+
+ return 1;
+}
/**
* idle_task - return the idle task for a given cpu.
* @cpu: the processor in question.