From: | Andres Freund <andres(at)anarazel(dot)de> |
---|---|
To: | Nathan Bossart <nathandbossart(at)gmail(dot)com> |
Cc: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: locked reads for atomics |
Date: | 2023-11-11 02:48:39 |
Message-ID: | 20231111024839.op2d2id33x777mll@alap3.anarazel.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hi,
On 2023-11-10 20:38:13 -0600, Nathan Bossart wrote:
> On Fri, Nov 10, 2023 at 03:11:50PM -0800, Andres Freund wrote:
> > On 2023-11-10 14:51:28 -0600, Nathan Bossart wrote:
> >> + * This read is guaranteed to read the current value,
> >
> > It doesn't guarantee that *at all*. What it guarantees is solely that the
> > current CPU won't be doing something that could lead to reading an outdated
> > value. To actually ensure the value is up2date, the modifying side also needs
> > to have used a form of barrier (in the form of fetch_add, compare_exchange,
> > etc or an explicit barrier).
>
> Okay, I think I was missing that this doesn't work along with
> pg_atomic_write_u32() because that doesn't have any barrier semantics
> (probably because the spinlock version does). IIUC you'd want to use
> pg_atomic_exchange_u32() to write the value instead, which seems to really
> just be another compare/exchange under the hood.
Yes. We should optimize pg_atomic_exchange_u32() one of these days - it can be
done *far* faster than a cmpxchg. When I was adding the atomic abstraction
there was concern with utilizing too many different atomic instructions. I
didn't really agree back then, but these days I really don't see a reason to
not use a few more intrinsics.
> Speaking of the spinlock implementation of pg_atomic_write_u32(), I've been
> staring at this comment for a while and can't make sense of it:
>
> void
> pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
> {
> /*
> * One might think that an unlocked write doesn't need to acquire the
> * spinlock, but one would be wrong. Even an unlocked write has to cause a
> * concurrent pg_atomic_compare_exchange_u32() (et al) to fail.
> */
> SpinLockAcquire((slock_t *) &ptr->sema);
> ptr->value = val;
> SpinLockRelease((slock_t *) &ptr->sema);
> }
>
> It refers to "unlocked writes," but this isn't
> pg_atomic_unlocked_write_u32_impl(). The original thread for this comment
> [0] doesn't offer any hints, either. Does "unlocked" mean something
> different here, such as "write without any barrier semantics?"
It's just about not using the spinlock. If we were to *not* use a spinlock
here, we'd break pg_atomic_compare_exchange_u32(), because the
spinlock-implementation of pg_atomic_compare_exchange_u32() needs to actually
be able to rely on no concurrent changes to the value to happen.
Greetings,
Andres Freund
From | Date | Subject | |
---|---|---|---|
Next Message | Erik Rijkers | 2023-11-11 02:52:42 | Re: remaining sql/json patches |
Previous Message | Nathan Bossart | 2023-11-11 02:38:13 | Re: locked reads for atomics |