From: Heikki Linnakangas Date: Sun, 5 Apr 2026 23:12:48 +0000 (+0300) Subject: Move some code from shmem.c and shmem.h X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ef9bee29310fa519b1b0f01221fcf1c41a33679;p=thirdparty%2Fpostgresql.git Move some code from shmem.c and shmem.h A little refactoring in preparation for the next commit, to make the material changes in that commit more clear. Reviewed-by: Ashutosh Bapat Reviewed-by: Matthias van de Meent Discussion: https://www.postgresql.org/message-id/CAExHW5vM1bneLYfg0wGeAa=52UiJ3z4vKd3AJ72X8Fw6k3KKrg@mail.gmail.com --- diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c index 434e0643022..15b136ea29d 100644 --- a/src/backend/postmaster/launch_backend.c +++ b/src/backend/postmaster/launch_backend.c @@ -50,6 +50,7 @@ #include "storage/dsm.h" #include "storage/io_worker.h" #include "storage/pg_shmem.h" +#include "storage/shmem_internal.h" #include "tcop/backend_startup.h" #include "utils/memutils.h" diff --git a/src/backend/storage/ipc/Makefile b/src/backend/storage/ipc/Makefile index 9a07f6e1d92..f71653bbe48 100644 --- a/src/backend/storage/ipc/Makefile +++ b/src/backend/storage/ipc/Makefile @@ -22,6 +22,7 @@ OBJS = \ shm_mq.o \ shm_toc.o \ shmem.o \ + shmem_hash.o \ signalfuncs.o \ sinval.o \ sinvaladt.o \ diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 7aab5da3386..ca4e4727489 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -50,6 +50,7 @@ #include "storage/proc.h" #include "storage/procarray.h" #include "storage/procsignal.h" +#include "storage/shmem_internal.h" #include "storage/sinvaladt.h" #include "utils/guc.h" #include "utils/injection_point.h" diff --git a/src/backend/storage/ipc/meson.build b/src/backend/storage/ipc/meson.build index 9c1ca954d9d..b8c31e29967 100644 --- a/src/backend/storage/ipc/meson.build +++ b/src/backend/storage/ipc/meson.build @@ -14,6 +14,7 @@ backend_sources += files( 'shm_mq.c', 'shm_toc.c', 'shmem.c', + 'shmem_hash.c', 'signalfuncs.c', 'sinval.c', 'sinvaladt.c', diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 3cb51ad62f8..e91c47d4d97 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -70,6 +70,7 @@ #include "storage/lwlock.h" #include "storage/pg_shmem.h" #include "storage/shmem.h" +#include "storage/shmem_internal.h" #include "storage/spin.h" #include "utils/builtins.h" #include "utils/tuplestore.h" @@ -96,9 +97,6 @@ typedef struct ShmemAllocatorData #define ShmemIndexLock (&ShmemAllocator->index_lock) -static HTAB *shmem_hash_create(void *location, size_t size, bool found, - const char *name, int64 nelems, HASHCTL *infoP, int hash_flags); -static void *ShmemHashAlloc(Size size, void *alloc_arg); static void *ShmemAllocRaw(Size size, Size *allocated_size); /* shared memory global variables */ @@ -115,16 +113,6 @@ static bool firstNumaTouch = true; Datum pg_numa_available(PG_FUNCTION_ARGS); -/* - * A very simple allocator used to carve out different parts of a hash table - * from a previously allocated contiguous shared memory area. - */ -typedef struct shmem_hash_allocator -{ - char *next; /* start of free space in the area */ - char *end; /* end of the shmem area */ -} shmem_hash_allocator; - /* * InitShmemAllocator() --- set up basic pointers to shared memory. * @@ -257,29 +245,6 @@ ShmemAllocNoError(Size size) return ShmemAllocRaw(size, &allocated_size); } -/* - * ShmemHashAlloc -- alloc callback for shared memory hash tables - * - * Carve out the allocation from a pre-allocated region. All shared memory - * hash tables are initialized with HASH_FIXED_SIZE, so all the allocations - * happen upfront during initialization and no locking is required. - */ -static void * -ShmemHashAlloc(Size size, void *alloc_arg) -{ - shmem_hash_allocator *allocator = (shmem_hash_allocator *) alloc_arg; - void *result; - - size = MAXALIGN(size); - - if (allocator->end - allocator->next < size) - return NULL; - result = allocator->next; - allocator->next += size; - - return result; -} - /* * ShmemAllocRaw -- allocate align chunk and return allocated size * @@ -341,88 +306,6 @@ ShmemAddrIsValid(const void *addr) return (addr >= ShmemBase) && (addr < ShmemEnd); } -/* - * ShmemInitHash -- Create and initialize, or attach to, a - * shared memory hash table. - * - * We assume caller is doing some kind of synchronization - * so that two processes don't try to create/initialize the same - * table at once. (In practice, all creations are done in the postmaster - * process; child processes should always be attaching to existing tables.) - * - * nelems is the maximum number of hashtable entries. - * - * *infoP and hash_flags must specify at least the entry sizes and key - * comparison semantics (see hash_create()). Flag bits and values specific - * to shared-memory hash tables are added here, except that callers may - * choose to specify HASH_PARTITION. - * - * Note: before Postgres 9.0, this function returned NULL for some failure - * cases. Now, it always throws error instead, so callers need not check - * for NULL. - */ -HTAB * -ShmemInitHash(const char *name, /* table string name for shmem index */ - int64 nelems, /* size of the table */ - HASHCTL *infoP, /* info about key and bucket size */ - int hash_flags) /* info about infoP */ -{ - bool found; - size_t size; - void *location; - - size = hash_estimate_size(nelems, infoP->entrysize); - - /* look it up in the shmem index or allocate */ - location = ShmemInitStruct(name, size, &found); - - return shmem_hash_create(location, size, found, - name, nelems, infoP, hash_flags); -} - -/* - * Initialize or attach to a shared hash table in the given shmem region. - * - * This is extracted from ShmemInitHash() to allow InitShmemAllocator() to - * share the logic for bootstrapping the ShmemIndex hash table. - */ -static HTAB * -shmem_hash_create(void *location, size_t size, bool found, - const char *name, int64 nelems, HASHCTL *infoP, int hash_flags) -{ - shmem_hash_allocator allocator; - - /* - * Hash tables allocated in shared memory have a fixed directory and have - * all elements allocated upfront. We don't support growing because we'd - * need to grow the underlying shmem region with it. - * - * The shared memory allocator must be specified too. - */ - infoP->alloc = ShmemHashAlloc; - infoP->alloc_arg = NULL; - hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_FIXED_SIZE; - - /* - * if it already exists, attach to it rather than allocate and initialize - * new space - */ - if (!found) - { - allocator.next = (char *) location; - allocator.end = (char *) location + size; - infoP->alloc_arg = &allocator; - } - else - { - /* Pass location of hashtable header to hash_create */ - infoP->hctl = (HASHHDR *) location; - hash_flags |= HASH_ATTACH; - } - - return hash_create(name, nelems, infoP, hash_flags); -} - /* * ShmemInitStruct -- Create/attach to a structure in shared memory. * diff --git a/src/backend/storage/ipc/shmem_hash.c b/src/backend/storage/ipc/shmem_hash.c new file mode 100644 index 00000000000..1ca4a321c0f --- /dev/null +++ b/src/backend/storage/ipc/shmem_hash.c @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------- + * + * shmem_hash.c + * hash table implementation in shared memory + * + * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * A shared memory hash table implementation on top of the named, fixed-size + * shared memory areas managed by shmem.c. Each hash table has its own free + * list, so hash buckets can be reused when an item is deleted. + * + * IDENTIFICATION + * src/backend/storage/ipc/shmem_hash.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "storage/shmem.h" +#include "storage/shmem_internal.h" + +/* + * A very simple allocator used to carve out different parts of a hash table + * from a previously allocated contiguous shared memory area. + */ +typedef struct shmem_hash_allocator +{ + char *next; /* start of free space in the area */ + char *end; /* end of the shmem area */ +} shmem_hash_allocator; + +static void *ShmemHashAlloc(Size size, void *alloc_arg); + +/* + * ShmemInitHash -- Create and initialize, or attach to, a + * shared memory hash table. + * + * We assume caller is doing some kind of synchronization + * so that two processes don't try to create/initialize the same + * table at once. (In practice, all creations are done in the postmaster + * process; child processes should always be attaching to existing tables.) + * + * nelems is the maximum number of hashtable entries. + * + * *infoP and hash_flags must specify at least the entry sizes and key + * comparison semantics (see hash_create()). Flag bits and values specific + * to shared-memory hash tables are added here, except that callers may + * choose to specify HASH_PARTITION. + * + * Note: before Postgres 9.0, this function returned NULL for some failure + * cases. Now, it always throws error instead, so callers need not check + * for NULL. + */ +HTAB * +ShmemInitHash(const char *name, /* table string name for shmem index */ + int64 nelems, /* size of the table */ + HASHCTL *infoP, /* info about key and bucket size */ + int hash_flags) /* info about infoP */ +{ + bool found; + size_t size; + void *location; + + size = hash_estimate_size(nelems, infoP->entrysize); + + /* look it up in the shmem index or allocate */ + location = ShmemInitStruct(name, size, &found); + + return shmem_hash_create(location, size, found, + name, nelems, infoP, hash_flags); +} + +/* + * Initialize or attach to a shared hash table in the given shmem region. + * + * This is extracted from ShmemInitHash() to allow InitShmemAllocator() to + * share the logic for bootstrapping the ShmemIndex hash table. + */ +HTAB * +shmem_hash_create(void *location, size_t size, bool found, + const char *name, int64 nelems, HASHCTL *infoP, int hash_flags) +{ + shmem_hash_allocator allocator; + + /* + * Hash tables allocated in shared memory have a fixed directory and have + * all elements allocated upfront. We don't support growing because we'd + * need to grow the underlying shmem region with it. + * + * The shared memory allocator must be specified too. + */ + infoP->alloc = ShmemHashAlloc; + infoP->alloc_arg = NULL; + hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_FIXED_SIZE; + + /* + * if it already exists, attach to it rather than allocate and initialize + * new space + */ + if (!found) + { + allocator.next = (char *) location; + allocator.end = (char *) location + size; + infoP->alloc_arg = &allocator; + } + else + { + /* Pass location of hashtable header to hash_create */ + infoP->hctl = (HASHHDR *) location; + hash_flags |= HASH_ATTACH; + } + + return hash_create(name, nelems, infoP, hash_flags); +} + +/* + * ShmemHashAlloc -- alloc callback for shared memory hash tables + * + * Carve out the allocation from a pre-allocated region. All shared memory + * hash tables are initialized with HASH_FIXED_SIZE, so all the allocations + * happen upfront during initialization and no locking is required. + */ +static void * +ShmemHashAlloc(Size size, void *alloc_arg) +{ + shmem_hash_allocator *allocator = (shmem_hash_allocator *) alloc_arg; + void *result; + + size = MAXALIGN(size); + + if (allocator->end - allocator->next < size) + return NULL; + result = allocator->next; + allocator->next += size; + + return result; +} diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index a2eb499d63c..81d05381f8f 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -3,6 +3,11 @@ * shmem.h * shared memory management structures * + * This file contains public functions for other core subsystems and + * extensions to allocate shared memory. Internal functions for the shmem + * allocator itself and hooking it to the rest of the system are in + * shmem_internal.h + * * Historical note: * A long time ago, Postgres' shared memory region was allowed to be mapped * at a different address in each process, and shared memory "pointers" were @@ -25,36 +30,20 @@ /* shmem.c */ -typedef struct PGShmemHeader PGShmemHeader; /* avoid including - * storage/pg_shmem.h here */ -extern void InitShmemAllocator(PGShmemHeader *seghdr); extern void *ShmemAlloc(Size size); extern void *ShmemAllocNoError(Size size); extern bool ShmemAddrIsValid(const void *addr); -extern HTAB *ShmemInitHash(const char *name, int64 nelems, - HASHCTL *infoP, int hash_flags); extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); extern PGDLLIMPORT Size pg_get_shmem_pagesize(void); +/* shmem_hash.c */ +extern HTAB *ShmemInitHash(const char *name, int64 nelems, + HASHCTL *infoP, int hash_flags); + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); -/* size constants for the shmem index table */ - /* max size of data structure string name */ -#define SHMEM_INDEX_KEYSIZE (48) - /* max number of named shmem structures and hash tables */ -#define SHMEM_INDEX_SIZE (256) - -/* this is a hash bucket in the shmem index table */ -typedef struct -{ - char key[SHMEM_INDEX_KEYSIZE]; /* string name */ - void *location; /* location in shared mem */ - Size size; /* # bytes requested for the structure */ - Size allocated_size; /* # bytes actually allocated */ -} ShmemIndexEnt; - #endif /* SHMEM_H */ diff --git a/src/include/storage/shmem_internal.h b/src/include/storage/shmem_internal.h new file mode 100644 index 00000000000..e0638135639 --- /dev/null +++ b/src/include/storage/shmem_internal.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------------- + * + * shmem_internal.h + * Internal functions related to shmem allocation + * + * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/shmem_internal.h + * + *------------------------------------------------------------------------- + */ +#ifndef SHMEM_INTERNAL_H +#define SHMEM_INTERNAL_H + +#include "storage/shmem.h" +#include "utils/hsearch.h" + +typedef struct PGShmemHeader PGShmemHeader; /* avoid including + * storage/pg_shmem.h here */ +extern void InitShmemAllocator(PGShmemHeader *seghdr); + +extern HTAB *shmem_hash_create(void *location, size_t size, bool found, + const char *name, int64 nelems, HASHCTL *infoP, int hash_flags); + +/* size constants for the shmem index table */ + /* max size of data structure string name */ +#define SHMEM_INDEX_KEYSIZE (48) + /* max number of named shmem structures and hash tables */ +#define SHMEM_INDEX_SIZE (256) + +/* this is a hash bucket in the shmem index table */ +typedef struct +{ + char key[SHMEM_INDEX_KEYSIZE]; /* string name */ + void *location; /* location in shared mem */ + Size size; /* # bytes requested for the structure */ + Size allocated_size; /* # bytes actually allocated */ +} ShmemIndexEnt; + +#endif /* SHMEM_INTERNAL_H */