forked from nuoya/openGauss-server
276 lines
13 KiB
C
276 lines
13 KiB
C
/* -------------------------------------------------------------------------
|
|
*
|
|
* memnodes.h
|
|
* POSTGRES memory context node definitions.
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/nodes/memnodes.h
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
#ifndef MEMNODES_H
|
|
#define MEMNODES_H
|
|
|
|
#include "nodes/nodes.h"
|
|
#include "nodes/pg_list.h"
|
|
|
|
/*
|
|
* MemoryContext
|
|
* A logical context in which memory allocations occur.
|
|
*
|
|
* MemoryContext itself is an abstract type that can have multiple
|
|
* implementations, though for now we have only AllocSetContext.
|
|
* The function pointers in MemoryContextMethods define one specific
|
|
* implementation of MemoryContext --- they are a virtual function table
|
|
* in C++ terms.
|
|
*
|
|
* Node types that are actual implementations of memory contexts must
|
|
* begin with the same fields as MemoryContext.
|
|
*
|
|
* Note: for largely historical reasons, typedef MemoryContext is a pointer
|
|
* to the context struct rather than the struct type itself.
|
|
*/
|
|
typedef struct MemoryContextMethods {
|
|
void* (*alloc)(MemoryContext context, Size align, Size size, const char* file, int line);
|
|
/* call this free_p in case someone #define's free() */
|
|
void (*free_p)(MemoryContext context, void* pointer);
|
|
void* (*realloc)(MemoryContext context, void* pointer, Size align, Size size, const char* file, int line);
|
|
void (*init)(MemoryContext context);
|
|
void (*reset)(MemoryContext context);
|
|
void (*delete_context)(MemoryContext context);
|
|
Size (*get_chunk_space)(MemoryContext context, void* pointer);
|
|
bool (*is_empty)(MemoryContext context);
|
|
void (*stats)(MemoryContext context, int level);
|
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
void (*check)(MemoryContext context);
|
|
#endif
|
|
} MemoryContextMethods;
|
|
|
|
typedef struct MemoryTrackData* MemoryTrack; /* forward reference */
|
|
|
|
typedef struct MemoryTrackData {
|
|
NodeTag type; /* identifies exact kind of context */
|
|
MemoryTrack parent; /* NULL if no parent (toplevel context) */
|
|
MemoryTrack firstchild; /* head of linked list of children */
|
|
MemoryTrack nextchild; /* next child of same parent */
|
|
char* name; /* context name */
|
|
Size peakSpace; /* the peak bytes allocated by this context */
|
|
Size allBytesPeak; /* the peak bytes allocated by this and its children's context */
|
|
Size allBytesAlloc; /* all bytes allocated by this and its children's context */
|
|
Size allBytesFreed; /* all bytes freed by this and its children's context */
|
|
int sequentCount; /* the sequent count when creating in the thread */
|
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
bool isTracking; /* flag to indicate which is tracked by memory_detail_tracking setting */
|
|
#endif
|
|
} MemoryTrackData;
|
|
|
|
typedef struct MemoryContextData {
|
|
NodeTag type; /* identifies exact kind of context */
|
|
MemoryContextMethods* methods; /* virtual function table */
|
|
MemoryContext parent; /* NULL if no parent (toplevel context) */
|
|
MemoryContext firstchild; /* head of linked list of children */
|
|
MemoryContext prevchild; /* previous child of same parent */
|
|
MemoryContext nextchild; /* next child of same parent */
|
|
char* name; /* context name (just for debugging) */
|
|
pthread_rwlock_t lock; /* lock to protect members if the context is shared */
|
|
bool is_sealed; /* sealed context prevent any memory change */
|
|
bool is_shared; /* context is shared by threads */
|
|
bool isReset; /* T = no space alloced since last reset */
|
|
int level; /* context level */
|
|
uint64 session_id; /* session id of context owner */
|
|
ThreadId thread_id; /* thread id of context owner */
|
|
ListCell cell; /* cell to pointer to this context*/
|
|
} MemoryContextData;
|
|
|
|
#define MemoryContextIsShared(context) (((MemoryContextData*)(context))->is_shared)
|
|
|
|
#define MemoryContextLock(context) \
|
|
do { \
|
|
START_CRIT_SECTION(); \
|
|
int err = pthread_rwlock_wrlock(&((MemoryContextData*)(context))->lock); \
|
|
if (err != 0) { \
|
|
END_CRIT_SECTION(); \
|
|
ereport(ERROR, \
|
|
(errcode(ERRCODE_LOCK_NOT_AVAILABLE), \
|
|
errmsg("system call failed when lock, errno:%d.", err))); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define MemoryContextUnlock(context) \
|
|
do { \
|
|
int unlock_err = pthread_rwlock_unlock(&((MemoryContextData*)(context))->lock); \
|
|
if (unlock_err != 0) { \
|
|
END_CRIT_SECTION(); \
|
|
ereport(PANIC, \
|
|
(errcode(ERRCODE_LOCK_NOT_AVAILABLE), \
|
|
errmsg("system call failed when unlock, errno:%d.", unlock_err))); \
|
|
} \
|
|
END_CRIT_SECTION(); \
|
|
} while (0)
|
|
|
|
typedef struct AllocBlockData* AllocBlock; /* forward reference */
|
|
typedef struct AllocChunkData* AllocChunk;
|
|
typedef struct AsanBlockData* AsanBlock;
|
|
/*
|
|
* AllocPointer
|
|
* Aligned pointer which may be a member of an allocation set.
|
|
*/
|
|
typedef void* AllocPointer;
|
|
|
|
#define ALLOCSET_NUM_FREELISTS 11
|
|
|
|
/*
|
|
* AllocSetContext is our standard implementation of MemoryContext.
|
|
*
|
|
* Note: header.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 {
|
|
MemoryContextData header; /* Standard memory-context fields */
|
|
/* 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 */
|
|
/* Allocation parameters for this context: */
|
|
Size initBlockSize; /* initial block size */
|
|
Size maxBlockSize; /* maximum block size */
|
|
Size nextBlockSize; /* next block size to allocate */
|
|
Size allocChunkLimit; /* effective chunk size limit */
|
|
AllocBlock keeper; /* if not NULL, keep this block over resets */
|
|
Size totalSpace; /* all bytes allocated by this context */
|
|
Size freeSpace; /* all bytes freed by this context */
|
|
|
|
/* maximum memory allocation of MemoryContext.For more information,we could see @StackSetContext too. */
|
|
Size maxSpaceSize;
|
|
|
|
MemoryTrack track; /* used to track the memory allocation information */
|
|
} AllocSetContext;
|
|
|
|
typedef AllocSetContext* AllocSet;
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
typedef struct AllocBlockData {
|
|
AllocSet aset; /* aset that owns this block */
|
|
AllocBlock prev; /* prev block in aset's blocks list, if any */
|
|
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 */
|
|
Size allocSize; /* allocated size */
|
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
uint64 magicNum; /* DADA */
|
|
#endif
|
|
} AllocBlockData;
|
|
|
|
#define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
|
|
/* AsanSetContext is our asan implementation of MemoryContext.
|
|
* Note:
|
|
* AsanSetContext's structure must be consistent with AllocSetContext.
|
|
* header.isReset means there is nothing for AsanSetContext 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 AsanSetContext {
|
|
MemoryContextData header; /* Standard memory-context fields */
|
|
/* Info about storage allocated in this context: */
|
|
AsanBlock blocks; /* head of list of blocks in this set */
|
|
char* reserve[ALLOCSET_NUM_FREELISTS]; /* Allocation parameters for this context: */
|
|
Size initBlockSize; /* initial block size */
|
|
Size maxBlockSize; /* maximum block size */
|
|
Size nextBlockSize; /* next block size to allocate */
|
|
Size allocChunkLimit; /* effective chunk size limit */
|
|
AsanBlock keeper; /* if not NULL, keep this block over resets */
|
|
Size totalSpace; /* all bytes allocated by this context */
|
|
Size freeSpace; /* all bytes freed by this context */
|
|
/* maximum memory allocation of MemoryContext.For more information,we could see @StackSetContext too. */
|
|
Size maxSpaceSize;
|
|
MemoryTrack track; /* used to track the memory allocation information */
|
|
} AsanSetContext;
|
|
|
|
typedef AsanSetContext* AsanSet;
|
|
|
|
typedef struct AsanBlockData {
|
|
AsanSet aset; /* aset that owns this block */
|
|
AsanBlock prev; /* prev block in aset's blocks list, if any */
|
|
AsanBlock next; /* next block in aset's blocks list */
|
|
uint32 requestSize; /* request size */
|
|
int line; /* __LINE__ of palloc/palloc0 call */
|
|
const char* file; /* __FILE__ of palloc/palloc0 call */
|
|
} AsanBlockData;
|
|
|
|
#define ASAN_BLOCKHDRSZ MAXALIGN(sizeof(AsanBlockData))
|
|
/* utils/palloc.h contains typedef struct MemoryContextData *MemoryContext */
|
|
typedef struct StackBlockData* StackBlock;
|
|
|
|
typedef struct StackSetContext {
|
|
MemoryContextData header; /* Standard memory-context fields */
|
|
StackBlock blocks;
|
|
StackBlock freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
|
|
|
|
// Allocation parameters for this context:
|
|
//
|
|
Size initBlockSize; // initial block size
|
|
Size maxBlockSize; // maximum block size
|
|
Size nextBlockSize; // next block size
|
|
Size allocChunkLimit; // limit chunk
|
|
StackBlock keeper;
|
|
Size totalSpace;
|
|
Size freeSpace;
|
|
|
|
/* The parameter named maxSpaceSize is an allocation parameter,but this parameter must be here.
|
|
* Otherwise the pointer of MemoryContextMethods will be out-of-order.
|
|
* So AllocSetContext is.You can see @AllocSetContext
|
|
*/
|
|
Size maxSpaceSize;
|
|
MemoryTrack track; /* used to track the memory allocation information */
|
|
} StackSetContext;
|
|
|
|
typedef struct MemoryProtectFuncDef {
|
|
void* (*malloc)(Size sz, bool needProtect);
|
|
void (*free)(void* ptr, Size sz);
|
|
void* (*realloc)(void* ptr, Size oldsz, Size newsz, bool needProtect);
|
|
int (*memalign)(void** memptr, Size alignment, Size sz, bool needProtect);
|
|
} MemoryProtectFuncDef;
|
|
|
|
extern MemoryProtectFuncDef GenericFunctions;
|
|
extern MemoryProtectFuncDef SessionFunctions;
|
|
extern MemoryProtectFuncDef SharedFunctions;
|
|
|
|
/*
|
|
* MemoryContextIsValid
|
|
* True iff memory context is valid.
|
|
*
|
|
* Add new context types to the set accepted by this macro.
|
|
*/
|
|
#define MemoryContextIsValid(context) \
|
|
((context) != NULL && \
|
|
(IsA((context), AllocSetContext) || IsA((context), AsanSetContext) || IsA((context), StackAllocSetContext) || \
|
|
IsA((context), SharedAllocSetContext) || IsA((context), MemalignAllocSetContext) || \
|
|
IsA((context), MemalignSharedAllocSetContext)))
|
|
|
|
#define AllocSetContextUsedSpace(aset) ((aset)->totalSpace - (aset)->freeSpace)
|
|
|
|
typedef struct SessMemoryUsage {
|
|
uint64 sessid;
|
|
int64 usedSize;
|
|
int state;
|
|
} SessMemoryUsage;
|
|
|
|
#endif /* MEMNODES_H */
|
|
|