/*------------------------------------------------------------------------- * * memutils.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-2020, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/memutils.h * *------------------------------------------------------------------------- */ #ifndef MEMUTILS_H #define MEMUTILS_H #include "nodes/memnodes.h" /* * MaxAllocSize, MaxAllocHugeSize * Quasi-arbitrary limits on size of allocations. * * Note: * There is no guarantee that smaller allocations will succeed, but * larger requests will be summarily denied. * * palloc() enforces MaxAllocSize, chosen to correspond to the limiting size * of varlena objects under TOAST. See VARSIZE_4B() and related macros in * postgres.h. Many datatypes assume that any allocatable size can be * represented in a varlena header. This limit also permits a caller to use * an "int" variable for an index into or length of an allocation. Callers * careful to avoid these hazards can access the higher limit with * MemoryContextAllocHuge(). Both limits permit code to assume that it may * compute twice an allocation's size without overflow. */ #define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */ #define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize) #define MaxAllocHugeSize (SIZE_MAX / 2) #define AllocHugeSizeIsValid(size) ((Size) (size) <= MaxAllocHugeSize) /* * Standard top-level memory contexts. * * Only TopMemoryContext and ErrorContext are initialized by * MemoryContextInit() itself. */ extern PGDLLIMPORT MemoryContext TopMemoryContext; extern PGDLLIMPORT MemoryContext ErrorContext; extern PGDLLIMPORT MemoryContext PostmasterContext; extern PGDLLIMPORT MemoryContext CacheMemoryContext; extern PGDLLIMPORT MemoryContext MessageContext; extern PGDLLIMPORT MemoryContext TopTransactionContext; extern PGDLLIMPORT MemoryContext CurTransactionContext; /* This is a transient link to the active portal's memory context: */ extern PGDLLIMPORT MemoryContext PortalContext; /* Backwards compatibility macro */ #define MemoryContextResetAndDeleteChildren(ctx) MemoryContextReset(ctx) /* * Memory-context-type-independent functions in mcxt.c */ extern void MemoryContextInit(void); extern void MemoryContextReset(MemoryContext context); extern void MemoryContextDelete(MemoryContext context); extern void MemoryContextResetOnly(MemoryContext context); extern void MemoryContextResetChildren(MemoryContext context); extern void MemoryContextDeleteChildren(MemoryContext context); extern void MemoryContextSetIdentifier(MemoryContext context, const char *id); extern void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent); extern Size GetMemoryChunkSpace(void *pointer); extern MemoryContext MemoryContextGetParent(MemoryContext context); extern bool MemoryContextIsEmpty(MemoryContext context); extern Size MemoryContextMemAllocated(MemoryContext context, bool recurse); extern void MemoryContextStats(MemoryContext context); extern void MemoryContextStatsDetail(MemoryContext context, int max_children); extern void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow); #ifdef MEMORY_CONTEXT_CHECKING extern void MemoryContextCheck(MemoryContext context); #endif extern bool MemoryContextContains(MemoryContext context, void *pointer); /* Handy macro for copying and assigning context ID ... but note double eval */ #define MemoryContextCopyAndSetIdentifier(cxt, id) \ MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id)) /* * GetMemoryChunkContext * Given a currently-allocated chunk, determine the context * it belongs to. * * All chunks allocated by any memory context manager are required to be * preceded by the corresponding MemoryContext stored, without padding, in the * preceding sizeof(void*) bytes. A currently-allocated chunk must contain a * backpointer to its owning context. The backpointer is used by pfree() and * repalloc() to find the context to call. */ #ifndef FRONTEND static inline MemoryContext GetMemoryChunkContext(void *pointer) { MemoryContext context; /* * Try to detect bogus pointers handed to us, poorly though we can. * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an * allocated chunk. */ Assert(pointer != NULL); Assert(pointer == (void *) MAXALIGN(pointer)); /* * OK, it's probably safe to look at the context. */ context = *(MemoryContext *) (((char *) pointer) - sizeof(void *)); AssertArg(MemoryContextIsValid(context)); return context; } #endif /* * 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. */ extern void MemoryContextCreate(MemoryContext node, NodeTag tag, const MemoryContextMethods *methods, MemoryContext parent, const char *name); /* * Memory-context-type-specific functions */ /* aset.c */ extern MemoryContext AllocSetContextCreateInternal(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize); /* * This wrapper macro exists to check for non-constant strings used as context * names; that's no longer supported. (Use MemoryContextSetIdentifier if you * want to provide a variable identifier.) */ #ifdef HAVE__BUILTIN_CONSTANT_P #define AllocSetContextCreate(parent, name, ...) \ (StaticAssertExpr(__builtin_constant_p(name), \ "memory context names must be constant strings"), \ AllocSetContextCreateInternal(parent, name, __VA_ARGS__)) #else #define AllocSetContextCreate \ AllocSetContextCreateInternal #endif /* slab.c */ extern MemoryContext SlabContextCreate(MemoryContext parent, const char *name, Size blockSize, Size chunkSize); /* generation.c */ extern MemoryContext GenerationContextCreate(MemoryContext parent, const char *name, Size blockSize); /* * Recommended default alloc parameters, suitable for "ordinary" contexts * that might hold quite a lot of data. */ #define ALLOCSET_DEFAULT_MINSIZE 0 #define ALLOCSET_DEFAULT_INITSIZE (8 * 1024) #define ALLOCSET_DEFAULT_MAXSIZE (8 * 1024 * 1024) #define ALLOCSET_DEFAULT_SIZES \ ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE /* * Recommended alloc parameters for "small" contexts that are never expected * to contain much data (for example, a context to contain a query plan). */ #define ALLOCSET_SMALL_MINSIZE 0 #define ALLOCSET_SMALL_INITSIZE (1 * 1024) #define ALLOCSET_SMALL_MAXSIZE (8 * 1024) #define ALLOCSET_SMALL_SIZES \ ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE /* * Recommended alloc parameters for contexts that should start out small, * but might sometimes grow big. */ #define ALLOCSET_START_SMALL_SIZES \ ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE /* * Threshold above which a request in an AllocSet context is certain to be * allocated separately (and thereby have constant allocation overhead). * Few callers should be interested in this, but tuplesort/tuplestore need * to know it. */ #define ALLOCSET_SEPARATE_THRESHOLD 8192 #define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024) #define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024) #endif /* MEMUTILS_H */