On Fri, Jan 30, 2015 at 12:29 AM, Robert Haas <robertmh...@gmail.com> wrote:
> On Wed, Jan 28, 2015 at 9:34 AM, Michael Paquier
> <michael.paqu...@gmail.com> wrote:
>> As a result of all the comments on this thread, here are 3 patches
>> implementing incrementally the different ideas from everybody:
>> 1) 0001 modifies aset.c to return unconditionally NULL in case of an
>> OOM instead of reporting an error. All the OOM error reports are moved
>> to mcxt.c (MemoryContextAlloc* and palloc*)
>
> This seems like a good idea, but I think it's pretty clear that the
> MemoryContextStats(TopMemoryContext) calls ought to move along with
> the OOM error report.  The stats are basically another kind of
> error-case output, and the whole point here is that the caller wants
> to have control of what happens when malloc fails.  Committed that
> way.
Thanks for the clarifications!

>> 2) 0002 adds the noerror routines for frontend and backend.
>
> We don't have consensus on this name; as I read it, Andres and I are
> both strongly opposed to it.  Instead of continuing to litigate that
> point, I'd like to propose that we just leave this out.  We are
> unlikely to have so many callers who need the no-oom-error behavior to
> justify adding a bunch of convenience functions --- and if that does
> happen, we can resume arguing about the naming then.  For now, let's
> just say that if you want that behavior, you should use
> MemoryContextAllocExtended(CurrentMemoryContext, ...).
Fine for me, any extension or module can still define their own
equivalent of palloc_noerror or whatever using the Extended interface.

>> 3) 0003 adds MemoryContextAllocExtended
> I recommend we leave the existing MemoryContextAlloc* functions alone
> and add a new MemoryContextAllocExtended() function *in addition*.  I
> think the reason we have multiple copies of this code is because they
> are sufficiently hot to make the effect of a few extra CPU
> instructions potentially material.  By having separate copies of the
> code, we avoid introducing extra branches.
Yes, this refactoring was good for testing actually... I have changed
the flags as follows, appending MCXT_ seemed cleaner after waking up
this morning:
+#define MCXT_ALLOC_HUGE                   0x01    /* huge allocation */
+#define MCXT_ALLOC_NO_OOM              0x02    /* no failure if
out-of-memory */
+#define MCXT_ALLOC_ZERO                    0x04    /* clear allocated
memory using
+
          * MemSetAligned */
+#define MCXT_ALLOC_ZERO_ALIGNED   0x08    /* clear allocated memory using
+
          * MemSetLoop */
-- 
Michael
From b5d43fd598e177c402c354f0b76aca52305463c6 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@otacoo.com>
Date: Fri, 30 Jan 2015 12:56:21 +0900
Subject: [PATCH] Create MemoryContextAllocExtended central routine for memory
 allocation

This new routine is the central point can be used by extensions and
third-part utilities in a more extensive way than the already present
routines MemoryContextAlloc, one of the control flags introduced being
particularly useful to avoid out-of-memory errors when allocation request
cannot be completed correctly.
---
 src/backend/utils/mmgr/mcxt.c | 57 +++++++++++++++++++++++++++++++++++++++++++
 src/include/utils/palloc.h    | 12 +++++++++
 2 files changed, 69 insertions(+)

diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index c62922a..26579e3 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -603,6 +603,63 @@ MemoryContextCreate(NodeTag tag, Size size,
 }
 
 /*
+ * MemoryContextAllocExtended
+ *		Allocate space within the specified context using flag options
+ *		defined by caller.
+ *
+ * The following control flags can be used:
+ * - MCXT_ALLOC_HUGE, allocate possibly-expansive space. this is
+ *   equivalent to MemoryContextAllocHuge.
+ * - MCXT_ALLOC_NO_OOM, not fail in case of allocation request
+ *   failure and return NULL.
+ * - MCXT_ALLOC_ZERO, clear allocated memory using MemSetAligned.
+ * - MCXT_ALLOC_ZERO_ALIGNED, clear memory using MemSetLoop.
+ */
+void *
+MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
+{
+	void	   *ret;
+
+	AssertArg(MemoryContextIsValid(context));
+	AssertNotInCriticalSection(context);
+
+	if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
+		!AllocSizeIsValid(size))
+		elog(ERROR, "invalid memory alloc request size %zu", size);
+
+	context->isReset = false;
+
+	ret = (*context->methods->alloc) (context, size);
+	if ((flags & MCXT_ALLOC_NO_OOM) == 0 && ret == NULL)
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory"),
+				 errdetail("Failed on request of size %zu.", size)));
+	}
+
+	if (ret == NULL)
+		return NULL;
+
+	VALGRIND_MEMPOOL_ALLOC(context, ret, size);
+
+	/*
+	 * MemSetAligned and MemSetLoop should not be called in the same
+	 * context (see c.h for more details).
+	 */
+	Assert((flags & MCXT_ALLOC_ZERO) == 0 ||
+		   (flags & MCXT_ALLOC_ZERO_ALIGNED) == 0);
+
+	if ((flags & MCXT_ALLOC_ZERO) != 0)
+		MemSetAligned(ret, 0, size);
+	if ((flags & MCXT_ALLOC_ZERO_ALIGNED) != 0)
+		MemSetLoop(ret, 0, size);
+
+	return ret;
+}
+
+/*
  * MemoryContextAlloc
  *		Allocate space within the specified context.
  *
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index ca03f2b..34acabe 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -43,8 +43,20 @@ typedef struct MemoryContextData *MemoryContext;
 extern PGDLLIMPORT MemoryContext CurrentMemoryContext;
 
 /*
+ * Control flags for options of MemoryContextAllocExtended()
+ */
+#define MCXT_ALLOC_HUGE			0x01	/* huge allocation */
+#define MCXT_ALLOC_NO_OOM		0x02	/* no failure if out-of-memory */
+#define MCXT_ALLOC_ZERO			0x04	/* clear allocated memory using
+										 * MemSetAligned */
+#define MCXT_ALLOC_ZERO_ALIGNED	0x08	/* clear allocated memory using
+										 * MemSetLoop */
+
+/*
  * Fundamental memory-allocation operations (more are in utils/memutils.h)
  */
+extern void *MemoryContextAllocExtended(MemoryContext context,
+										Size size, int flags);
 extern void *MemoryContextAlloc(MemoryContext context, Size size);
 extern void *MemoryContextAllocZero(MemoryContext context, Size size);
 extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
-- 
2.2.2

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to