Subject: "38.10.10. Shared Memory and LWLocks" may require a clarification

From: Aleksander Alekseev <[email-masked]>
Date: Fri, 19 May 2023 18:49:11 +0300

Hi,

While re-reading 38.10.10. Shared Memory and LWLocks [1] and the
corresponding code in pg_stat_statements.c I noticed that there are
several things that can puzzle the reader.

The documentation and the example suggest that LWLock* should be
stored within a structure in shared memory:

```
typedef struct pgssSharedState
{
    LWLock       *lock;
    /* ... etc ... */
} pgssSharedState;
```

... and initialized like this:

```
    LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);

    pgss = ShmemInitStruct("pg_stat_statements",
                           sizeof(pgssSharedState),
                           &found);

    if (!found)
    {
        pgss->lock = &(GetNamedLWLockTranche("pg_stat_statements"))->lock;
        /* ... */
    }

    /* ... */

    LWLockRelease(AddinShmemInitLock);
```

It is not clear why placing LWLock* in a local process memory would be a bug.

On top of that the documentation says:

"""
To avoid possible race-conditions, each backend should use the LWLock
AddinShmemInitLock when connecting to and initializing its allocation
of shared memory
"""

However it's not clear when a race-condition may happen. The rest of
the text gives an overall impression that the shmem_startup_hook will
be called by postmaster once (unless an extension places several hooks
in series). Thus there is no real need to ackquire AddinShmemInitLock
and it should be safe to store LWLock* in local process memory. This
memory will be inherited from postmaster by child processes and the
overall memory usage is going to be the same due to copy-on-write.

Perhaps we should clarify this.

Thoughts?

[1]: https://www.postgresql.org/docs/15/xfunc-c.html#XFUNC-SHARED-ADDIN

-- 
Best regards,
Aleksander Alekseev