| /*------------------------------------------------------------------------- |
| * |
| * 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 */ |