Home Explore Blog CI



postgresql

46th chunk of `doc/src/sgml/xfunc.sgml`
c869ce11d0dd50024c2fd0e10ccd3637f35ba121335a52920000000100000fa3
 reserve shared memory by
      calling:
<programlisting>
void RequestAddinShmemSpace(Size size)
</programlisting>
      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, &amp;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>

    <sect3 id="xfunc-shared-addin-after-startup">
     <title>Requesting Shared Memory After Startup</title>

     <para>
      There is another, more flexible method of reserving shared memory that
      can be done after server startup and outside a
      <literal>shmem_request_hook</literal>.  To do so, each backend that will
      use the shared memory should obtain a pointer to it by calling:
<programlisting>
void *GetNamedDSMSegment(const char *name, size_t size,
                         void (*init_callback) (void *ptr),
                         bool *found)
</programlisting>
      If a dynamic shared memory segment with the given name does not yet
      exist, this function will allocate it and initialize it with the provided
      <function>init_callback</function> callback function.  If the segment has
      already been allocated and initialized by another backend, this function
      simply attaches the existing dynamic shared memory segment to the current
      backend.
     </para>

     <para>
      Unlike shared memory reserved at server startup, there is no need to
      acquire <function>AddinShmemInitLock</function> or otherwise take action
      to avoid race conditions when reserving shared memory with
      <function>GetNamedDSMSegment</function>.  This function ensures that only
      one backend allocates and initializes the segment and that all other
      backends receive a pointer to the fully allocated and initialized
      segment.
     </para>

     <para>
      A complete usage example of <function>GetNamedDSMSegment</function> can
      be found in
      <filename>src/test/modules/test_dsm_registry/test_dsm_registry.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

Title: Shared Memory Allocation and Initialization: Startup and Post-Startup
Summary
Add-ins can reserve shared memory at startup using RequestAddinShmemSpace in a shmem_request_hook, obtaining a pointer with ShmemInitStruct. To prevent race conditions during initialization, backends should use the AddinShmemInitLock LWLock. The shmem_startup_hook is a convenient place for initialization code. Alternatively, shared memory can be reserved after startup with GetNamedDSMSegment, which allocates and initializes a dynamic shared memory segment if it doesn't exist, ensuring only one backend initializes it and avoiding race conditions.