From: Thomas Gleixner <tglx@linutronix.de>
To: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Waiman Long <longman@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Clark Williams <clrkwllms@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev
Subject: Re: [PATCH-tip v3] debugobjects: Don't call fill_pool() in early boot non-task context
Date: Wed, 03 Jun 2026 19:07:52 +0200 [thread overview]
Message-ID: <87mrxb5z87.ffs@fw13> (raw)
In-Reply-To: <20260603075656.S1aZM9PO@linutronix.de>
On Wed, Jun 03 2026 at 09:56, Sebastian Andrzej Siewior wrote:
> On 2026-05-20 16:15:09 [-0400], Waiman Long wrote:
> diff --git a/lib/debugobjects.c b/lib/debugobjects.c
> index b18a682fe3da2..2adfe2a79a086 100644
> --- a/lib/debugobjects.c
> +++ b/lib/debugobjects.c
> @@ -736,12 +736,17 @@ static void debug_objects_fill_pool(void)
>
> /*
> * On RT enabled kernels the pool refill must happen in preemptible
> - * context and not enqueued on an rt_mutex -- for !RT kernels we rely
> - * on the fact that spinlock_t and raw_spinlock_t are basically the
> - * same type and this lock-type inversion works just fine.
> + * context and not while blocking on a lock which can trigger recursion
> + * during PI. During system boot (before scheduling) preemption is
> + * disabled and the pool gets exhausted. Without scheduling a deadlock
> + * is not possible if allocations from interrupt context are excluded.
> + * For !RT kernels we rely on the fact that spinlock_t and
> + * raw_spinlock_t are basically the same type and this lock-type
> + * inversion works just fine.
> */
> - if (!IS_ENABLED(CONFIG_PREEMPT_RT) || system_state < SYSTEM_SCHEDULING ||
> - (preemptible() && !debug_objects_is_pi_blocked_on())) {
> + if (!IS_ENABLED(CONFIG_PREEMPT_RT) ||
> + !debug_objects_is_pi_blocked_on() &&
> + (preemptible() || (system_state < SYSTEM_SCHEDULING && !in_hardirq()))) {
This whole thing is unreadable gunk by now and I really can't decode the
correctness of the condition without reading it five times. Something
like the below:
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -720,6 +720,34 @@ static inline bool debug_objects_is_pi_b
#endif
}
+static inline bool can_fill_pool(void)
+{
+ /*
+ * On !RT enabled kernels there are no restrictions and spinlock_t and
+ * raw_spinlock_t are the same types.
+ */
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ return true;
+
+ /*
+ * On RT enabled kernels the pool refill must happen in preemptible
+ * context and the task must not be blocked on a lock as that could
+ * corrupt the PI state when blocking on a lock in the allocation path.
+ */
+ if (preemptible() && !debug_objects_is_pi_blocked_on())
+ return true;
+
+ /*
+ * Though during system boot before scheduling is set up, preemption is
+ * disabled and the pool can get exhausted. Before scheduling is active
+ * a task cannot be blocked on a sleeping lock, but it might hold a lock
+ * and if interrupted then hard interrupt context might run into a lock
+ * inversion. So exclude hard interrupt context from allocations before
+ * scheduling is active.
+ */
+ return system_state < SYSTEM_SCHEDULING && !in_hardirq();
+}
+
static void debug_objects_fill_pool(void)
{
if (!static_branch_likely(&obj_cache_enabled))
@@ -734,18 +762,11 @@ static void debug_objects_fill_pool(void
if (likely(!pool_should_refill(&pool_global)))
return;
- /*
- * On RT enabled kernels the pool refill must happen in preemptible
- * context and not enqueued on an rt_mutex -- for !RT kernels we rely
- * on the fact that spinlock_t and raw_spinlock_t are basically the
- * same type and this lock-type inversion works just fine.
- */
- if (!IS_ENABLED(CONFIG_PREEMPT_RT) || system_state < SYSTEM_SCHEDULING ||
- (preemptible() && !debug_objects_is_pi_blocked_on())) {
+ if (can_fill_pool()) {
/*
* Annotate away the spinlock_t inside raw_spinlock_t warning
* by temporarily raising the wait-type to LD_WAIT_CONFIG, matching
- * the preemptible() condition above.
+ * the preemptible() condition in can_fill_pool().
*/
static DEFINE_WAIT_OVERRIDE_MAP(fill_pool_map, LD_WAIT_CONFIG);
lock_map_acquire_try(&fill_pool_map);
prev parent reply other threads:[~2026-06-03 17:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-20 20:15 [PATCH-tip v3] debugobjects: Don't call fill_pool() in early boot non-task context Waiman Long
2026-06-03 2:26 ` Waiman Long
2026-06-03 7:56 ` Sebastian Andrzej Siewior
2026-06-03 14:59 ` Waiman Long
2026-06-03 15:30 ` Sebastian Andrzej Siewior
2026-06-03 17:07 ` Thomas Gleixner [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87mrxb5z87.ffs@fw13 \
--to=tglx@linutronix.de \
--cc=akpm@linux-foundation.org \
--cc=bigeasy@linutronix.de \
--cc=clrkwllms@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=longman@redhat.com \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.