From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from shelob.surriel.com (shelob.surriel.com [96.67.55.147]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46304314A60 for ; Thu, 11 Jun 2026 02:14:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.67.55.147 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781144097; cv=none; b=lzI6OjD51Yvz4NY/VuPFKuQFocSoCGyfgvSCV82CvGx3qDyjcqT3fAGRghmq3tukyvJSvp09yH/CoYyRFQYUXLt0UOHf0NdMj8GTi8Q1JFKPoQQ6W0rzbVZF6uQqIWCFqyF6Zf5E5nxAMIbSMOfbqN5Ige2Zzc1jOu86D4l9Uow= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781144097; c=relaxed/simple; bh=QA0Afkdh0HOL6gFKxUoKkLZzY8ZwBlYbjjru8bKiW/M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eXgpOhZ9x5MOwA0B2T/5U2a9o8Eebtc59qoPgIojRgfLZ8nYlJcK1xT5CxoBfiBJKyDQ9jnZaJT0e0XixCMjBUrgMAxehuZdlpr4KZ07YAAWQJG/BM5E4jueBf6HFc46PQ5uzzPyR4t/K36napdMWSC+cGvMQuCd11oOHbbZLrk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=surriel.com; spf=pass smtp.mailfrom=surriel.com; dkim=pass (2048-bit key) header.d=surriel.com header.i=@surriel.com header.b=RV4KgsFl; arc=none smtp.client-ip=96.67.55.147 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=surriel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=surriel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=surriel.com header.i=@surriel.com header.b="RV4KgsFl" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=surriel.com ; s=mail; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=oX8CpqmRqN+FDdmLkVkPTSNqUIxBDg3ts6pC04eCpkQ=; b=RV4KgsFlEeifn1UM4QFXiE5oX1 CQoWTNN5JNulQLhjup7qcq6v5LTkK+me1TwVAH9ZkzILa/D8RgZKjelH1yq/1b7OWIwpnkPvcyjmY pf+cmmislOmMKcvN97cfDDN+1Zepfj1+iZ8mzg1zcCYlonGEwcABs3jRv1qEw+njZNL0hQst1w1YI 5jAt+w9CghYRAlDtDBeHsYGuF9zyTUZtKM1Kjk3epQ0Ssj0FUKh12BU3K8TrjC7S9Gjlph+Im9Jfy eyjMB27qStRozpyfChrFmQ8216xr2Na6lH4Jq0721j/i+jq5vb+wcuQxg21C+h989TeWLz3Rf8fo1 DJ/HVNrw==; Received: from fangorn.home.surriel.com ([10.0.13.7]) by shelob.surriel.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.97.1) (envelope-from ) id 1wXUwJ-000000003Zo-0Gf6; Wed, 10 Jun 2026 22:14:39 -0400 From: Rik van Riel To: linux-kernel@vger.kernel.org Cc: kernel-team@meta.com, mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, vschneid@redhat.com, Rik van Riel Subject: [PATCH 2/9] sched/core: defer WARN console output under rq->lock Date: Wed, 10 Jun 2026 22:14:09 -0400 Message-ID: <20260611021416.910555-3-riel@surriel.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260611021416.910555-1-riel@surriel.com> References: <20260611021416.910555-1-riel@surriel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Convert the WARN*() calls that run under rq->lock or ->pi_lock to the SCHED_WARN*() variants, so their console output is deferred to irq_work instead of being emitted synchronously (which can deadlock via console_unlock() -> up(&console_sem) -> try_to_wake_up() while the lock is held). This should prevent a deadlock if these warnings fire with a legacy or boot console configured. Signed-off-by: Rik van Riel Assisted-by: Claude:claude-opus-4-8 --- kernel/sched/core.c | 68 ++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2f4530eb543f..d83ee1fcdd5e 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -868,7 +868,7 @@ void update_rq_clock(struct rq *rq) return; if (sched_feat(WARN_DOUBLE_CLOCK)) - WARN_ON_ONCE(rq->clock_update_flags & RQCF_UPDATED); + SCHED_WARN_ON_ONCE(rq->clock_update_flags & RQCF_UPDATED); rq->clock_update_flags |= RQCF_UPDATED; clock = sched_clock_cpu(cpu_of(rq)); @@ -1826,7 +1826,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p, bucket = &uc_rq->bucket[uc_se->bucket_id]; - WARN_ON_ONCE(!bucket->tasks); + SCHED_WARN_ON_ONCE(!bucket->tasks); if (likely(bucket->tasks)) bucket->tasks--; @@ -1846,7 +1846,7 @@ static inline void uclamp_rq_dec_id(struct rq *rq, struct task_struct *p, * Defensive programming: this should never happen. If it happens, * e.g. due to future modification, warn and fix up the expected value. */ - WARN_ON_ONCE(bucket->value > rq_clamp); + SCHED_WARN_ON_ONCE(bucket->value > rq_clamp); if (bucket->value >= rq_clamp) { bkt_clamp = uclamp_rq_max_value(rq, clamp_id, uc_se->value); uclamp_rq_set(rq, clamp_id, bkt_clamp); @@ -2229,7 +2229,7 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags) void deactivate_task(struct rq *rq, struct task_struct *p, int flags) { - WARN_ON_ONCE(flags & DEQUEUE_SLEEP); + SCHED_WARN_ON_ONCE(flags & DEQUEUE_SLEEP); WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING); ASSERT_EXCLUSIVE_WRITER(p->on_rq); @@ -2556,7 +2556,7 @@ static struct rq *move_queued_task(struct rq *rq, struct rq_flags *rf, rq = cpu_rq(new_cpu); rq_lock(rq, rf); - WARN_ON_ONCE(task_cpu(p) != new_cpu); + SCHED_WARN_ON_ONCE(task_cpu(p) != new_cpu); activate_task(rq, p, 0); wakeup_preempt(rq, p, 0); @@ -2642,7 +2642,7 @@ static int migration_cpu_stop(void *data) * If we were passed a pending, then ->stop_pending was set, thus * p->migration_pending must have remained stable. */ - WARN_ON_ONCE(pending && pending != p->migration_pending); + SCHED_WARN_ON_ONCE(pending && pending != p->migration_pending); /* * If task_rq(p) != rq, it cannot be migrated here, because we're @@ -2701,7 +2701,7 @@ static int migration_cpu_stop(void *data) * determine is_migration_disabled() and so have to chase after * it. */ - WARN_ON_ONCE(!pending->stop_pending); + SCHED_WARN_ON_ONCE(!pending->stop_pending); preempt_disable(); rq_unlock(rq, &rf); raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags); @@ -3044,7 +3044,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag * * Either way, we really should have a @pending here. */ - if (WARN_ON_ONCE(!pending)) { + if (SCHED_WARN_ON_ONCE(!pending)) { task_rq_unlock(rq, p, rf); return -EINVAL; } @@ -3101,7 +3101,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag wait_var_event(&my_pending.refs, !refcount_read(&my_pending.refs)); /* ARGH */ - WARN_ON_ONCE(my_pending.stop_pending); + SCHED_WARN_ON_ONCE(my_pending.stop_pending); return 0; } @@ -3156,7 +3156,7 @@ static int __set_cpus_allowed_ptr_locked(struct task_struct *p, goto out; } - if (WARN_ON_ONCE(p == current && + if (SCHED_WARN_ON_ONCE(p == current && is_migration_disabled(p) && !cpumask_test_cpu(task_cpu(p), ctx->new_mask))) { ret = -EBUSY; @@ -3346,14 +3346,14 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) * We should never call set_task_cpu() on a blocked task, * ttwu() will sort out the placement. */ - WARN_ON_ONCE(state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq); + SCHED_WARN_ON_ONCE(state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq); /* * Migrating fair class task must have p->on_rq = TASK_ON_RQ_MIGRATING, * because schedstat_wait_{start,end} rebase migrating task's wait_start * time relying on p->on_rq. */ - WARN_ON_ONCE(state == TASK_RUNNING && + SCHED_WARN_ON_ONCE(state == TASK_RUNNING && p->sched_class == &fair_sched_class && (p->on_rq && !task_on_rq_migrating(p))); @@ -3368,15 +3368,15 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) * Furthermore, all task_rq users should acquire both locks, see * task_rq_lock(). */ - WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || + SCHED_WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || lockdep_is_held(__rq_lockp(task_rq(p))))); #endif /* * Clearly, migrating tasks to offline CPUs is a fairly daft thing. */ - WARN_ON_ONCE(!cpu_online(new_cpu)); + SCHED_WARN_ON_ONCE(!cpu_online(new_cpu)); - WARN_ON_ONCE(is_migration_disabled(p)); + SCHED_WARN_ON_ONCE(is_migration_disabled(p)); trace_sched_migrate_task(p, new_cpu); @@ -3902,10 +3902,10 @@ void sched_ttwu_pending(void *arg) update_rq_clock(rq); llist_for_each_entry_safe(p, t, llist, wake_entry.llist) { - if (WARN_ON_ONCE(p->on_cpu)) + if (SCHED_WARN_ON_ONCE(p->on_cpu)) smp_cond_load_acquire(&p->on_cpu, !VAL); - if (WARN_ON_ONCE(task_cpu(p) != cpu_of(rq))) + if (SCHED_WARN_ON_ONCE(task_cpu(p) != cpu_of(rq))) set_task_cpu(p, cpu_of(rq)); ttwu_do_activate(rq, p, p->sched_remote_wakeup ? WF_MIGRATED : 0, &rf); @@ -4102,7 +4102,7 @@ bool ttwu_state_match(struct task_struct *p, unsigned int state, int *success) int match; if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) { - WARN_ON_ONCE((state & TASK_RTLOCK_WAIT) && + SCHED_WARN_ON_ONCE((state & TASK_RTLOCK_WAIT) && state != TASK_RTLOCK_WAIT); } @@ -5333,7 +5333,7 @@ static struct rq *finish_task_switch(struct task_struct *prev) * * Also, see FORK_PREEMPT_COUNT. */ - if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET, + if (SCHED_WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET, "corrupted preempt_count: %s/%d/0x%x\n", current->comm, current->pid, preempt_count())) preempt_count_set(FORK_PREEMPT_COUNT); @@ -5861,7 +5861,7 @@ static void sched_tick_remote(struct work_struct *work) * we are always sure that there is no proxy (only a * single task is running). */ - WARN_ON_ONCE(rq->curr != rq->donor); + SCHED_WARN_ON_ONCE(rq->curr != rq->donor); update_rq_clock(rq); if (!is_idle_task(curr)) { @@ -5870,7 +5870,7 @@ static void sched_tick_remote(struct work_struct *work) * reasonable amount of time. */ u64 delta = rq_clock_task(rq) - curr->se.exec_start; - WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 30); + SCHED_WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 30); } curr->sched_class->task_tick(rq, curr, 0); @@ -6302,7 +6302,7 @@ pick_next_task(struct rq *rq, struct rq_flags *rf) * For robustness, update the min_vruntime_fi for * unconstrained picks as well. */ - WARN_ON_ONCE(fi_before); + SCHED_WARN_ON_ONCE(fi_before); task_vruntime_update(rq, next, false); goto out_set_next; } @@ -6380,7 +6380,7 @@ pick_next_task(struct rq *rq, struct rq_flags *rf) rq->core_sched_seq = rq->core->core_pick_seq; /* Something should have been selected for current CPU */ - WARN_ON_ONCE(!next); + SCHED_WARN_ON_ONCE(!next); /* * Reschedule siblings @@ -6423,7 +6423,7 @@ pick_next_task(struct rq *rq, struct rq_flags *rf) } /* Did we break L1TF mitigation requirements? */ - WARN_ON_ONCE(!cookie_match(next, rq_i->core_pick)); + SCHED_WARN_ON_ONCE(!cookie_match(next, rq_i->core_pick)); if (rq_i->curr == rq_i->core_pick) { rq_i->core_pick = NULL; @@ -6561,7 +6561,7 @@ static void sched_core_cpu_starting(unsigned int cpu) guard(core_lock)(&cpu); - WARN_ON_ONCE(rq->core != rq); + SCHED_WARN_ON_ONCE(rq->core != rq); /* if we're the first, we'll be our own leader */ if (cpumask_weight(smt_mask) == 1) @@ -6578,7 +6578,7 @@ static void sched_core_cpu_starting(unsigned int cpu) } } - if (WARN_ON_ONCE(!core_rq)) /* whoopsie */ + if (SCHED_WARN_ON_ONCE(!core_rq)) /* whoopsie */ return; /* install and validate core_rq */ @@ -6588,7 +6588,7 @@ static void sched_core_cpu_starting(unsigned int cpu) if (t == cpu) rq->core = core_rq; - WARN_ON_ONCE(rq->core != core_rq); + SCHED_WARN_ON_ONCE(rq->core != core_rq); } } @@ -6602,7 +6602,7 @@ static void sched_core_cpu_deactivate(unsigned int cpu) /* if we're the last man standing, nothing to do */ if (cpumask_weight(smt_mask) == 1) { - WARN_ON_ONCE(rq->core != rq); + SCHED_WARN_ON_ONCE(rq->core != rq); return; } @@ -6618,7 +6618,7 @@ static void sched_core_cpu_deactivate(unsigned int cpu) break; } - if (WARN_ON_ONCE(!core_rq)) /* impossible */ + if (SCHED_WARN_ON_ONCE(!core_rq)) /* impossible */ return; /* copy the shared state to the new leader */ @@ -7004,7 +7004,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) static struct task_struct * find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) { - WARN_ONCE(1, "This should never be called in the !SCHED_PROXY_EXEC case\n"); + SCHED_WARN_ONCE(1, "This should never be called in the !SCHED_PROXY_EXEC case\n"); return donor; } #endif /* SCHED_PROXY_EXEC */ @@ -7666,8 +7666,8 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) * real need to boost. */ if (unlikely(p == rq->idle)) { - WARN_ON(p != rq->curr); - WARN_ON(p->pi_blocked_on); + SCHED_WARN_ON(p != rq->curr); + SCHED_WARN_ON(p->pi_blocked_on); goto out_unlock; } @@ -8499,7 +8499,7 @@ static void balance_push_set(int cpu, bool on) rq_lock_irqsave(rq, &rf); if (on) { - WARN_ON_ONCE(rq->balance_callback); + SCHED_WARN_ON_ONCE(rq->balance_callback); rq->balance_callback = &balance_push_callback; } else if (rq->balance_callback == &balance_push_callback) { rq->balance_callback = NULL; @@ -8832,7 +8832,7 @@ int sched_cpu_dying(unsigned int cpu) rq_lock_irqsave(rq, &rf); update_rq_clock(rq); if (rq->nr_running != 1 || rq_has_pinned_tasks(rq)) { - WARN(true, "Dying CPU not properly vacated!"); + SCHED_WARN(true, "Dying CPU not properly vacated!"); dump_rq_tasks(rq, KERN_WARNING); } dl_server_stop(&rq->fair_server); -- 2.53.0-Meta