From fcffd59c54aed417d3fef664c87a541a3c20ce4e Mon Sep 17 00:00:00 2001 From: Florents Tselai Date: Sun, 13 Jul 2025 13:13:51 +0300 Subject: [PATCH] Document DSM registry --- doc/src/sgml/xfunc.sgml | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 04bf919b3438..d8d419c60350 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3687,18 +3687,32 @@ LWLockRelease(AddinShmemInitLock); - Requesting Shared Memory After Startup + DSM Registry - There is another, more flexible method of reserving shared memory that - can be done after server startup and outside a - shmem_request_hook. To do so, each backend that will - use the shared memory should obtain a pointer to it by calling: - -void *GetNamedDSMSegment(const char *name, size_t size, + Another, more flexible way to reserve shared memory after server startup + (and outside a shmem_request_hook) is to use the dynamic shared memory (DSM) registry. + The registry maps library-defined string keys to DSM handles. + It supports creating named DSM segments with GetNamedDSMSegment, + named dynamic shared memory areas (DSAs) with GetNamedDSA, + and named hash tables backed by a DSA with GetNamedDSHash. + + + + Unlike shared memory reserved at server startup, there is no need to + acquire AddinShmemInitLock or otherwise take action + to avoid race conditions when reserving shared memory with these functions. + They ensure that only one backend allocates and initializes the memory structure and that all other + backends receive an appropriate pointer to the fully allocated and initialized segment, area or hash table. + + + + Consider for example this function to allocate a named DSM segment. + + void *GetNamedDSMSegment(const char *name, size_t size, void (*init_callback) (void *ptr), 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 @@ -3707,19 +3721,34 @@ void *GetNamedDSMSegment(const char *name, size_t size, backend. + The same logic applies to the other functions offered by the registry. + - Unlike shared memory reserved at server startup, there is no need to - acquire AddinShmemInitLock or otherwise take action - to avoid race conditions when reserving shared memory with - GetNamedDSMSegment. 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. + To allocate a named DSA, one can use + + dsa_area *GetNamedDSA(const char *name, bool *found) + + + Νote that this should be called at most once for a given DSA in each backend. + + + + To allocate a named hash table backed by shared memory, one can use + + dshash_table *GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found) + + + Also note that this should be called at most once for a given table in each backend. + + + + To monitor the allocations of the DSM registry + the pg_dsm_registry_allocations system view + documented in can be used. - A complete usage example of GetNamedDSMSegment can - be found in + A complete usage example of the DSM Registry and its facilities can be found in src/test/modules/test_dsm_registry/test_dsm_registry.c in the PostgreSQL source tree.