diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a28e215..5666b0c 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -6095,9 +6095,8 @@ ShmemBackendArrayAllocation(void)
 {
 	Size		size = ShmemBackendArraySize();
 
-	ShmemBackendArray = (Backend *) ShmemAlloc(size);
 	/* Mark all slots as empty */
-	memset(ShmemBackendArray, 0, size);
+	ShmemBackendArray = (Backend *) ShmemAllocExtended(size, SHMEM_ALLOC_ZERO);
 }
 
 static void
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 1efe020..d8bc21f 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -163,15 +163,50 @@ InitShmemAllocation(void)
 /*
  * ShmemAlloc -- allocate max-aligned chunk from shared memory
  *
- * Assumes ShmemLock and ShmemSegHdr are initialized.
+ * Throws error if request cannot be satisfied.
  *
- * Returns: real pointer to memory or NULL if we are out
- *		of space.  Has to return a real pointer in order
- *		to be compatible with malloc().
+ * Assumes ShmemLock and ShmemSegHdr are initialized.
  */
 void *
 ShmemAlloc(Size size)
 {
+	void	   *newSpace;
+
+	newSpace = ShmemAllocExtended(size, 0);
+
+	return newSpace;
+}
+
+/*
+ * ShmemAllocNoError -- allocate max-aligned chunk from shared memory
+ *
+ * As ShmemAlloc, but returns NULL if out of space, rather than erroring.
+ *
+ * Assumes ShmemLock and ShmemSegHdr are initialized.
+ */
+void *
+ShmemAllocNoError(Size size)
+{
+	void	   *newSpace;
+
+	newSpace = ShmemAllocExtended(size, SHMEM_ALLOC_NO_OOM);
+
+	return newSpace;
+}
+
+/*
+ * ShmemAllocExtended -- allocate max-aligned chunk from shared memory
+ *
+ * The allocation is done according to the flags specified by caller
+ * - SHMEM_ALLOC_ZERO for zero-allocated memory.
+ * - SHMEM_ALLOC_NO_OOM, no failure in if out-of-memory, returning NULL
+ *   in this case.
+ *
+ * Assumes ShmemLock and ShmemSegHdr are initialized.
+ */
+void *
+ShmemAllocExtended(Size size, int flags)
+{
 	Size		newStart;
 	Size		newFree;
 	void	   *newSpace;
@@ -206,12 +241,17 @@ ShmemAlloc(Size size)
 
 	SpinLockRelease(ShmemLock);
 
-	if (!newSpace)
-		ereport(WARNING,
+	/* note this assert is okay with newSpace == NULL */
+	Assert(newSpace == (void *) CACHELINEALIGN(newSpace));
+
+	if (!newSpace && (flags & SHMEM_ALLOC_NO_OOM) == 0)
+		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
-				 errmsg("out of shared memory")));
+				 errmsg("out of shared memory (%zu bytes requested)",
+						size)));
 
-	Assert(newSpace == (void *) CACHELINEALIGN(newSpace));
+	if ((flags & SHMEM_ALLOC_ZERO) != 0)
+		MemSet(newSpace, 0, size);
 
 	return newSpace;
 }
@@ -293,7 +333,7 @@ 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 = ShmemAlloc;
+	infoP->alloc = ShmemAllocNoError;
 	hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE;
 
 	/* look it up in the shmem index */
@@ -364,12 +404,6 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 			 */
 			Assert(shmemseghdr->index == NULL);
 			structPtr = ShmemAlloc(size);
-			if (structPtr == NULL)
-				ereport(ERROR,
-						(errcode(ERRCODE_OUT_OF_MEMORY),
-						 errmsg("not enough shared memory for data structure"
-								" \"%s\" (%zu bytes requested)",
-								name, size)));
 			shmemseghdr->index = structPtr;
 			*foundPtr = FALSE;
 		}
