public inbox for [email protected]
help / color / mirror / Atom feedFrom: Nathan Bossart <[email protected]>
To: Aleksander Alekseev <[email protected]>
Cc: [email protected]
Subject: Re: reorganize "Shared Memory and LWLocks" section of docs
Date: Sat, 13 Jan 2024 15:28:15 -0600
Message-ID: <20240113212815.GA4065002@nathanxps13> (raw)
In-Reply-To: <CAJ7c6TOdT9TyUKwx+DgS=MEi48JiscGxoAjuMczKEU8-jMsDpA@mail.gmail.com>
References: <20240112041430.GA3557928@nathanxps13>
<CAJ7c6TNC-tC9JS_X_FSShDEeGujrUdunVdtBBm+YGg8VW+AkFg@mail.gmail.com>
<20240112154650.GA3565306@nathanxps13>
<20240112172350.GB3803561@nathanxps13>
<CAJ7c6TOdT9TyUKwx+DgS=MEi48JiscGxoAjuMczKEU8-jMsDpA@mail.gmail.com>
On Sat, Jan 13, 2024 at 01:49:08PM +0300, Aleksander Alekseev wrote:
> That's much better, thanks.
>
> I think the patch could use another pair of eyes, ideally from a
> native English speaker. But if no one will express any objections for
> a while I suggest merging it.
Great. I've attached a v3 with a couple of fixes suggested in the other
thread [0]. I'll wait a little while longer in case anyone else wants to
take a look.
[0] https://postgr.es/m/ZaF6UpYImGqVIhVp%40toroid.org
--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com
Attachments:
[text/x-diff] v3-0001-reorganize-shared-memory-and-lwlocks-documentatio.patch (9.3K, ../20240113212815.GA4065002@nathanxps13/2-v3-0001-reorganize-shared-memory-and-lwlocks-documentatio.patch)
download | inline diff:
From b56931edc4488a7376b27ba0e5519cc3a61b4899 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <[email protected]>
Date: Thu, 11 Jan 2024 21:55:25 -0600
Subject: [PATCH v3 1/1] reorganize shared memory and lwlocks documentation
---
doc/src/sgml/xfunc.sgml | 182 +++++++++++++++++++++++++---------------
1 file changed, 114 insertions(+), 68 deletions(-)
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 89116ae74c..82e1dadcca 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3397,90 +3397,136 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray
</sect2>
<sect2 id="xfunc-shared-addin">
- <title>Shared Memory and LWLocks</title>
+ <title>Shared Memory</title>
- <para>
- Add-ins can reserve LWLocks and an allocation of shared memory on server
- startup. The add-in's shared library must be preloaded by specifying
- it in
- <xref linkend="guc-shared-preload-libraries"/><indexterm><primary>shared_preload_libraries</primary></indexterm>.
- The shared library should register a <literal>shmem_request_hook</literal>
- in its <function>_PG_init</function> function. This
- <literal>shmem_request_hook</literal> can reserve LWLocks or shared memory.
- Shared memory is reserved by calling:
+ <sect3 id="xfunc-shared-addin-at-startup">
+ <title>Requesting Shared Memory at Startup</title>
+
+ <para>
+ Add-ins can reserve shared memory on server startup. To do so, the
+ add-in's shared library must be preloaded by specifying it in
+ <xref linkend="guc-shared-preload-libraries"/><indexterm><primary>shared_preload_libraries</primary></indexterm>.
+ The shared library should also register a
+ <literal>shmem_request_hook</literal> in its
+ <function>_PG_init</function> function. This
+ <literal>shmem_request_hook</literal> can reserve shared memory by
+ calling:
<programlisting>
void RequestAddinShmemSpace(int size)
</programlisting>
- from your <literal>shmem_request_hook</literal>.
- </para>
- <para>
- LWLocks are reserved by calling:
+ Each backend should obtain a pointer to the reserved shared memory by
+ calling:
+<programlisting>
+void *ShmemInitStruct(const char *name, Size size, bool *foundPtr)
+</programlisting>
+ If this function sets <literal>foundPtr</literal> to
+ <literal>false</literal>, the caller should proceed to initialize the
+ contents of the reserved shared memory. If <literal>foundPtr</literal>
+ is set to <literal>true</literal>, the shared memory was already
+ initialized by another backend, and the caller need not initialize
+ further.
+ </para>
+
+ <para>
+ To avoid race conditions, each backend should use the LWLock
+ <function>AddinShmemInitLock</function> when initializing its allocation
+ of shared memory, as shown here:
+<programlisting>
+static mystruct *ptr = NULL;
+bool found;
+
+LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
+ptr = ShmemInitStruct("my struct name", size, &found);
+if (!found)
+{
+ ... initialize contents of shared memory ...
+ ptr->locks = GetNamedLWLockTranche("my tranche name");
+}
+LWLockRelease(AddinShmemInitLock);
+</programlisting>
+ <literal>shmem_startup_hook</literal> provides a convenient place for the
+ initialization code, but it is not strictly required that all such code
+ be placed in this hook. Each backend will execute the registered
+ <literal>shmem_startup_hook</literal> shortly after it attaches to shared
+ memory. Note that add-ins should still acquire
+ <function>AddinShmemInitLock</function> within this hook, as shown in the
+ example above.
+ </para>
+
+ <para>
+ An example of a <literal>shmem_request_hook</literal> and
+ <literal>shmem_startup_hook</literal> can be found in
+ <filename>contrib/pg_stat_statements/pg_stat_statements.c</filename> in
+ the <productname>PostgreSQL</productname> source tree.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="xfunc-addin-lwlocks">
+ <title>LWLocks</title>
+
+ <sect3 id="xfunc-addin-lwlocks-at-startup">
+ <title>Requesting LWLocks at Startup</title>
+
+ <para>
+ Add-ins can reserve LWLocks on server startup. As with shared memory,
+ the add-in's shared library must be preloaded by specifying it in
+ <xref linkend="guc-shared-preload-libraries"/><indexterm><primary>shared_preload_libraries</primary></indexterm>,
+ and the shared library should register a
+ <literal>shmem_request_hook</literal> in its
+ <function>_PG_init</function> function. This
+ <literal>shmem_request_hook</literal> can reserve LWLocks by calling:
<programlisting>
void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
</programlisting>
- from your <literal>shmem_request_hook</literal>. This will ensure that an array of
- <literal>num_lwlocks</literal> LWLocks is available under the name
- <literal>tranche_name</literal>. Use <function>GetNamedLWLockTranche</function>
- to get a pointer to this array.
- </para>
- <para>
- An example of a <literal>shmem_request_hook</literal> can be found in
- <filename>contrib/pg_stat_statements/pg_stat_statements.c</filename> in the
- <productname>PostgreSQL</productname> source tree.
- </para>
- <para>
- There is another, more flexible method of obtaining LWLocks. First,
- allocate a <literal>tranche_id</literal> from a shared counter by
- calling:
+ This ensures that an array of <literal>num_lwlocks</literal> LWLocks is
+ available under the name <literal>tranche_name</literal>. A pointer to
+ this array can be obtained by calling:
<programlisting>
-int LWLockNewTrancheId(void)
+LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)
</programlisting>
- Next, each individual process using the <literal>tranche_id</literal>
- should associate it with a <literal>tranche_name</literal> by calling:
+ </para>
+ </sect3>
+
+ <sect3 id="xfunc-addin-lwlocks-after-startup">
+ <title>Requesting LWLocks After Startup</title>
+
+ <para>
+ There is another, more flexible method of obtaining LWLocks that can be
+ done after server startup and outside a
+ <literal>shmem_request_hook</literal>. To do so, first allocate a
+ <literal>tranche_id</literal> by calling:
<programlisting>
-void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
+int LWLockNewTrancheId(void)
</programlisting>
- It is also required to call <function>LWLockInitialize</function> once
- per LWLock, passing the <literal>tranche_id</literal> as argument:
+ Next, initialize each LWLock, passing the new
+ <literal>tranche_id</literal> as an argument:
<programlisting>
void LWLockInitialize(LWLock *lock, int tranche_id)
</programlisting>
- A complete usage example of <function>LWLockNewTrancheId</function>,
- <function>LWLockInitialize</function> and
- <function>LWLockRegisterTranche</function> can be found in
- <filename>contrib/pg_prewarm/autoprewarm.c</filename> in the
- <productname>PostgreSQL</productname> source tree.
- </para>
- <para>
- To avoid possible race-conditions, each backend should use the LWLock
- <function>AddinShmemInitLock</function> when connecting to and initializing
- its allocation of shared memory, as shown here:
-<programlisting>
-static mystruct *ptr = NULL;
+ Similar to shared memory, each backend should ensure that only one
+ process allocates a new <literal>tranche_id</literal> and initializes
+ each new LWLock. One way to do this is to only call these functions in
+ your shared memory initialization code with the
+ <function>AddinShmemInitLock</function> held exclusively.
+ </para>
-if (!ptr)
-{
- bool found;
-
- LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
- ptr = ShmemInitStruct("my struct name", size, &found);
- if (!found)
- {
- initialize contents of shmem area;
- acquire any requested LWLocks using:
- ptr->locks = GetNamedLWLockTranche("my tranche name");
- }
- LWLockRelease(AddinShmemInitLock);
-}
+ <para>
+ Finally, each backend using the <literal>tranche_id</literal> should
+ associate it with a <literal>tranche_name</literal> by calling:
+<programlisting>
+void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
</programlisting>
- </para>
- <para>
- It is convenient to use <literal>shmem_startup_hook</literal> which allows
- placing all the code responsible for initializing shared memory in one
- place. When using <literal>shmem_startup_hook</literal> the extension
- still needs to acquire <function>AddinShmemInitLock</function> in order to
- work properly on all the supported platforms.
- </para>
+ </para>
+
+ <para>
+ A complete usage example of <function>LWLockNewTrancheId</function>,
+ <function>LWLockInitialize</function>, and
+ <function>LWLockRegisterTranche</function> can be found in
+ <filename>contrib/pg_prewarm/autoprewarm.c</filename> in the
+ <productname>PostgreSQL</productname> source tree.
+ </para>
+ </sect3>
</sect2>
<sect2 id="xfunc-addin-wait-events">
--
2.25.1
view thread (11+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: reorganize "Shared Memory and LWLocks" section of docs
In-Reply-To: <20240113212815.GA4065002@nathanxps13>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox