aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/mmgr/aset.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index de56a2dc010..6c1b5f390da 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
- * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.62 2005/06/04 22:57:22 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mmgr/aset.c,v 1.63 2005/09/01 18:15:42 tgl Exp $
*
* NOTE:
* This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -123,6 +123,12 @@ typedef void *AllocPointer;
/*
* AllocSetContext is our standard implementation of MemoryContext.
+ *
+ * Note: isReset means there is nothing for AllocSetReset to do. This is
+ * different from the aset being physically empty (empty blocks list) because
+ * we may still have a keeper block. It's also different from the set being
+ * logically empty, because we don't attempt to detect pfree'ing the last
+ * active chunk.
*/
typedef struct AllocSetContext
{
@@ -130,6 +136,7 @@ typedef struct AllocSetContext
/* Info about storage allocated in this context: */
AllocBlock blocks; /* head of list of blocks in this set */
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
+ bool isReset; /* T = no space alloced since last reset */
/* Allocation parameters for this context: */
Size initBlockSize; /* initial block size */
Size maxBlockSize; /* maximum block size */
@@ -347,6 +354,8 @@ AllocSetContextCreate(MemoryContext parent,
context->keeper = block;
}
+ context->isReset = true;
+
return (MemoryContext) context;
}
@@ -386,26 +395,28 @@ static void
AllocSetReset(MemoryContext context)
{
AllocSet set = (AllocSet) context;
- AllocBlock block = set->blocks;
+ AllocBlock block;
AssertArg(AllocSetIsValid(set));
+ /* Nothing to do if no pallocs since startup or last reset */
+ if (set->isReset)
+ return;
+
#ifdef MEMORY_CONTEXT_CHECKING
/* Check for corruption and leaks before freeing */
AllocSetCheck(context);
#endif
- /* Nothing to do if context has never contained any data */
- if (block == NULL)
- return;
-
/* Clear chunk freelists */
MemSetAligned(set->freelist, 0, sizeof(set->freelist));
+ block = set->blocks;
+
/* New blocks list is either empty or just the keeper block */
set->blocks = set->keeper;
- do
+ while (block != NULL)
{
AllocBlock next = block->next;
@@ -432,7 +443,8 @@ AllocSetReset(MemoryContext context)
}
block = next;
}
- while (block != NULL);
+
+ set->isReset = true;
}
/*
@@ -538,6 +550,8 @@ AllocSetAlloc(MemoryContext context, Size size)
set->blocks = block;
}
+ set->isReset = false;
+
AllocAllocInfo(set, chunk);
return AllocChunkGetPointer(chunk);
}
@@ -576,6 +590,9 @@ AllocSetAlloc(MemoryContext context, Size size)
((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
#endif
+ /* isReset must be false already */
+ Assert(!set->isReset);
+
AllocAllocInfo(set, chunk);
return AllocChunkGetPointer(chunk);
}
@@ -748,6 +765,8 @@ AllocSetAlloc(MemoryContext context, Size size)
((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
#endif
+ set->isReset = false;
+
AllocAllocInfo(set, chunk);
return AllocChunkGetPointer(chunk);
}
@@ -846,6 +865,9 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
set->header.name, chunk);
#endif
+ /* isReset must be false already */
+ Assert(!set->isReset);
+
/*
* Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
* allocated area already is >= the new size. (In particular, we
@@ -1009,12 +1031,12 @@ AllocSetIsEmpty(MemoryContext context)
AllocSet set = (AllocSet) context;
/*
- * For now, we say "empty" only if the context never contained any
- * space at all. We could examine the freelists to determine if all
- * space has been freed, but it's not really worth the trouble for
- * present uses of this functionality.
+ * For now, we say "empty" only if the context is new or just reset.
+ * We could examine the freelists to determine if all space has been
+ * freed, but it's not really worth the trouble for present uses of
+ * this functionality.
*/
- if (set->blocks == NULL)
+ if (set->isReset)
return true;
return false;
}