git: 096c0b9b469b - stable/13 - sched_ule: Ensure we hold the thread lock when modifying td_flags

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 01 Aug 2022 14:19:16 UTC
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=096c0b9b469b9fab1a4d73d13541298af41da9c1

commit 096c0b9b469b9fab1a4d73d13541298af41da9c1
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-07-18 19:50:45 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-08-01 14:13:24 +0000

    sched_ule: Ensure we hold the thread lock when modifying td_flags
    
    The load balancer may force a running thread to reschedule and pick a
    new CPU.  To do this it sets some flags in the thread running on a
    loaded CPU.  But the code assumed that a running thread's lock is the
    same as that of the corresponding runqueue, and there are small windows
    where this is not true.  In this case, we can end up with non-atomic
    modifications to td_flags.
    
    Since this load balancing is best-effort, simply give up if the thread's
    lock doesn't match; in this case the thread is about to enter the
    scheduler anyway.
    
    Reviewed by:    kib
    Reported by:    glebius
    Fixes:          e745d729be60 ("sched_ule(4): Improve long-term load balancer.")
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit bd980ca847b76439bd27a4144cf0dd69d48b33af)
---
 sys/kern/sched_ule.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 519b8275cf7d..0a830da7e2d5 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -871,7 +871,8 @@ sched_balance_group(struct cpu_group *cg)
 			 */
 			TDQ_LOCK(tdq);
 			td = tdq->tdq_curthread;
-			if ((td->td_flags & TDF_IDLETD) == 0 &&
+			if (td->td_lock == TDQ_LOCKPTR(tdq) &&
+			    (td->td_flags & TDF_IDLETD) == 0 &&
 			    THREAD_CAN_MIGRATE(td)) {
 				td->td_flags |= TDF_NEEDRESCHED | TDF_PICKCPU;
 				if (high != curcpu)