History

sched/proxy: Optimize try_to_wake_up()

The reason for the clause in try_to_wake_up() is, per its comment, that find_proxy_task()'s proxy_deactivate() is not always called with a cleared p->blocked_on. However, that seems silly and easily cured. Make sure to always call proxy_deactivate() with a cleared p->blocked_on such that we might remove this clause from the common wake-up path.

Peter Zijlstra committed 5 months ago

Commit abc40cc1 parent 1628b251 file · +4 −10Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/sched/core.c+4−10
@@ -4343,14 +4343,6 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) · 4342 unmodified lines
4343 */4343 */
4344 WRITE_ONCE(p->__state, TASK_WAKING);4344 WRITE_ONCE(p->__state, TASK_WAKING);
4345 4345
4346 /*
4347 * We never clear the blocked_on relation on proxy_deactivate.
4348 * If we don't clear it here, we have TASK_RUNNING + p->blocked_on
4349 * when waking up. Since this is a fully blocked, off CPU task
4350 * waking up, it should be safe to clear the blocked_on relation.
4351 */
4352 if (task_is_blocked(p))
4353 clear_task_blocked_on(p, NULL);
4354 /*4346 /*
4355 * If the owning (remote) CPU is still in the middle of schedule() with4347 * If the owning (remote) CPU is still in the middle of schedule() with
4356 * this task as prev, considering queueing p on the remote CPUs wake_list4348 * this task as prev, considering queueing p on the remote CPUs wake_list
@@ -6739,6 +6731,7 @@ static void proxy_deactivate(struct rq *rq, struct task_struct *donor) · 2382 unmodified lines
6739 unsigned long state = READ_ONCE(donor->__state);6731 unsigned long state = READ_ONCE(donor->__state);
6740 6732
6741 WARN_ON_ONCE(state == TASK_RUNNING);6733 WARN_ON_ONCE(state == TASK_RUNNING);
6734 WARN_ON_ONCE(donor->blocked_on);
6742 /*6735 /*
6743 * Because we got donor from pick_next_task(), it is *crucial*6736 * Because we got donor from pick_next_task(), it is *crucial*
6744 * that we call proxy_resched_idle() before we deactivate it.6737 * that we call proxy_resched_idle() before we deactivate it.
@@ -6864,9 +6857,9 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 119 unmodified lines
6864 for (p = donor; (mutex = p->blocked_on); p = owner) {6857 for (p = donor; (mutex = p->blocked_on); p = owner) {
6865 /* if its PROXY_WAKING, do return migration or run if current */6858 /* if its PROXY_WAKING, do return migration or run if current */
6866 if (mutex == PROXY_WAKING) {6859 if (mutex == PROXY_WAKING) {
6860 clear_task_blocked_on(p, PROXY_WAKING);
6867 if (task_current(rq, p)) {6861 if (task_current(rq, p)) {
6868 p->is_blocked = 0;6862 p->is_blocked = 0;
6869 clear_task_blocked_on(p, PROXY_WAKING);
6870 return p;6863 return p;
6871 }6864 }
6872 goto deactivate;6865 goto deactivate;
@@ -6900,9 +6893,9 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 27 unmodified lines
6900 * and return p (if it is current and safe to6893 * and return p (if it is current and safe to
6901 * just run on this rq), or return-migrate the task.6894 * just run on this rq), or return-migrate the task.
6902 */6895 */
6896 __clear_task_blocked_on(p, NULL);
6903 if (task_current(rq, p)) {6897 if (task_current(rq, p)) {
6904 p->is_blocked = 0;6898 p->is_blocked = 0;
6905 __clear_task_blocked_on(p, NULL);
6906 return p;6899 return p;
6907 }6900 }
6908 goto deactivate;6901 goto deactivate;
@@ -6912,6 +6905,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 3 unmodified lines
6912 /* XXX Don't handle blocked owners/delayed dequeue yet */6905 /* XXX Don't handle blocked owners/delayed dequeue yet */
6913 if (curr_in_chain)6906 if (curr_in_chain)
6914 return proxy_resched_idle(rq);6907 return proxy_resched_idle(rq);
6908 __clear_task_blocked_on(p, NULL);
6915 goto deactivate;6909 goto deactivate;
6916 }6910 }
6917 6911