Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f479bdc authored by Junjie Wu's avatar Junjie Wu
Browse files

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: default avatarJunjie Wu <junjiew@codeaurora.org>
parent f9fb0d29
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2459,6 +2459,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);
+31 −5
Original line number Diff line number Diff line
@@ -4095,6 +4095,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
@@ -4185,11 +4188,14 @@ out:
		atomic_notifier_call_chain(&migration_notifier_head,
					   0, (void *)&mnd);

	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)
		} else if (heavy_task) {
			check_for_freq_change(cpu_rq(cpu));
		}
	}

	return success;
}
@@ -4260,6 +4266,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);
+31 −5
Original line number Diff line number Diff line
@@ -3460,6 +3460,9 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
	struct rq *rq;
	u64 wallclock;
#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
@@ -3546,11 +3549,14 @@ out:
		atomic_notifier_call_chain(&migration_notifier_head,
					   0, (void *)&mnd);

	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)
		} else if (heavy_task) {
			check_for_freq_change(cpu_rq(cpu));
		}
	}

	return success;
}
@@ -3620,6 +3626,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);
+1 −0
Original line number Diff line number Diff line
@@ -1374,6 +1374,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
+1 −0
Original line number Diff line number Diff line
@@ -1515,6 +1515,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