v2-0003-Change-the-signature-of-dynahash-s-alloc-function.patch
text/x-patch
Filename: v2-0003-Change-the-signature-of-dynahash-s-alloc-function.patch
Type: text/x-patch
Part: 2
Message:
Re: Shared hash table allocations
Patch
Format: format-patch
Series: patch v2-0003
Subject: Change the signature of dynahash's alloc function
| File | + | − |
|---|---|---|
| src/backend/storage/ipc/shmem.c | 13 | 2 |
| src/backend/utils/hash/dynahash.c | 27 | 25 |
| src/include/utils/hsearch.h | 2 | 1 |
From 684d8f9f9c22636c628af1dc5b5694b214e1d194 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 30 Mar 2026 18:20:58 +0300
Subject: [PATCH v2 3/8] 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 <tomas@vondra.me>
Discussion: https://www.postgresql.org/message-id/01ab1d41-3eda-4705-8bbd-af898f5007f1@iki.fi
---
src/backend/storage/ipc/shmem.c | 15 +++++++--
src/backend/utils/hash/dynahash.c | 52 ++++++++++++++++---------------
src/include/utils/hsearch.h | 3 +-
3 files changed, 42 insertions(+), 28 deletions(-)
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 3cc38450949..a6fd4c30059 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,14 @@ ShmemAllocNoError(Size size)
return ShmemAllocRaw(size, &allocated_size);
}
+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 +349,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..16cf103b8e4 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 to pass to allocator function */
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 cxt = (MemoryContext) alloc_arg;
+
+ Assert(MemoryContextIsValid(cxt));
+ return MemoryContextAllocExtended(cxt, 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..03bc1c171cd 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -41,7 +41,7 @@ typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize);
* 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 +80,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 to pass to allocator function */
/* Used if HASH_CONTEXT flag is set: */
MemoryContext hcxt; /* memory context to use for allocations */
/* Used if HASH_SHARED_MEM flag is set: */
--
2.47.3