]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
sched/proxy: Yield the donor task
authorFernand Sieber <sieberf@amazon.com>
Thu, 6 Nov 2025 10:40:10 +0000 (12:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 09:16:41 +0000 (10:16 +0100)
commit 127b90315ca07ccad2618db7ba950a63e3b32d22 upstream.

When executing a task in proxy context, handle yields as if they were
requested by the donor task. This matches the traditional PI semantics
of yield() as well.

This avoids scenario like proxy task yielding, pick next task selecting the
same previous blocked donor, running the proxy task again, etc.

Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202510211205.1e0f5223-lkp@intel.com
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Fernand Sieber <sieberf@amazon.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251106104022.195157-1-sieberf@amazon.com
Cc: Holger Hoffstätte <holger@applied-asynchrony.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/sched/deadline.c
kernel/sched/ext.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/sched/syscalls.c

index 19b1a8b81c76ce5607f438924225effa1a90e351..d3be71d5a9ccc9e076e2dfb228ffd0079485a33c 100644 (file)
@@ -2143,7 +2143,7 @@ static void yield_task_dl(struct rq *rq)
         * it and the bandwidth timer will wake it up and will give it
         * new scheduling parameters (thanks to dl_yielded=1).
         */
-       rq->curr->dl.dl_yielded = 1;
+       rq->donor->dl.dl_yielded = 1;
 
        update_rq_clock(rq);
        update_curr_dl(rq);
index b959a70471c104f633cde8250be2dab15e3d5021..907eea83294ce241fe028f1072606c2d6b46d9b2 100644 (file)
@@ -1493,7 +1493,7 @@ static bool dequeue_task_scx(struct rq *rq, struct task_struct *p, int deq_flags
 static void yield_task_scx(struct rq *rq)
 {
        struct scx_sched *sch = scx_root;
-       struct task_struct *p = rq->curr;
+       struct task_struct *p = rq->donor;
 
        if (SCX_HAS_OP(sch, yield))
                SCX_CALL_OP_2TASKS_RET(sch, SCX_KF_REST, yield, rq, p, NULL);
@@ -1504,7 +1504,7 @@ static void yield_task_scx(struct rq *rq)
 static bool yield_to_task_scx(struct rq *rq, struct task_struct *to)
 {
        struct scx_sched *sch = scx_root;
-       struct task_struct *from = rq->curr;
+       struct task_struct *from = rq->donor;
 
        if (SCX_HAS_OP(sch, yield))
                return SCX_CALL_OP_2TASKS_RET(sch, SCX_KF_REST, yield, rq,
index 967ca52fb23118c2988f6924a4329532b53ca614..5c965666d1663669ab1ef925516c857aaa80fab9 100644 (file)
@@ -8993,7 +8993,7 @@ static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, struct t
  */
 static void yield_task_fair(struct rq *rq)
 {
-       struct task_struct *curr = rq->curr;
+       struct task_struct *curr = rq->donor;
        struct cfs_rq *cfs_rq = task_cfs_rq(curr);
        struct sched_entity *se = &curr->se;
 
index 7936d43337313cf25c972cd61af4920edc733b2e..fb07dcfc60a244c929089e999cb5e241ce7244ca 100644 (file)
@@ -1490,7 +1490,7 @@ static void requeue_task_rt(struct rq *rq, struct task_struct *p, int head)
 
 static void yield_task_rt(struct rq *rq)
 {
-       requeue_task_rt(rq, rq->curr, 0);
+       requeue_task_rt(rq, rq->donor, 0);
 }
 
 static int find_lowest_rq(struct task_struct *task);
index 77ae87f36e841296c13266910c34a1d9a79659de..bf360a6fbb800e01065dd080a2e2afa2fb0c4030 100644 (file)
@@ -1351,7 +1351,7 @@ static void do_sched_yield(void)
        rq = this_rq_lock_irq(&rf);
 
        schedstat_inc(rq->yld_count);
-       current->sched_class->yield_task(rq);
+       rq->donor->sched_class->yield_task(rq);
 
        preempt_disable();
        rq_unlock_irq(rq, &rf);
@@ -1420,12 +1420,13 @@ EXPORT_SYMBOL(yield);
  */
 int __sched yield_to(struct task_struct *p, bool preempt)
 {
-       struct task_struct *curr = current;
+       struct task_struct *curr;
        struct rq *rq, *p_rq;
        int yielded = 0;
 
        scoped_guard (raw_spinlock_irqsave, &p->pi_lock) {
                rq = this_rq();
+               curr = rq->donor;
 
 again:
                p_rq = task_rq(p);