[PATCH 1/2] swqueue: Control if a task should be queued on swq in select_idle_sibling()

From: Gautham R. Shenoy
Date: Fri Jun 23 2023 - 01:32:03 EST


If select_idle_sibling() fails to find an idle CPU to wakeup the task
on, then update the newly defined sched_add_to_swq field in its task
struct.

Use the value in this field to later on to determine if the task
should also be queued on the shared-wakequeue of the LLC of the target
CPU.

This extends the use of shared-wakequeue to cases when the target of a
wakeup is the current CPU instead of the task's previous CPU.

Signed-off-by: Gautham R. Shenoy <gautham.shenoy@xxxxxxx>
---
include/linux/sched.h | 6 ++++++
kernel/sched/fair.c | 15 ++++++++-------
2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index b64fec55a381..38005262a7fe 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -910,6 +910,12 @@ struct task_struct {
*/
unsigned sched_remote_wakeup:1;

+ /*
+ * Bit used by select_idle_sibling() to signal enqueuing the
+ * task on a shared wakequeue when it failed find an idle CPU.
+ */
+ unsigned sched_add_to_swq:1;
+
/* Bit to tell LSMs we're in execve(): */
unsigned in_execve:1;
unsigned in_iowait:1;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e311d1c3b992..fe33f6b13299 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -215,21 +215,17 @@ static void swqueue_enqueue(struct rq *rq, struct task_struct *p, int enq_flags)
{
unsigned long flags;
struct swqueue *swqueue;
- bool task_migrated = enq_flags & ENQUEUE_MIGRATED;
- bool task_wakeup = enq_flags & ENQUEUE_WAKEUP;

/*
* Only enqueue the task in the shared wakequeue if:
*
* - SWQUEUE is enabled
- * - The task is on the wakeup path
- * - The task wasn't purposefully migrated to the current rq by
- * select_task_rq()
- * - The task isn't pinned to a specific CPU
+ * - select_idle_sibling() didn't find an idle CPU to enqueue this wakee task.
*/
- if (!task_wakeup || task_migrated || p->nr_cpus_allowed == 1)
+ if (!p->sched_add_to_swq)
return;

+ p->sched_add_to_swq = 0;
swqueue = rq_swqueue(rq);
spin_lock_irqsave(&swqueue->lock, flags);
list_add_tail(&p->swqueue_node, &swqueue->list);
@@ -7361,6 +7357,11 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
if ((unsigned)i < nr_cpumask_bits)
return i;

+ /*
+ * No idle sibling was found. Ok to queue this task on the
+ * shared wakequeue of the target.
+ */
+ p->sched_add_to_swq = 1;
return target;
}

--
2.25.1


--iIvtSLGF+N61/3UL
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="david-ego-2.patch"