From f8dace7c732320f7c61f764b27366e9922b59436 Mon Sep 17 00:00:00 2001 From: Zsolt Parragi Date: Thu, 11 Dec 2025 22:54:06 +0000 Subject: [PATCH v4 1/1] Pass name and callback data to GetNamedDSMSegment init callback Modify the signature of GetNamedDSMSegment to pass the segment name and an additional init_callback_arg to the init_callback function. This allows the callback to differentiate initialization logic based on the segment's name and additional context. Author: zsolt.parragi@percona.com Reviewed-by: Nathan Bossart Reviewed-by: Sami Imseih Discussion: https://postgr.es/m/CAN4CZFMjh8TrT9ZhWgjVTzBDkYZi2a84BnZ8bM%2BfLPuq7Cirzg%40mail.gmail.com --- contrib/pg_prewarm/autoprewarm.c | 5 +++-- doc/src/sgml/xfunc.sgml | 15 ++++++++++----- src/backend/storage/ipc/dsm_registry.c | 10 ++++++---- src/include/storage/dsm_registry.h | 3 ++- .../modules/injection_points/injection_points.c | 5 +++-- src/test/modules/test_dsa/test_dsa.c | 16 ++++++++++------ .../test_dsm_registry/test_dsm_registry.c | 3 ++- 7 files changed, 36 insertions(+), 21 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index 5ba1240d51f..2ff24dad167 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -858,11 +858,11 @@ autoprewarm_dump_now(PG_FUNCTION_ARGS) } static void -apw_init_state(void *ptr) +apw_init_state(void *ptr, const char *name, void *arg) { AutoPrewarmSharedState *state = (AutoPrewarmSharedState *) ptr; - LWLockInitialize(&state->lock, LWLockNewTrancheId("autoprewarm")); + LWLockInitialize(&state->lock, LWLockNewTrancheId(name)); state->bgworker_pid = InvalidPid; state->pid_using_dumpfile = InvalidPid; } @@ -880,6 +880,7 @@ apw_init_shmem(void) apw_state = GetNamedDSMSegment("autoprewarm", sizeof(AutoPrewarmSharedState), apw_init_state, + NULL, &found); return found; diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 7c76ab8c349..5a56e653e38 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3696,15 +3696,20 @@ LWLockRelease(AddinShmemInitLock); use the shared memory should obtain a pointer to it by calling: void *GetNamedDSMSegment(const char *name, size_t size, - void (*init_callback) (void *ptr), + void (*init_callback) (void *ptr, const char *name, void *init_callback_arg), + void *init_callback_arg, bool *found) 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 - init_callback 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. + init_callback callback function. The + init_callback_arg parameter is passed to the callback + function, allowing additional context to be provided during initialization. + The name parameter is passed to the callback to uniquely + identify the segment, enabling different initialization logic for different segments. + 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. diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c index 66240318e83..53e17e4f86e 100644 --- a/src/backend/storage/ipc/dsm_registry.c +++ b/src/backend/storage/ipc/dsm_registry.c @@ -179,12 +179,14 @@ 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. + * This routine returns the address of the segment. The init_callback is used to + * initialize the segment when it is first created. An optional callback_arg is + * passed to the init_callback to provide additional context during initialization. */ void * GetNamedDSMSegment(const char *name, size_t size, - void (*init_callback) (void *ptr), bool *found) + void (*init_callback) (void *ptr, const char *name, void *init_callback_arg), + void *init_callback_arg, bool *found) { 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), name, init_callback_arg); dsm_pin_segment(seg); dsm_pin_mapping(seg); diff --git a/src/include/storage/dsm_registry.h b/src/include/storage/dsm_registry.h index 4871ed509eb..6e4bd3e2cb3 100644 --- a/src/include/storage/dsm_registry.h +++ b/src/include/storage/dsm_registry.h @@ -16,7 +16,8 @@ #include "lib/dshash.h" extern void *GetNamedDSMSegment(const char *name, size_t size, - void (*init_callback) (void *ptr), + void (*init_callback) (void *ptr, const char *name, void *init_callback_arg), + void *init_callback_arg, bool *found); extern dsa_area *GetNamedDSA(const char *name, bool *found); extern dshash_table *GetNamedDSHash(const char *name, diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c index 417b61f31c5..e7c8cdddbf2 100644 --- a/src/test/modules/injection_points/injection_points.c +++ b/src/test/modules/injection_points/injection_points.c @@ -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, const char *name, 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, "injection_points", NULL); } LWLockRelease(AddinShmemInitLock); @@ -179,6 +179,7 @@ injection_init_shmem(void) inj_state = GetNamedDSMSegment("injection_points", sizeof(InjectionPointSharedState), injection_point_init_state, + NULL, &found); } diff --git a/src/test/modules/test_dsa/test_dsa.c b/src/test/modules/test_dsa/test_dsa.c index 21e4ce6a745..fc41ce9bdb8 100644 --- a/src/test/modules/test_dsa/test_dsa.c +++ b/src/test/modules/test_dsa/test_dsa.c @@ -21,11 +21,15 @@ PG_MODULE_MAGIC; static void -init_tranche(void *ptr) +init_tranche(void *ptr, const char *name, void *arg) { int *tranche_id = (int *) ptr; - *tranche_id = LWLockNewTrancheId("test_dsa"); + /* Verify arg if given */ + if (arg && strcmp(name, (char *) arg) != 0) + elog(ERROR, "didn't receive expected arg data"); + + *tranche_id = LWLockNewTrancheId(name); } /* Test basic DSA functionality */ @@ -38,8 +42,8 @@ test_dsa_basic(PG_FUNCTION_ARGS) dsa_area *a; dsa_pointer p[100]; - tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int), - init_tranche, &found); + tranche_id = GetNamedDSMSegment("test_dsa_basic", sizeof(int), + init_tranche, "test_dsa_basic", &found); a = dsa_create(*tranche_id); for (int i = 0; i < 100; i++) @@ -79,8 +83,8 @@ test_dsa_resowners(PG_FUNCTION_ARGS) ResourceOwner oldowner; ResourceOwner childowner; - tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int), - init_tranche, &found); + tranche_id = GetNamedDSMSegment("test_dsa_resowners", sizeof(int), + init_tranche, "test_dsa_resowners", &found); /* Create DSA in parent resource owner */ a = dsa_create(*tranche_id); diff --git a/src/test/modules/test_dsm_registry/test_dsm_registry.c b/src/test/modules/test_dsm_registry/test_dsm_registry.c index 4cc2ccdac3f..47330b22a7f 100644 --- a/src/test/modules/test_dsm_registry/test_dsm_registry.c +++ b/src/test/modules/test_dsm_registry/test_dsm_registry.c @@ -44,7 +44,7 @@ static const dshash_parameters dsh_params = { }; static void -init_tdr_dsm(void *ptr) +init_tdr_dsm(void *ptr, const char *name, void *arg) { TestDSMRegistryStruct *dsm = (TestDSMRegistryStruct *) ptr; @@ -60,6 +60,7 @@ tdr_attach_shmem(void) tdr_dsm = GetNamedDSMSegment("test_dsm_registry_dsm", sizeof(TestDSMRegistryStruct), init_tdr_dsm, + NULL, &found); if (tdr_dsa == NULL) -- 2.43.0