From 4cf6e9e081be62c28ecdeb8ca2672651d107925a Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 13 Sep 2003 22:25:38 +0000
Subject: [PATCH] Avoid corner cases where aset.c would unnecessarily make
 malloc() requests of sizes that aren't powers of 2.  Per observation from
 David Schultz, 28-Aug.

---
 src/backend/utils/mmgr/aset.c | 33 +++++++++++++++------------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index fddcad7a29b..b36596734d7 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.52 2003/08/04 02:40:08 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.53 2003/09/13 22:25:38 tgl Exp $
  *
  * NOTE:
  *	This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -650,32 +650,29 @@ AllocSetAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
-			/* Get size of prior block */
-			blksize = set->blocks->endptr - ((char *) set->blocks);
-
 			/*
-			 * Special case: if very first allocation was for a large
-			 * chunk (or we have a small "keeper" block), could have an
-			 * undersized top block.  Do something reasonable.
+			 * Use first power of 2 that is larger than previous block,
+			 * but not more than the allowed limit.  (We don't simply double
+			 * the prior block size, because in some cases this could be a
+			 * funny size, eg if very first allocation was for an odd-sized
+			 * large chunk.)
 			 */
-			if (blksize < set->initBlockSize)
-				blksize = set->initBlockSize;
-			else
-			{
-				/* Crank it up, but not past max */
+			Size	pblksize = set->blocks->endptr - ((char *) set->blocks);
+
+			blksize = set->initBlockSize;
+			while (blksize <= pblksize)
 				blksize <<= 1;
-				if (blksize > set->maxBlockSize)
-					blksize = set->maxBlockSize;
-			}
+			if (blksize > set->maxBlockSize)
+				blksize = set->maxBlockSize;
 		}
 
 		/*
 		 * If initBlockSize is less than ALLOC_CHUNK_LIMIT, we could need
-		 * more space...
+		 * more space... but try to keep it a power of 2.
 		 */
 		required_size = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
-		if (blksize < required_size)
-			blksize = required_size;
+		while (blksize < required_size)
+			blksize <<= 1;
 
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
-- 
GitLab