From: Heikki Linnakangas Date: Tue, 31 Mar 2026 13:55:03 +0000 (+0300) Subject: Change the signature of dynahash's alloc function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b424e3108e4745ba7d37e358a1177911fa5a5ad;p=thirdparty%2Fpostgresql.git Change the signature of dynahash's alloc function Instead of passing the current memory context to the alloc function via a shared variable, pass it directly as an argument. Reviewed-by: Tomas Vondra Discussion: https://www.postgresql.org/message-id/01ab1d41-3eda-4705-8bbd-af898f5007f1@iki.fi --- diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 3cc38450949..0e49debaaac 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -100,6 +100,7 @@ typedef struct ShmemAllocatorData #define ShmemIndexLock (&ShmemAllocator->index_lock) +static void *ShmemHashAlloc(Size size, void *alloc_arg); static void *ShmemAllocRaw(Size size, Size *allocated_size); /* shared memory global variables */ @@ -184,7 +185,8 @@ InitShmemAllocator(PGShmemHeader *seghdr) info.keysize = SHMEM_INDEX_KEYSIZE; info.entrysize = sizeof(ShmemIndexEnt); info.dsize = info.max_dsize = hash_select_dirsize(SHMEM_INDEX_SIZE); - info.alloc = ShmemAllocNoError; + info.alloc = ShmemHashAlloc; + info.alloc_arg = NULL; hash_flags = HASH_ELEM | HASH_STRINGS | HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE; if (!IsUnderPostmaster) { @@ -233,6 +235,15 @@ ShmemAllocNoError(Size size) return ShmemAllocRaw(size, &allocated_size); } +/* Alloc callback for shared memory hash tables */ +static void * +ShmemHashAlloc(Size size, void *alloc_arg) +{ + Size allocated_size; + + return ShmemAllocRaw(size, &allocated_size); +} + /* * ShmemAllocRaw -- allocate align chunk and return allocated size * @@ -339,7 +350,8 @@ ShmemInitHash(const char *name, /* table string name for shmem index */ * The shared memory allocator must be specified too. */ infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size); - infoP->alloc = ShmemAllocNoError; + infoP->alloc = ShmemHashAlloc; + infoP->alloc_arg = NULL; hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE; /* look it up in the shmem index */ diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index af3f7142afb..f8317add68f 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -224,6 +224,7 @@ struct HTAB HashCompareFunc match; /* key comparison function */ HashCopyFunc keycopy; /* key copying function */ HashAllocFunc alloc; /* memory allocator */ + void *alloc_arg; /* opaque argument passed to allocator */ MemoryContext hcxt; /* memory context if default allocator used */ char *tabname; /* table name (for error messages) */ bool isshared; /* true if table is in shared memory */ @@ -264,7 +265,7 @@ struct HTAB /* * Private function prototypes */ -static void *DynaHashAlloc(Size size); +static void *DynaHashAlloc(Size size, void *alloc_arg); static HASHSEGMENT seg_alloc(HTAB *hashp); static bool element_alloc(HTAB *hashp, int nelem, int freelist_idx); static bool dir_realloc(HTAB *hashp); @@ -287,14 +288,13 @@ static bool has_seq_scans(HTAB *hashp); /* * memory allocation support */ -static MemoryContext CurrentDynaHashCxt = NULL; - static void * -DynaHashAlloc(Size size) +DynaHashAlloc(Size size, void *alloc_arg) { - Assert(MemoryContextIsValid(CurrentDynaHashCxt)); - return MemoryContextAllocExtended(CurrentDynaHashCxt, size, - MCXT_ALLOC_NO_OOM); + MemoryContext hcxt = (MemoryContext) alloc_arg; + + Assert(MemoryContextIsValid(hcxt)); + return MemoryContextAllocExtended(hcxt, size, MCXT_ALLOC_NO_OOM); } @@ -355,6 +355,7 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags) { HTAB *hashp; HASHHDR *hctl; + MemoryContext hcxt; /* * Hash tables now allocate space for key and data, but you have to say @@ -377,22 +378,21 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags) if (flags & HASH_SHARED_MEM) { /* Set up to allocate the hash header */ - CurrentDynaHashCxt = TopMemoryContext; + hcxt = TopMemoryContext; } else { /* Create the hash table's private memory context */ if (flags & HASH_CONTEXT) - CurrentDynaHashCxt = info->hcxt; + hcxt = info->hcxt; else - CurrentDynaHashCxt = TopMemoryContext; - CurrentDynaHashCxt = AllocSetContextCreate(CurrentDynaHashCxt, - "dynahash", - ALLOCSET_DEFAULT_SIZES); + hcxt = TopMemoryContext; + hcxt = AllocSetContextCreate(hcxt, "dynahash", + ALLOCSET_DEFAULT_SIZES); } /* Initialize the hash header, plus a copy of the table name */ - hashp = (HTAB *) MemoryContextAlloc(CurrentDynaHashCxt, + hashp = (HTAB *) MemoryContextAlloc(hcxt, sizeof(HTAB) + strlen(tabname) + 1); MemSet(hashp, 0, sizeof(HTAB)); @@ -401,7 +401,7 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags) /* If we have a private context, label it with hashtable's name */ if (!(flags & HASH_SHARED_MEM)) - MemoryContextSetIdentifier(CurrentDynaHashCxt, hashp->tabname); + MemoryContextSetIdentifier(hcxt, hashp->tabname); /* * Select the appropriate hash function (see comments at head of file). @@ -473,9 +473,15 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags) /* And select the entry allocation function, too. */ if (flags & HASH_ALLOC) + { hashp->alloc = info->alloc; + hashp->alloc_arg = info->alloc_arg; + } else + { hashp->alloc = DynaHashAlloc; + hashp->alloc_arg = hcxt; + } if (flags & HASH_SHARED_MEM) { @@ -504,13 +510,13 @@ hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags) /* setup hash table defaults */ hashp->hctl = NULL; hashp->dir = NULL; - hashp->hcxt = CurrentDynaHashCxt; + hashp->hcxt = hcxt; hashp->isshared = false; } if (!hashp->hctl) { - hashp->hctl = (HASHHDR *) hashp->alloc(sizeof(HASHHDR)); + hashp->hctl = (HASHHDR *) hashp->alloc(sizeof(HASHHDR), hashp->alloc_arg); if (!hashp->hctl) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), @@ -732,9 +738,8 @@ init_htab(HTAB *hashp, int64 nelem) /* Allocate a directory */ if (!(hashp->dir)) { - CurrentDynaHashCxt = hashp->hcxt; hashp->dir = (HASHSEGMENT *) - hashp->alloc(hctl->dsize * sizeof(HASHSEGMENT)); + hashp->alloc(hctl->dsize * sizeof(HASHSEGMENT), hashp->alloc_arg); if (!hashp->dir) return false; } @@ -1636,8 +1641,7 @@ dir_realloc(HTAB *hashp) new_dirsize = new_dsize * sizeof(HASHSEGMENT); old_p = hashp->dir; - CurrentDynaHashCxt = hashp->hcxt; - p = (HASHSEGMENT *) hashp->alloc((Size) new_dirsize); + p = (HASHSEGMENT *) hashp->alloc((Size) new_dirsize, hashp->alloc_arg); if (p != NULL) { @@ -1662,8 +1666,7 @@ seg_alloc(HTAB *hashp) { HASHSEGMENT segp; - CurrentDynaHashCxt = hashp->hcxt; - segp = (HASHSEGMENT) hashp->alloc(sizeof(HASHBUCKET) * HASH_SEGSIZE); + segp = (HASHSEGMENT) hashp->alloc(sizeof(HASHBUCKET) * HASH_SEGSIZE, hashp->alloc_arg); if (!segp) return NULL; @@ -1703,8 +1706,7 @@ element_alloc(HTAB *hashp, int nelem, int freelist_idx) #endif /* Allocate the memory. */ - CurrentDynaHashCxt = hashp->hcxt; - allocedBlock = hashp->alloc(requestSize); + allocedBlock = hashp->alloc(requestSize, hashp->alloc_arg); if (!allocedBlock) return false; diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index 0721849c036..337b2e44625 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -37,11 +37,10 @@ typedef int (*HashCompareFunc) (const void *key1, const void *key2, typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize); /* - * Space allocation function for a hashtable --- designed to match malloc(). - * Note: there is no free function API; can't destroy a hashtable unless you - * use the default allocator. + * Space allocation function for a hashtable. Note: there is no free function + * API; can't destroy a hashtable unless you use the default allocator. */ -typedef void *(*HashAllocFunc) (Size request); +typedef void *(*HashAllocFunc) (Size request, void *alloc_arg); /* * HASHELEMENT is the private part of a hashtable entry. The caller's data @@ -80,6 +79,7 @@ typedef struct HASHCTL HashCopyFunc keycopy; /* key copying function */ /* Used if HASH_ALLOC flag is set: */ HashAllocFunc alloc; /* memory allocator */ + void *alloc_arg; /* opaque argument passed to allocator */ /* Used if HASH_CONTEXT flag is set: */ MemoryContext hcxt; /* memory context to use for allocations */ /* Used if HASH_SHARED_MEM flag is set: */