Re: [PATCH v2] smp: Use release stores for csd_lock_record() state
Dmitry Ilvokhin <[email protected]> Fri, 26 Jun 2026 16:45:41 +0000
| Newsgroups | dev.linux.lists.lkmm,org.kernel.vger.linux-kernel,org.kernel.vger.rcu |
|---|---|
| Message-ID | <[email protected]> |
On Fri, Jun 26, 2026 at 05:30:21PM +0100, Usama Arif wrote: > > > On 25/06/2026 15:42, Dmitry Ilvokhin wrote: > > On Mon, Jun 22, 2026 at 09:38:07AM -0700, Usama Arif wrote: > >> __csd_lock_record() publishes per-CPU CSD debug state that is read by > >> csd_lock_wait_toolong() on another CPU. The remote side first reads > >> cur_csd with smp_load_acquire() and, when non-NULL, may then read the > >> matching cur_csd_func and cur_csd_info fields. > >> > >> Use smp_store_release() when publishing cur_csd so that the preceding > >> cur_csd_func and cur_csd_info stores are ordered before the pointer > >> that csd_lock_wait_toolong() acquires. This replaces the open-coded > >> smp_wmb() plus plain cur_csd store with the release operation that > >> matches the smp_load_acquire() in csd_lock_wait_toolong(). > >> > >> For the clear path, use smp_store_release(&cur_csd, NULL) so that > >> clearing the diagnostic state remains ordered after the preceding > >> callback/unlock work, without requiring a full barrier before the > >> store. On x86 this removes the locked full barrier from the clear > >> path; on weaker memory models it uses the release operation needed by > >> the smp_load_acquire() in csd_lock_wait_toolong(). > > > > The changelog only calls out the clear path here, but the publish path > > also drops its trailing smp_mb() (plus the smp_wmb()), so on x86 both > > paths lose a locked full barrier. Worth describing symmetrically. > > Do you mean whats written in the next paragraph? The paragraph above > is for clear, the paragraph just below is for publish. The reason for removing > smp_wmb() is in 2nd paragraph. I think all the information regarding the changes > is in the commit message.> Indeed. I clearly can not read properly. > >> > >> The old code also had smp_mb() calls around cur_csd updates. Those would > >> only be needed if cur_csd were treated as an exact live-state marker whose > >> publication had to be observed before callback execution or CSD unlock. > >> CSD stall warnings do not currently have RCU-style stall-ended checks, so > >> they already allow the stall to end while diagnostics are being assembled. > >> The cur_csd record is therefore best-effort diagnostic context, not a > >> precise completion/stall boundary. > >> > >> Signed-off-by: Usama Arif <[email protected]> > >> --- > >> v1 -> v2: https://lore.kernel.org/all/[email protected]/ > >> - Document where the smp_store_release() synchronizes with (Alan Stern, > >> Randy Dunlap and Paul McKenney). > >> --- > >> kernel/smp.c | 18 ++++++++++++------ > >> 1 file changed, 12 insertions(+), 6 deletions(-) > >> > >> diff --git a/kernel/smp.c b/kernel/smp.c > >> index a0bb56bd8dda..685829875a3e 100644 > >> --- a/kernel/smp.c > >> +++ b/kernel/smp.c > >> @@ -182,16 +182,22 @@ static atomic_t csd_bug_count = ATOMIC_INIT(0); > >> static void __csd_lock_record(call_single_data_t *csd) > >> { > >> if (!csd) { > >> - smp_mb(); /* NULL cur_csd after unlock. */ > >> - __this_cpu_write(cur_csd, NULL); > >> + /* > >> + * Pairs with smp_load_acquire() of cur_csd in > >> + * csd_lock_wait_toolong(): orders any preceding CSD > >> + * callback/unlock before a remote reader observes NULL. > >> + */ > >> + smp_store_release(this_cpu_ptr(&cur_csd), NULL); > >> return; > >> } > >> __this_cpu_write(cur_csd_func, csd->func); > >> __this_cpu_write(cur_csd_info, csd->info); > >> - smp_wmb(); /* func and info before csd. */ > >> - __this_cpu_write(cur_csd, csd); > >> - smp_mb(); /* Update cur_csd before function call. */ > >> - /* Or before unlock, as the case may be. */ > >> + /* > >> + * Pairs with smp_load_acquire() of cur_csd in > >> + * csd_lock_wait_toolong(): publishes cur_csd_func and > >> + * cur_csd_info before the non-NULL pointer becomes visible. > >> + */ > >> + smp_store_release(this_cpu_ptr(&cur_csd), csd); > >> } > > > > Since v2 is specifically about documenting the pairing, it would be good > > to make it symmetric and add the comment on the acquire side in > > csd_lock_wait_toolong(). > > > > Its already documented [1] > > [1] https://elixir.bootlin.com/linux/v7.1.1/source/kernel/smp.c#L275 It is documented to some extent, but it doesn't explicitly state which smp_store_release() the smp_load_acquire() pairs with. I think that's the main benefit of these comments: making the synchronization pair explicit so readers don't have to infer it.