sched: Provide a wake up API without sending freq notifications
authorJunjie Wu <junjiew@codeaurora.org>
Tue, 5 Jan 2016 18:53:30 +0000 (10:53 -0800)
committerDanny Wood <danwood76@gmail.com>
Mon, 8 Apr 2019 09:20:45 +0000 (10:20 +0100)
Each time a task wakes up, scheduler evaluates its load and notifies
governor if the resulting frequency of destination CPU is larger than
a threshold. However, some governor wakes up a separate task that
handles frequency change, which again calls wake_up_process().

This is dangerous because if the task being woken up meets the
threshold and ends up being moved around, there is a potential for
endless recursive notifications.

Introduce a new API for waking up a task without triggering
frequency notification.

Change-Id: I24261af81b7dc410c7fb01eaa90920b8d66fbd2a
Signed-off-by: Junjie Wu <junjiew@codeaurora.org>
include/linux/sched.h
kernel/sched/core.c
kernel/sched/sched.h

index 0a2e678c1f0dc3834fd51356a0c8850a4ddbfcdf..ab8fa8243bf9319243c8451e77128a6dc5aa70e5 100644 (file)
@@ -2059,6 +2059,7 @@ extern void xtime_update(unsigned long ticks);
 
 extern int wake_up_state(struct task_struct *tsk, unsigned int state);
 extern int wake_up_process(struct task_struct *tsk);
+extern int wake_up_process_no_notif(struct task_struct *tsk);
 extern void wake_up_new_task(struct task_struct *tsk);
 #ifdef CONFIG_SMP
  extern void kick_process(struct task_struct *tsk);
index 37b3b4a951cd0557214da5aa14c49252729bf7ff..165d563e565e463a5b445b2101de425a81ce06dc 100644 (file)
@@ -1676,6 +1676,26 @@ int wake_up_process(struct task_struct *p)
 }
 EXPORT_SYMBOL(wake_up_process);
 
+/**
+ * wake_up_process_no_notif - Wake up a specific process without notifying
+ * governor
+ * @p: The process to be woken up.
+ *
+ * Attempt to wake up the nominated process and move it to the set of runnable
+ * processes.
+ *
+ * Return: 1 if the process was woken up, 0 if it was already running.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+int wake_up_process_no_notif(struct task_struct *p)
+{
+       WARN_ON(task_is_stopped_or_traced(p));
+       return try_to_wake_up(p, TASK_NORMAL, WF_NO_NOTIFIER);
+}
+EXPORT_SYMBOL(wake_up_process_no_notif);
+
 int wake_up_state(struct task_struct *p, unsigned int state)
 {
        return try_to_wake_up(p, state, 0);
index 5f64c976ec0277ef24a5f57c8f8ad1b572bd250b..c6135f519e26175cb353146045e50f8da1809b3c 100644 (file)
@@ -892,6 +892,7 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 #define WF_SYNC                0x01            /* waker goes to sleep after wakeup */
 #define WF_FORK                0x02            /* child wakeup after fork */
 #define WF_MIGRATED    0x4             /* internal use, task got migrated */
+#define WF_NO_NOTIFIER 0x08            /* do not notify governor */
 
 static inline void update_load_add(struct load_weight *lw, unsigned long inc)
 {