]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Change the signature of dynahash's alloc function
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 31 Mar 2026 13:55:03 +0000 (16:55 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 31 Mar 2026 13:55:03 +0000 (16:55 +0300)
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
src/backend/utils/hash/dynahash.c
src/include/utils/hsearch.h

index 3cc38450949f404ad0ec12e27ac625553a7e3abd..0e49debaaaca2eee360ce1e8965738b4513efedd 100644 (file)
@@ -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 */
index af3f7142afbc829b7927d1b82380021c10228c67..f8317add68fa83a88256d011ff025ac73a6cab97 100644 (file)
@@ -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;
index 0721849c036bc62caf7fe9ad9dd1ad6f5f6b9706..337b2e446259b5aa89a63573e1054647dc96996f 100644 (file)
@@ -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: */