From: Matthew Wilcox <willy@infradead.org>
To: Vlastimil Babka <vbabka@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
LKML <linux-kernel@vger.kernel.org>,
"linux-mm@kvack.org" <linux-mm@kvack.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Waiman Long <longman@redhat.com>,
Mel Gorman <mgorman@techsingularity.net>,
Steven Rostedt <rostedt@goodmis.org>
Subject: Re: [RFC] making nested spin_trylock() work on UP?
Date: Sat, 14 Feb 2026 06:28:43 +0000 [thread overview]
Message-ID: <aZAWGwZP_Z75YHKt@casper.infradead.org> (raw)
In-Reply-To: <d762c46b-36f0-471a-b5b4-23c8cf5628ae@suse.cz>
On Fri, Feb 13, 2026 at 12:57:43PM +0100, Vlastimil Babka wrote:
> The page allocator has been using a locking scheme for its percpu page
> caches (pcp) for years now, based on spin_trylock() with no _irqsave() part.
> The point is that if we interrupt the locked section, we fail the trylock
> and just fallback to something that's more expensive, but it's rare so we
> don't need to pay the irqsave cost all the time in the fastpaths.
>
> It's similar to but not exactly local_trylock_t (which is also newer anyway)
> because in some cases we do lock the pcp of a non-local cpu to flush it, in
> a way that's cheaper than IPI or queue_work_on().
>
> The complication of this scheme has been UP non-debug spinlock
> implementation which assumes spin_trylock() can't fail on UP and has no
> state to track it. It just doesn't anticipate this usage scenario. So to
> work around that we disable IRQs on UP, complicating the implementation.
> Also recently we found years old bug in the implementation - see
> 038a102535eb ("mm/page_alloc: prevent pcp corruption with SMP=n").
>
> So my question is if we could have spinlock implementation supporting this
> nested spin_trylock() usage, or if the UP optimization is still considered
> too important to lose it. I was thinking:
>
> - remove the UP implementation completely - would it increase the overhead
> on SMP=n systems too much and do we still care?
>
> - make the non-debug implementation a bit like the debug one so we do have
> the 'locked' state (see include/linux/spinlock_up.h and lock->slock). This
> also adds some overhead but not as much as the full SMP implementation?
What if we use an atomic_t on UP to simulate there being a spinlock,
but only for pcp? Your demo shows pcp_spin_trylock() continuing to
exist, so how about doing something like:
#ifdef CONFIG_SMP
#define pcp_spin_trylock(ptr) \
({ \
struct per_cpu_pages *__ret; \
__ret = pcpu_spin_trylock(struct per_cpu_pages, lock, ptr); \
__ret; \
})
#else
static atomic_t pcp_UP_lock = ATOMIC_INIT(0);
#define pcp_spin_trylock(ptr) \
({ \
struct per_cpu_pages *__ret = NULL; \
if (atomic_try_cmpxchg(&pcp_UP_lock, 0, 1)) \
__ret = (void *)&pcp_UP_lock; \
__ret; \
});
#endif
(obviously you need pcp_spin_lock/pcp_spin_unlock also defined)
That only costs us 4 extra bytes on UP, rather than 4 bytes per spinlock.
And some people still use routers with tiny amounts of memory and a
single CPU, or retrocomputers with single CPUs.
next prev parent reply other threads:[~2026-02-14 6:29 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-13 11:57 [RFC] making nested spin_trylock() work on UP? Vlastimil Babka
2026-02-14 6:28 ` Matthew Wilcox [this message]
2026-02-14 16:32 ` Linus Torvalds
2026-02-16 10:32 ` Vlastimil Babka
2026-04-15 18:44 ` Harry Yoo (Oracle)
2026-04-16 10:05 ` Vlastimil Babka (SUSE)
2026-04-16 14:26 ` Alexei Starovoitov
2026-04-16 14:35 ` Harry Yoo (Oracle)
2026-04-16 14:37 ` Alexei Starovoitov
2026-04-17 2:34 ` Harry Yoo (Oracle)
2026-04-17 2:41 ` Alexei Starovoitov
2026-04-17 3:59 ` Harry Yoo (Oracle)
2026-04-17 5:37 ` Alexei Starovoitov
-- strict thread matches above, loose matches on Subject: below --
2026-02-13 11:57 Vlastimil Babka
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=aZAWGwZP_Z75YHKt@casper.infradead.org \
--to=willy@infradead.org \
--cc=bigeasy@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=longman@redhat.com \
--cc=mgorman@techsingularity.net \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=torvalds@linux-foundation.org \
--cc=vbabka@suse.cz \
--cc=will@kernel.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.