summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2022-10-14 15:55:56 +0000
committerTom Lane2022-10-14 15:55:56 +0000
commit9c911ec065df0f660e3add65d986f95928914375 (patch)
tree2c352600e5078023ba3ca93c45343deb6841d8ba
parent1b11561cc1de7596f6f7cb750743af94b9d168f7 (diff)
Make some minor improvements in memory-context infrastructure.
We lack a version of repalloc() that supports MCXT_ALLOC_NO_OOM semantics, so invent repalloc_extended() with the usual set of flags. repalloc_huge() becomes a legacy wrapper for that. Also, fix dynahash.c so that it can support HASH_ENTER_NULL requests when using the default palloc-based allocator. The only reason it didn't do that already was the lack of the MCXT_ALLOC_NO_OOM option when that code was written, ages ago. While here, simplify a few overcomplicated tests in mcxt.c. Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/utils/hash/dynahash.c13
-rw-r--r--src/backend/utils/mmgr/mcxt.c83
-rw-r--r--src/include/utils/palloc.h2
3 files changed, 56 insertions, 42 deletions
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 3babde8d704..4f629588835 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -289,7 +289,8 @@ static void *
DynaHashAlloc(Size size)
{
Assert(MemoryContextIsValid(CurrentDynaHashCxt));
- return MemoryContextAlloc(CurrentDynaHashCxt, size);
+ return MemoryContextAllocExtended(CurrentDynaHashCxt, size,
+ MCXT_ALLOC_NO_OOM);
}
@@ -939,9 +940,7 @@ calc_bucket(HASHHDR *hctl, uint32 hash_val)
*
* HASH_ENTER will normally ereport a generic "out of memory" error if
* it is unable to create a new entry. The HASH_ENTER_NULL operation is
- * the same except it will return NULL if out of memory. Note that
- * HASH_ENTER_NULL cannot be used with the default palloc-based allocator,
- * since palloc internally ereports on out-of-memory.
+ * the same except it will return NULL if out of memory.
*
* If foundPtr isn't NULL, then *foundPtr is set true if we found an
* existing entry in the table, false otherwise. This is needed in the
@@ -1084,12 +1083,8 @@ hash_search_with_hash_value(HTAB *hashp,
}
return NULL;
- case HASH_ENTER_NULL:
- /* ENTER_NULL does not work with palloc-based allocator */
- Assert(hashp->alloc != DynaHashAlloc);
- /* FALL THRU */
-
case HASH_ENTER:
+ case HASH_ENTER_NULL:
/* Return existing element if found, else create one */
if (currBucket != NULL)
return (void *) ELEMENTKEY(currBucket);
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index b1a3c748305..012517be5c5 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -1114,8 +1114,8 @@ MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
AssertArg(MemoryContextIsValid(context));
AssertNotInCriticalSection(context);
- if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
- ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
+ if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
+ AllocSizeIsValid(size)))
elog(ERROR, "invalid memory alloc request size %zu", size);
context->isReset = false;
@@ -1269,8 +1269,8 @@ palloc_extended(Size size, int flags)
AssertArg(MemoryContextIsValid(context));
AssertNotInCriticalSection(context);
- if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
- ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
+ if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
+ AllocSizeIsValid(size)))
elog(ERROR, "invalid memory alloc request size %zu", size);
context->isReset = false;
@@ -1352,6 +1352,50 @@ repalloc(void *pointer, Size size)
}
/*
+ * repalloc_extended
+ * Adjust the size of a previously allocated chunk,
+ * with HUGE and NO_OOM options.
+ */
+void *
+repalloc_extended(void *pointer, Size size, int flags)
+{
+#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
+ MemoryContext context = GetMemoryChunkContext(pointer);
+#endif
+ void *ret;
+
+ if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
+ AllocSizeIsValid(size)))
+ elog(ERROR, "invalid memory alloc request size %zu", size);
+
+ AssertNotInCriticalSection(context);
+
+ /* isReset must be false already */
+ Assert(!context->isReset);
+
+ ret = MCXT_METHOD(pointer, realloc) (pointer, size);
+ if (unlikely(ret == NULL))
+ {
+ if ((flags & MCXT_ALLOC_NO_OOM) == 0)
+ {
+ MemoryContext cxt = GetMemoryChunkContext(pointer);
+
+ MemoryContextStats(TopMemoryContext);
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed on request of size %zu in memory context \"%s\".",
+ size, cxt->name)));
+ }
+ return NULL;
+ }
+
+ VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
+
+ return ret;
+}
+
+/*
* MemoryContextAllocHuge
* Allocate (possibly-expansive) space within the specified context.
*
@@ -1394,35 +1438,8 @@ MemoryContextAllocHuge(MemoryContext context, Size size)
void *
repalloc_huge(void *pointer, Size size)
{
-#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
- MemoryContext context = GetMemoryChunkContext(pointer);
-#endif
- void *ret;
-
- if (!AllocHugeSizeIsValid(size))
- elog(ERROR, "invalid memory alloc request size %zu", size);
-
- AssertNotInCriticalSection(context);
-
- /* isReset must be false already */
- Assert(!context->isReset);
-
- ret = MCXT_METHOD(pointer, realloc) (pointer, size);
- if (unlikely(ret == NULL))
- {
- MemoryContext cxt = GetMemoryChunkContext(pointer);
-
- MemoryContextStats(TopMemoryContext);
- ereport(ERROR,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory"),
- errdetail("Failed on request of size %zu in memory context \"%s\".",
- size, cxt->name)));
- }
-
- VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
-
- return ret;
+ /* this one seems not worth its own implementation */
+ return repalloc_extended(pointer, size, MCXT_ALLOC_HUGE);
}
/*
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index a0b62aa7b0c..8eee0e29385 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -78,6 +78,8 @@ extern void *palloc(Size size);
extern void *palloc0(Size size);
extern void *palloc_extended(Size size, int flags);
extern pg_nodiscard void *repalloc(void *pointer, Size size);
+extern pg_nodiscard void *repalloc_extended(void *pointer,
+ Size size, int flags);
extern void pfree(void *pointer);
/*