Allow passing a pointer to GetNamedDSMSegment()'s init callback.
authorNathan Bossart <nathan@postgresql.org>
Mon, 15 Dec 2025 20:27:16 +0000 (14:27 -0600)
committerNathan Bossart <nathan@postgresql.org>
Mon, 15 Dec 2025 20:27:16 +0000 (14:27 -0600)
This commit adds a new "void *arg" parameter to
GetNamedDSMSegment() that is passed to the initialization callback
function.  This is useful for reusing an initialization callback
function for multiple DSM segments.

Author: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Discussion: https://postgr.es/m/CAN4CZFMjh8TrT9ZhWgjVTzBDkYZi2a84BnZ8bM%2BfLPuq7Cirzg%40mail.gmail.com

contrib/pg_prewarm/autoprewarm.c
doc/src/sgml/xfunc.sgml
src/backend/storage/ipc/dsm_registry.c
src/include/storage/dsm_registry.h
src/test/modules/injection_points/injection_points.c
src/test/modules/test_dsa/test_dsa.c
src/test/modules/test_dsm_registry/test_dsm_registry.c

index 5ba1240d51f81af911b9d1e5bba5f4f86de1505b..a87b046d8be979f37755fa654eaded1721165a19 100644 (file)
@@ -858,7 +858,7 @@ autoprewarm_dump_now(PG_FUNCTION_ARGS)
 }
 
 static void
-apw_init_state(void *ptr)
+apw_init_state(void *ptr, void *arg)
 {
    AutoPrewarmSharedState *state = (AutoPrewarmSharedState *) ptr;
 
@@ -880,7 +880,7 @@ apw_init_shmem(void)
    apw_state = GetNamedDSMSegment("autoprewarm",
                                   sizeof(AutoPrewarmSharedState),
                                   apw_init_state,
-                                  &found);
+                                  &found, NULL);
 
    return found;
 }
index 2de3309267d40e9349650c3ed8dde8583e5a7387..e9288bd6b5e201ae017ece9360bd417d56b44a4c 100644 (file)
@@ -3696,15 +3696,18 @@ LWLockRelease(AddinShmemInitLock);
       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)
+                         void (*init_callback) (void *ptr, void *arg),
+                         bool *found, void *arg)
 </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.
+      backend.  In the former case, <function>GetNamedDSMSegment</function>
+      passes the <literal>void *arg</literal> argument to the
+      <function>init_callback</function>.  This is particularly useful for
+      reusing an initialization callback function for multiple DSM segments.
      </para>
 
      <para>
index 66240318e83dd0c50f2ffd0afd431c511233a8c9..072f9399969d037a804ab51dd0ae21ad79b1ab15 100644 (file)
@@ -180,11 +180,13 @@ init_dsm_registry(void)
  * Initialize or attach a named DSM segment.
  *
  * This routine returns the address of the segment.  init_callback is called to
- * initialize the segment when it is first created.
+ * initialize the segment when it is first created.  'arg' is passed through to
+ * the initialization callback function.
  */
 void *
 GetNamedDSMSegment(const char *name, size_t size,
-                  void (*init_callback) (void *ptr), bool *found)
+                  void (*init_callback) (void *ptr, void *arg),
+                  bool *found, void *arg)
 {
    DSMRegistryEntry *entry;
    MemoryContext oldcontext;
@@ -235,7 +237,7 @@ GetNamedDSMSegment(const char *name, size_t size,
        seg = dsm_create(size, 0);
 
        if (init_callback)
-           (*init_callback) (dsm_segment_address(seg));
+           (*init_callback) (dsm_segment_address(seg), arg);
 
        dsm_pin_segment(seg);
        dsm_pin_mapping(seg);
index 4871ed509ebc6a03b19e296f6ba029765f1ec3cf..c7c6827afec711a9a85436ae212ef6044dcee642 100644 (file)
@@ -16,8 +16,8 @@
 #include "lib/dshash.h"
 
 extern void *GetNamedDSMSegment(const char *name, size_t size,
-                               void (*init_callback) (void *ptr),
-                               bool *found);
+                               void (*init_callback) (void *ptr, void *arg),
+                               bool *found, void *arg);
 extern dsa_area *GetNamedDSA(const char *name, bool *found);
 extern dshash_table *GetNamedDSHash(const char *name,
                                    const dshash_parameters *params,
index 417b61f31c519067403523d986ba2cc2f93ccd3f..25340e8d81be7fb1a1b469967b0efc1fac0ab7f3 100644 (file)
@@ -115,7 +115,7 @@ static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
  * when initializing dynamically with a DSM or when loading the module.
  */
 static void
-injection_point_init_state(void *ptr)
+injection_point_init_state(void *ptr, void *arg)
 {
    InjectionPointSharedState *state = (InjectionPointSharedState *) ptr;
 
@@ -159,7 +159,7 @@ injection_shmem_startup(void)
         * First time through, so initialize.  This is shared with the dynamic
         * initialization using a DSM.
         */
-       injection_point_init_state(inj_state);
+       injection_point_init_state(inj_state, NULL);
    }
 
    LWLockRelease(AddinShmemInitLock);
@@ -179,7 +179,7 @@ injection_init_shmem(void)
    inj_state = GetNamedDSMSegment("injection_points",
                                   sizeof(InjectionPointSharedState),
                                   injection_point_init_state,
-                                  &found);
+                                  &found, NULL);
 }
 
 /*
index 21e4ce6a74528f0b104c9232c8894f1d81301bc1..b9c45c0d41cfe77879760e14eb1a4cd058e68755 100644 (file)
@@ -21,7 +21,7 @@
 PG_MODULE_MAGIC;
 
 static void
-init_tranche(void *ptr)
+init_tranche(void *ptr, void *arg)
 {
    int        *tranche_id = (int *) ptr;
 
@@ -39,7 +39,7 @@ test_dsa_basic(PG_FUNCTION_ARGS)
    dsa_pointer p[100];
 
    tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
-                                   init_tranche, &found);
+                                   init_tranche, &found, NULL);
 
    a = dsa_create(*tranche_id);
    for (int i = 0; i < 100; i++)
@@ -80,7 +80,7 @@ test_dsa_resowners(PG_FUNCTION_ARGS)
    ResourceOwner childowner;
 
    tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
-                                   init_tranche, &found);
+                                   init_tranche, &found, NULL);
 
    /* Create DSA in parent resource owner */
    a = dsa_create(*tranche_id);
index 4cc2ccdac3f1123ee57afad5008b7be88047d91c..3e5f4f3cda1c063feb47673c3fd930485790d0c2 100644 (file)
@@ -44,10 +44,13 @@ static const dshash_parameters dsh_params = {
 };
 
 static void
-init_tdr_dsm(void *ptr)
+init_tdr_dsm(void *ptr, void *arg)
 {
    TestDSMRegistryStruct *dsm = (TestDSMRegistryStruct *) ptr;
 
+   if ((int) (intptr_t) arg != 5432)
+       elog(ERROR, "unexpected arg value %d", (int) (intptr_t) arg);
+
    LWLockInitialize(&dsm->lck, LWLockNewTrancheId("test_dsm_registry"));
    dsm->val = 0;
 }
@@ -60,7 +63,7 @@ tdr_attach_shmem(void)
    tdr_dsm = GetNamedDSMSegment("test_dsm_registry_dsm",
                                 sizeof(TestDSMRegistryStruct),
                                 init_tdr_dsm,
-                                &found);
+                                &found, (void *) (intptr_t) 5432);
 
    if (tdr_dsa == NULL)
        tdr_dsa = GetNamedDSA("test_dsm_registry_dsa", &found);