*
* 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-2012, 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"
#include "pgtime.h"
#include "storage/proc.h"
enum MemoryContextType {
STANDARD_CONTEXT,
STACK_CONTEXT,
SHARED_CONTEXT,
MEMALIGN_CONTEXT,
MEMALIGN_SHRCTX,
RACK_CONTEXT,
};
extern bool EnableBorrowWorkMemory();
extern bool RackMemoryBusy(int64 used);
extern Size GetAvailRackMemory(int dop);
* MaxAllocSize
* Quasi-arbitrary limit on size of allocations.
*
* Note:
* There is no guarantee that allocations smaller than MaxAllocSize
* will succeed. Allocation requests larger than MaxAllocSize will
* be summarily denied.
*
* XXX This is deliberately 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.
*
* XXX Also, various places in aset.c assume they can compute twice an
* allocation's size without overflow, so beware of raising this.
*/
#define MaxAllocSize ((Size)0x3fffffff)
#define MaxBuildAllocSize ((Size)0x3ffffff)
#define AllocSizeIsValid(size) ((Size)(size) <= MaxAllocSize)
#define MaxAllocHugeSize ((Size)-1 >> 1)
#define AllocHugeSizeIsValid(size) ((Size)(size) <= MaxAllocHugeSize)
* 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 struct StandardChunkHeader {
MemoryContext context;
Size size;
#ifdef MEMORY_CONTEXT_CHECKING
Size requested_size;
#endif
#ifdef MEMORY_CONTEXT_TRACK
const char* file;
int line;
#endif
} StandardChunkHeader;
#define STANDARDCHUNKHEADERSIZE MAXALIGN(sizeof(StandardChunkHeader))
extern MemoryContext AdioSharedContext;
extern MemoryContext ProcSubXidCacheContext;
extern MemoryContext PmTopMemoryContext;
extern MemoryContext StreamInfoContext;
extern MemoryContext DMSDrcContext;
extern THR_LOCAL PGDLLIMPORT MemoryContext ErrorContext;
* Memory-context-type-independent functions in mcxt.c
*/
extern void MemoryContextInit(void);
#define MemoryContextReset(context) \
(((MemoryContext)context)->mcxt_methods->mcxt_reset(context))
#define MemoryContextDelete(context) \
(((MemoryContext)context)->mcxt_methods->mcxt_delete(context))
#define MemoryContextDeleteChildren(context, list) \
(((MemoryContext)context)->mcxt_methods->mcxt_delete_children(context, list))
#define MemoryContextDestroyAtThreadExit(context) \
(((MemoryContext)context)->mcxt_methods->mcxt_destroy(context))
#define MemoryContextResetAndDeleteChildren(context) \
(((MemoryContext)context)->mcxt_methods->mcxt_reset_and_delete_children(context))
#define MemoryContextSetParent(context, new_parent) \
(((MemoryContext)context)->mcxt_methods->mcxt_set_parent(context, new_parent))
extern void MemoryContextResetChildren(MemoryContext context);
extern MemoryContext MemoryContextGetParent(MemoryContext context);
extern bool MemoryContextIsEmpty(MemoryContext context);
extern void MemoryContextStats(MemoryContext context);
extern void MemoryContextSeal(MemoryContext context);
extern void MemoryContextUnSeal(MemoryContext context);
extern void MemoryContextUnSealChildren(MemoryContext context);
extern void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow);
extern bool MemoryContextContains(MemoryContext context, void* pointer);
extern MemoryContext MemoryContextOriginal(const char* node);
extern Size GetMemoryTotalSpace(MemoryContext context, bool recurse);
extern Size GetMemoryChildrenTotalSpace(MemoryContext context, bool recurse);
extern Size GetMemoryChunkSpace(void* pointer);
extern MemoryContext GetMemoryChunkContext(void* pointer);
#ifdef MEMORY_CONTEXT_CHECKING
#define MemoryContextCheck(context, own_by_session) \
(((MemoryContext)context)->mcxt_methods->mcxt_check(context, own_by_session))
#define MemoryContextCheck2(mctx)
#endif
extern void std_MemoryContextReset(MemoryContext context);
extern void std_MemoryContextDelete(MemoryContext context);
extern void std_MemoryContextDeleteChildren(MemoryContext context, List* context_list = NULL);
extern void std_MemoryContextDestroyAtThreadExit(MemoryContext context);
extern void std_MemoryContextResetAndDeleteChildren(MemoryContext context);
extern void std_MemoryContextSetParent(MemoryContext context, MemoryContext new_parent);
extern void std_MemoryContextCheck(MemoryContext context, bool own_by_session);
extern void opt_MemoryContextReset(MemoryContext context);
extern void opt_MemoryContextDelete(MemoryContext context);
extern void opt_MemoryContextDeleteChildren(MemoryContext context, List* context_list = NULL);
extern void opt_MemoryContextDestroyAtThreadExit(MemoryContext context);
#define opt_MemoryContextResetAndDeleteChildren(context) \
opt_MemoryContextReset(context)
extern void opt_MemoryContextSetParent(MemoryContext context, MemoryContext new_parent);
#ifdef MEMORY_CONTEXT_CHECKING
extern void opt_MemoryContextCheck(MemoryContext context, bool own_by_session);
#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 MemoryContext MemoryContextCreate(
NodeTag tag, Size size, MemoryContext parent, const char* name, const char* file, int line);
extern MemoryContext MemoryContextCreate(
NodeTag tag, Size size, MemoryContextMethods* methods, MemoryContext parent, const char* name);
extern MemoryContext opt_MemoryContextCreate(MemoryContext node, NodeTag tag,
MemoryContextMethods *methods, MemoryContext parent, const char* name);
* Memory-context-type-specific functions
*/
#define DEFAULT_MEMORY_CONTEXT_MAX_SIZE 0
#define SHARED_MEMORY_CONTEXT_MAX_SIZE (100 * 1024 * 1024)
extern MemoryContext AllocSetContextCreate(MemoryContext parent, const char* name, Size minContextSize,
Size initBlockSize, Size maxBlockSize, MemoryContextType type = STANDARD_CONTEXT,
Size maxSize = DEFAULT_MEMORY_CONTEXT_MAX_SIZE, bool isSession = false);
extern MemoryContext opt_AllocSetContextCreate(MemoryContext parent,
const char* name, Size minContextSize, Size initBlockSize, Size maxBlockSize);
* 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 not 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
#define DEFAULT_GROW_RATIO 2.0
#define MEM_AUTO_SPREAD_MIN_RATIO 0.1
class AutoContextSwitch {
public:
AutoContextSwitch(MemoryContext memContext)
{
if (memContext == NULL) {
m_oldMemContext = CurrentMemoryContext;
} else {
m_oldMemContext = MemoryContextSwitchTo(memContext);
}
};
~AutoContextSwitch()
{
MemoryContextSwitchTo(m_oldMemContext);
}
private:
MemoryContext m_oldMemContext;
};
#define IS_USESS_AVAILABLE (likely(u_sess != NULL))
#define GS_MP_INITED (t_thrd.utils_cxt.gs_mp_inited)
#define MEMORY_TRACKING_MODE (IS_USESS_AVAILABLE ? u_sess->attr.attr_memory.memory_tracking_mode : 0)
#define MEMORY_TRACKING_QUERY_PEAK (IS_USESS_AVAILABLE ? (u_sess->attr.attr_memory.memory_tracking_mode == MEMORY_TRACKING_PEAKMEMORY ) : 0)
#define ENABLE_MEMORY_CONTEXT_CONTROL \
(IS_USESS_AVAILABLE ? u_sess->attr.attr_memory.enable_memory_context_control : false)
#define MEMORY_FAULT_PERCENT (IS_USESS_AVAILABLE ? u_sess->attr.attr_resource.memory_fault_percent : 0)
#define STATEMENT_MAX_MEM (IS_USESS_AVAILABLE ? u_sess->attr.attr_sql.statement_max_mem : 0)
#define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024)
#define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024)
#endif