sched: Provide a wake up API without sending freq notifications
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>
This commit is contained in:
parent
71a8c392b7
commit
efa673322f
3 changed files with 33 additions and 5 deletions
|
@ -2596,6 +2596,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);
|
||||
|
|
|
@ -4360,6 +4360,9 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
|
|||
u64 wallclock;
|
||||
struct related_thread_group *grp = NULL;
|
||||
#endif
|
||||
bool freq_notif_allowed = !(wake_flags & WF_NO_NOTIFIER);
|
||||
|
||||
wake_flags &= ~WF_NO_NOTIFIER;
|
||||
|
||||
/*
|
||||
* If we are going to wake up a thread waiting for CONDITION we
|
||||
|
@ -4477,11 +4480,14 @@ out:
|
|||
atomic_notifier_call_chain(&migration_notifier_head,
|
||||
0, (void *)&mnd);
|
||||
|
||||
if (!same_freq_domain(src_cpu, cpu)) {
|
||||
check_for_freq_change(cpu_rq(cpu));
|
||||
check_for_freq_change(cpu_rq(src_cpu));
|
||||
} else if (heavy_task)
|
||||
check_for_freq_change(cpu_rq(cpu));
|
||||
if (freq_notif_allowed) {
|
||||
if (!same_freq_domain(src_cpu, cpu)) {
|
||||
check_for_freq_change(cpu_rq(cpu));
|
||||
check_for_freq_change(cpu_rq(src_cpu));
|
||||
} else if (heavy_task) {
|
||||
check_for_freq_change(cpu_rq(cpu));
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -4561,6 +4567,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);
|
||||
|
|
|
@ -1596,6 +1596,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 */
|
||||
|
||||
/*
|
||||
* To aid in avoiding the subversion of "niceness" due to uneven distribution
|
||||
|
|
Loading…
Add table
Reference in a new issue