| From: | Alexandre Felipe <o(dot)alexandre(dot)felipe(at)gmail(dot)com> |
|---|---|
| To: | Andres Freund <andres(at)anarazel(dot)de> |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: Throwing away unnecessary spin-locks |
| Date: | 2026-10-02 05:06:01 |
| Message-ID: | CAE8JnxOic51vSs0XZqsGheWnNLeJP7p2_z=O3PorU8cXNSC7pg@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Mutatis mutandis.
At this stage I am happy if it compiles everywhere
On Thu, Oct 1, 2026 at 9:50 PM Alexandre Felipe <
o(dot)alexandre(dot)felipe(at)gmail(dot)com> wrote:
>
>
> On Thu, Oct 1, 2026 at 9:08 PM Andres Freund <andres(at)anarazel(dot)de> wrote:
>
>> Hi,
>>
>> On 2026-10-01 20:50:35 +0100, Alexandre Felipe wrote:
>> > Please try, if you want
>> > $ grep -A 2 -rn SpinLockAcquire src/backend | grep SpinLockRelease -B 2
>> >
>> > Story
>> > =====
>> > A common pattern that I have been repeatedly warned against is using
>> > spin-locks unnecessarily. I was surprised to see in checkpointer.c
>> > FirstCallSinceLastCheckpoint.
>> >
>> > int new_done;
>> > SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
>> > new_done = CheckpointerShmem->ckpt_done;
>> > SpinLockRelease(&CheckpointerShmem->ckpt_lck);
>> >
>> > I think could certainly be replaced by something like
>> >
>> > + pg_compiler_barrier()
>> > + new_done = CheckpointerShmem->ckpt_done;
>> > + pg_compiler_barrier()
>>
>> That's not a correct transformation. A compiler barrier does not guarantee
>> cache coherency. You actually have to use correct memory barrier
>> pairings. It
>> might suffice to use a read memory barrier in this case, but obviously the
>> easiest transformation is to use full memory barriers on both sides.
>>
>
> Like this (sometimes I miss C++ templates)
>
>
> #define SLOCK_DEFINE_SCALAR_ACCESSORS(typename) \
>
> static inline typename \
>
> slock_read_barrier_##typename(volatile slock_t *lock, volatile typename
> *p) \
>
> { \
>
> typename val; \
>
> \
>
> (void) lock; \
>
> AssertPointerAlignment(p, alignof(typename)); \
>
> val = *p; \
>
> pg_read_barrier(); \
>
> return val; \
>
> } \
>
> static inline void \
>
> slock_write_barrier_##typename(volatile slock_t *lock, volatile typename
> *p, typename v) \
>
> { \
>
> (void) lock; \
>
> AssertPointerAlignment(p, alignof(typename)); \
>
> *p = v; \
>
> pg_write_barrier(); \
>
>
> }
>
> Or on both sides?
>
> The main reason for not having changed all of these over is that you
>> actually
>> have to carefully think about the changes...
>>
>
> Or thinking once about conditions that make them possible and apply some
> transformation.
>
>
>> > Grepping the codebase we get 105 matches, in 26 files.
>> >
>> > One interesting case is xlog.c that uses the lock to protect 64-bit
>> > assignments I saw conversations about pg_atomic_u64 for that, but then
>> in
>> > 32-bit platforms we get this weird 3-field structure everywhere.
>>
>> What are you referring to with "weird 3-field structure"?
>>
>
>
> typedef struct pg_atomic_uint64
> {
> int sema;
> volatile uint64 value;
> } pg_atomic_uint64;
>
> Sorry it is not declared as 3 field, I was thinking
> struct {int sema; volatile uint32 v1; volatile uint32 v2; }
>
> Regards,
> Alexandre
>
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Spin-lock-protected-scalar-accessors.patch | application/octet-stream | 4.1 KB |
| v1-0002-replace-slock_-read-write-_.patch | application/octet-stream | 28.3 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | shihao zhong | 2026-10-02 05:30:07 | Re: Throwing away unnecessary spin-locks |
| Previous Message | Michael Paquier | 2026-10-02 04:57:41 | Re: WAL segment file descriptor leak on read errors can PANIC the server |