mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
First phase of memory management rewrite (see backend/utils/mmgr/README
for details). It doesn't really do that much yet, since there are no short-term memory contexts in the executor, but the infrastructure is in place and long-term contexts are handled reasonably. A few long- standing bugs have been fixed, such as 'VACUUM; anything' in a single query string crashing. Also, out-of-memory is now considered a recoverable ERROR, not FATAL. Eliminate a large amount of crufty, now-dead code in and around memory management. Fix problem with holding off SIGTRAP, SIGSEGV, etc in postmaster and backend startup.
This commit is contained in:
@ -1,230 +1,114 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* memutils.h
|
||||
* this file contains general memory alignment, allocation
|
||||
* and manipulation stuff that used to be spread out
|
||||
* between the following files:
|
||||
*
|
||||
* align.h alignment macros
|
||||
* aset.h memory allocation set stuff
|
||||
* oset.h (used by aset.h)
|
||||
* This file contains declarations for memory allocation utility
|
||||
* functions. These are functions that are not quite widely used
|
||||
* enough to justify going in utils/palloc.h, but are still part
|
||||
* of the API of the memory management subsystem.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: memutils.h,v 1.35 2000/05/21 02:23:28 tgl Exp $
|
||||
* $Id: memutils.h,v 1.36 2000/06/28 03:33:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef MEMUTILS_H
|
||||
#define MEMUTILS_H
|
||||
|
||||
/* ----------------
|
||||
* Alignment macros: align a length or address appropriately for a given type.
|
||||
*
|
||||
* There used to be some incredibly crufty platform-dependent hackery here,
|
||||
* but now we rely on the configure script to get the info for us. Much nicer.
|
||||
*
|
||||
* NOTE: TYPEALIGN will not work if ALIGNVAL is not a power of 2.
|
||||
* That case seems extremely unlikely to occur in practice, however.
|
||||
* ----------------
|
||||
*/
|
||||
#include "nodes/memnodes.h"
|
||||
|
||||
#define TYPEALIGN(ALIGNVAL,LEN) (((long)(LEN) + (ALIGNVAL-1)) & ~(ALIGNVAL-1))
|
||||
|
||||
#define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN))
|
||||
#define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN))
|
||||
#define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN))
|
||||
#define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN))
|
||||
#define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
|
||||
|
||||
/*****************************************************************************
|
||||
* oset.h -- Fixed format ordered set definitions. *
|
||||
*****************************************************************************/
|
||||
/* Note:
|
||||
* Fixed format ordered sets are <EXPLAIN>.
|
||||
* XXX This is a preliminary version. Work is needed to explain
|
||||
* XXX semantics of the external definitions. Otherwise, the
|
||||
* XXX functional interface should not change.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct OrderedElemData OrderedElemData;
|
||||
typedef OrderedElemData *OrderedElem;
|
||||
|
||||
typedef struct OrderedSetData OrderedSetData;
|
||||
typedef OrderedSetData *OrderedSet;
|
||||
|
||||
struct OrderedElemData
|
||||
{
|
||||
OrderedElem next; /* Next elem or &this->set->dummy */
|
||||
OrderedElem prev; /* Previous elem or &this->set->head */
|
||||
OrderedSet set; /* Parent set */
|
||||
};
|
||||
|
||||
struct OrderedSetData
|
||||
{
|
||||
OrderedElem head; /* First elem or &this->dummy */
|
||||
OrderedElem dummy; /* (hack) Terminator == NULL */
|
||||
OrderedElem tail; /* Last elem or &this->head */
|
||||
Offset offset; /* Offset from struct base to elem */
|
||||
/* this could be signed short int! */
|
||||
};
|
||||
|
||||
extern void OrderedSetInit(OrderedSet set, Offset offset);
|
||||
extern Pointer OrderedSetGetHead(OrderedSet set);
|
||||
extern Pointer OrderedElemGetPredecessor(OrderedElem elem);
|
||||
extern Pointer OrderedElemGetSuccessor(OrderedElem elem);
|
||||
extern void OrderedElemPop(OrderedElem elem);
|
||||
extern void OrderedElemPushInto(OrderedElem elem, OrderedSet Set);
|
||||
|
||||
/*****************************************************************************
|
||||
* aset.h -- Allocation set definitions. *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Description:
|
||||
* An allocation set is a set containing allocated elements. When
|
||||
* an allocation is requested for a set, memory is allocated and a
|
||||
* pointer is returned. Subsequently, this memory may be freed or
|
||||
* reallocated. In addition, an allocation set may be reset which
|
||||
* will cause all memory allocated within it to be freed.
|
||||
*
|
||||
* XXX The following material about allocation modes is all OUT OF DATE.
|
||||
* aset.c currently implements only one allocation strategy,
|
||||
* DynamicAllocMode, and that's the only one anyone ever requests anyway.
|
||||
* If we ever did have more strategies, the new ones might or might
|
||||
* not look like what is described here...
|
||||
*
|
||||
* Allocations may occur in four different modes. The mode of
|
||||
* allocation does not affect the behavior of allocations except in
|
||||
* terms of performance. The allocation mode is set at the time of
|
||||
* set initialization. Once the mode is chosen, it cannot be changed
|
||||
* unless the set is reinitialized.
|
||||
*
|
||||
* "Dynamic" mode forces all allocations to occur in a heap. This
|
||||
* is a good mode to use when small memory segments are allocated
|
||||
* and freed very frequently. This is a good choice when allocation
|
||||
* characteristics are unknown. This is the default mode.
|
||||
*
|
||||
* "Static" mode attempts to allocate space as efficiently as possible
|
||||
* without regard to freeing memory. This mode should be chosen only
|
||||
* when it is known that many allocations will occur but that very
|
||||
* little of the allocated memory will be explicitly freed.
|
||||
*
|
||||
* "Tunable" mode is a hybrid of dynamic and static modes. The
|
||||
* tunable mode will use static mode allocation except when the
|
||||
* allocation request exceeds a size limit supplied at the time of set
|
||||
* initialization. "Big" objects are allocated using dynamic mode.
|
||||
*
|
||||
* "Bounded" mode attempts to allocate space efficiently given a limit
|
||||
* on space consumed by the allocation set. This restriction can be
|
||||
* considered a "soft" restriction, because memory segments will
|
||||
* continue to be returned after the limit is exceeded. The limit is
|
||||
* specified at the time of set initialization like for tunable mode.
|
||||
* MaxAllocSize
|
||||
* Arbitrary limit on size of allocations.
|
||||
*
|
||||
* Note:
|
||||
* Allocation sets are not automatically reset on a system reset.
|
||||
* Higher level code is responsible for cleaning up.
|
||||
* There is no guarantee that allocations smaller than MaxAllocSize
|
||||
* will succeed. Allocation requests larger than MaxAllocSize will
|
||||
* be summarily denied.
|
||||
*
|
||||
* There may be other modes in the future.
|
||||
* XXX This should be defined in a file of tunable constants.
|
||||
*/
|
||||
#define MaxAllocSize ((Size) 0xfffffff) /* 16G - 1 */
|
||||
|
||||
#define AllocSizeIsValid(size) (0 < (size) && (size) <= MaxAllocSize)
|
||||
|
||||
/*
|
||||
* AllocPointer
|
||||
* Aligned pointer which may be a member of an allocation set.
|
||||
* All chunks allocated by any memory context manager are required to be
|
||||
* preceded by a StandardChunkHeader at a spacing of STANDARDCHUNKHEADERSIZE.
|
||||
* A currently-allocated chunk must contain a backpointer to its owning
|
||||
* context as well as the allocated size of the chunk. The backpointer is
|
||||
* used by pfree() and repalloc() to find the context to call. The allocated
|
||||
* size is not absolutely essential, but it's expected to be needed by any
|
||||
* reasonable implementation.
|
||||
*/
|
||||
typedef Pointer AllocPointer;
|
||||
typedef struct StandardChunkHeader
|
||||
{
|
||||
MemoryContext context; /* owning context */
|
||||
Size size; /* size of data space allocated in chunk */
|
||||
} StandardChunkHeader;
|
||||
|
||||
#define STANDARDCHUNKHEADERSIZE MAXALIGN(sizeof(StandardChunkHeader))
|
||||
|
||||
|
||||
/*
|
||||
* AllocMode
|
||||
* Mode of allocation for an allocation set.
|
||||
* Standard top-level memory contexts.
|
||||
*
|
||||
* Note:
|
||||
* See above for a description of the various modes.
|
||||
* Only TopMemoryContext and ErrorContext are initialized by
|
||||
* MemoryContextInit() itself.
|
||||
*/
|
||||
typedef enum AllocMode
|
||||
{
|
||||
DynamicAllocMode, /* always dynamically allocate */
|
||||
StaticAllocMode, /* always "statically" allocate */
|
||||
TunableAllocMode, /* allocations are "tuned" */
|
||||
BoundedAllocMode /* allocations bounded to fixed usage */
|
||||
} AllocMode;
|
||||
extern MemoryContext TopMemoryContext;
|
||||
extern MemoryContext ErrorContext;
|
||||
extern MemoryContext PostmasterContext;
|
||||
extern MemoryContext CacheMemoryContext;
|
||||
extern MemoryContext QueryContext;
|
||||
extern MemoryContext TopTransactionContext;
|
||||
extern MemoryContext TransactionCommandContext;
|
||||
|
||||
#define DefaultAllocMode DynamicAllocMode
|
||||
|
||||
typedef struct AllocSetData *AllocSet;
|
||||
typedef struct AllocBlockData *AllocBlock;
|
||||
typedef struct AllocChunkData *AllocChunk;
|
||||
|
||||
/*
|
||||
* AllocSet
|
||||
* Allocation set.
|
||||
* Memory-context-type-independent functions in mcxt.c
|
||||
*/
|
||||
typedef struct AllocSetData
|
||||
{
|
||||
AllocBlock blocks; /* head of list of blocks in this set */
|
||||
#define ALLOCSET_NUM_FREELISTS 8
|
||||
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
|
||||
/* Note: this will change in the future to support other modes */
|
||||
} AllocSetData;
|
||||
extern void MemoryContextInit(void);
|
||||
extern void MemoryContextReset(MemoryContext context);
|
||||
extern void MemoryContextDelete(MemoryContext context);
|
||||
extern void MemoryContextResetChildren(MemoryContext context);
|
||||
extern void MemoryContextDeleteChildren(MemoryContext context);
|
||||
extern void MemoryContextResetAndDeleteChildren(MemoryContext context);
|
||||
extern void MemoryContextStats(MemoryContext context);
|
||||
extern bool MemoryContextContains(MemoryContext context, void *pointer);
|
||||
|
||||
/*
|
||||
* AllocBlock
|
||||
* An AllocBlock is the unit of memory that is obtained by aset.c
|
||||
* from malloc(). It contains one or more AllocChunks, which are
|
||||
* the units requested by palloc() and freed by pfree(). AllocChunks
|
||||
* cannot be returned to malloc() individually, instead they are put
|
||||
* on freelists by pfree() and re-used by the next palloc() that has
|
||||
* a matching request size.
|
||||
*
|
||||
* AllocBlockData is the header data for a block --- the usable space
|
||||
* within the block begins at the next alignment boundary.
|
||||
* This routine handles the context-type-independent part of memory
|
||||
* context creation. It's intended to be called from context-type-
|
||||
* specific creation routines, and noplace else.
|
||||
*/
|
||||
typedef struct AllocBlockData
|
||||
{
|
||||
AllocSet aset; /* aset that owns this block */
|
||||
AllocBlock next; /* next block in aset's blocks list */
|
||||
char *freeptr; /* start of free space in this block */
|
||||
char *endptr; /* end of space in this block */
|
||||
} AllocBlockData;
|
||||
extern MemoryContext MemoryContextCreate(NodeTag tag, Size size,
|
||||
MemoryContextMethods *methods,
|
||||
MemoryContext parent,
|
||||
const char *name);
|
||||
|
||||
|
||||
/*
|
||||
* AllocChunk
|
||||
* The prefix of each piece of memory in an AllocBlock
|
||||
* Memory-context-type-specific functions
|
||||
*/
|
||||
typedef struct AllocChunkData
|
||||
{
|
||||
/* aset is the owning aset if allocated, or the freelist link if free */
|
||||
void *aset;
|
||||
/* size is always the size of the usable space in the chunk */
|
||||
Size size;
|
||||
} AllocChunkData;
|
||||
|
||||
/* aset.c */
|
||||
extern MemoryContext AllocSetContextCreate(MemoryContext parent,
|
||||
const char *name,
|
||||
Size minContextSize,
|
||||
Size initBlockSize,
|
||||
Size maxBlockSize);
|
||||
|
||||
/*
|
||||
* AllocPointerIsValid
|
||||
* True iff pointer is valid allocation pointer.
|
||||
* Recommended default alloc parameters, suitable for "ordinary" contexts
|
||||
* that might hold quite a lot of data.
|
||||
*/
|
||||
#define AllocPointerIsValid(pointer) PointerIsValid(pointer)
|
||||
|
||||
/*
|
||||
* AllocSetIsValid
|
||||
* True iff set is valid allocation set.
|
||||
*/
|
||||
#define AllocSetIsValid(set) PointerIsValid(set)
|
||||
|
||||
extern void AllocSetInit(AllocSet set, AllocMode mode, Size limit);
|
||||
|
||||
extern void AllocSetReset(AllocSet set);
|
||||
|
||||
extern bool AllocSetContains(AllocSet set, AllocPointer pointer);
|
||||
extern AllocPointer AllocSetAlloc(AllocSet set, Size size);
|
||||
extern void AllocSetFree(AllocSet set, AllocPointer pointer);
|
||||
extern AllocPointer AllocSetRealloc(AllocSet set, AllocPointer pointer,
|
||||
Size size);
|
||||
|
||||
extern void AllocSetDump(AllocSet set);
|
||||
extern void AllocSetStats(AllocSet set, const char *ident);
|
||||
#define ALLOCSET_DEFAULT_MINSIZE (8 * 1024)
|
||||
#define ALLOCSET_DEFAULT_INITSIZE (8 * 1024)
|
||||
#define ALLOCSET_DEFAULT_MAXSIZE (8 * 1024 * 1024)
|
||||
|
||||
|
||||
#endif /* MEMUTILS_H */
|
||||
|
Reference in New Issue
Block a user