@@ -410,7 +444,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 	else
 	{
 		/* It isn't in the table yet. allocate and initialize it */
-		structPtr = ShmemAlloc(size);
+		structPtr = ShmemAllocExtended(size, SHMEM_ALLOC_NO_OOM);
 		if (structPtr == NULL)
 		{
 			/* out of memory; remove the failed ShmemIndex entry */
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 7cdb355..54cbd47 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1183,15 +1183,8 @@ InitPredicateLocks(void)
 		PredXact->HavePartialClearedThrough = 0;
 		requestSize = mul_size((Size) max_table_size,
 							   PredXactListElementDataSize);
-		PredXact->element = ShmemAlloc(requestSize);
-		if (PredXact->element == NULL)
-			ereport(ERROR,
-					(errcode(ERRCODE_OUT_OF_MEMORY),
-			 errmsg("not enough shared memory for elements of data structure"
-					" \"%s\" (%zu bytes requested)",
-					"PredXactList", requestSize)));
 		/* Add all elements to available list, clean. */
-		memset(PredXact->element, 0, requestSize);
+		PredXact->element = ShmemAllocExtended(requestSize, SHMEM_ALLOC_ZERO);
 		for (i = 0; i < max_table_size; i++)
 		{
 			SHMQueueInsertBefore(&(PredXact->availableList),
@@ -1254,15 +1247,9 @@ InitPredicateLocks(void)
 		SHMQueueInit(&RWConflictPool->availableList);
 		requestSize = mul_size((Size) max_table_size,
 							   RWConflictDataSize);
-		RWConflictPool->element = ShmemAlloc(requestSize);
-		if (RWConflictPool->element == NULL)
-			ereport(ERROR,
-					(errcode(ERRCODE_OUT_OF_MEMORY),
-			 errmsg("not enough shared memory for elements of data structure"
-					" \"%s\" (%zu bytes requested)",
-					"RWConflictPool", requestSize)));
 		/* Add all elements to available list, clean. */
-		memset(RWConflictPool->element, 0, requestSize);
+		RWConflictPool->element = ShmemAllocExtended(requestSize,
+													 SHMEM_ALLOC_ZERO);
 		for (i = 0; i < max_table_size; i++)
 		{
 			SHMQueueInsertBefore(&(RWConflictPool->availableList),
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 9a758bd..ab4adbe 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -193,15 +193,11 @@ InitProcGlobal(void)
 	 * dedicated to exactly one of these purposes, and they do not move
 	 * between groups.
 	 */
-	procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
+	procs = (PGPROC *) ShmemAllocExtended(TotalProcs * sizeof(PGPROC),
+										  SHMEM_ALLOC_ZERO);
 	ProcGlobal->allProcs = procs;
 	/* XXX allProcCount isn't really all of them; it excludes prepared xacts */
 	ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS;
-	if (!procs)
-		ereport(FATAL,
-				(errcode(ERRCODE_OUT_OF_MEMORY),
-				 errmsg("out of shared memory")));
-	MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
 
 	/*
 	 * Also allocate a separate array of PGXACT structures.  This is separate
@@ -211,8 +207,8 @@ InitProcGlobal(void)
 	 * multiprocessor system.  There is one PGXACT structure for every PGPROC
 	 * structure.
 	 */
-	pgxacts = (PGXACT *) ShmemAlloc(TotalProcs * sizeof(PGXACT));
-	MemSet(pgxacts, 0, TotalProcs * sizeof(PGXACT));
+	pgxacts = (PGXACT *) ShmemAllocExtended(TotalProcs * sizeof(PGXACT),
+											SHMEM_ALLOC_ZERO);
 	ProcGlobal->allPgXact = pgxacts;
 
 	for (i = 0; i < TotalProcs; i++)
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index 6468e66..b654fd4 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -31,10 +31,18 @@ typedef struct SHM_QUEUE
 	struct SHM_QUEUE *next;
 } SHM_QUEUE;
 
+/*
+ * Flags for ShmemAllocExtended.
+ */
+#define SHMEM_ALLOC_NO_OOM		0x01	/* no failure if out-of-memory */
+#define SHMEM_ALLOC_ZERO		0x02	/* zero allocated memory */
+
 /* shmem.c */
 extern void InitShmemAccess(void *seghdr);
 extern void InitShmemAllocation(void);
 extern void *ShmemAlloc(Size size);
+extern void *ShmemAllocNoError(Size size);
+extern void *ShmemAllocExtended(Size size, int flags);
 extern bool ShmemAddrIsValid(const void *addr);
 extern void InitShmemIndex(void);
 extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size,
