summaryrefslogtreecommitdiff
path: root/src/include/utils/memutils.h
blob: 597ffc9b56bdbf7c242fb017e66492c47d92146b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*-------------------------------------------------------------------------
 *
 * 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-2015, 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) -1 >> 1)	/* SIZE_MAX / 2 */

#define AllocHugeSizeIsValid(size)	((Size) (size) <= MaxAllocHugeSize)

/*
 * You should not do memory allocations within a critical section, because
 * an out-of-memory error will be escalated to a PANIC. To enforce that
 * rule, the allocation functions Assert that.
 */
#define AssertNotInCriticalSection(context) \
	Assert(CritSectionCount == 0 || (context)->allowInCritSection)

/*
 * To save space, we cram a compact representation of the memory context
 * type, the specific memory context in use, and the size of the chunk into
 * a single 4-byte or 8-byte word prior to the start of the chunk.
 * It won't be possible to do this in all cases for lack of bit space;
 * but individual memory context implementations can use an extended header
 * which precedes the standard header in cases where it is needed.
 *
 * We allow three bits to represent the context type.  Considering that
 * we not had more than one context type any time in recent memory, this
 * seems likely to be adequate for some time to come.
 *
 * On systems with 8-byte alignment, we allow 29 bits for the context ID and
 * 32 bits for the size.  This allows for up to half a billion context IDs and
 * sizes of up to 1 byte less than 4GB.  Thus, extended headers should
 * almost never be required.  On systems with 4-byte alignment, we allow 20
 * bits for the context ID and 19 bits for the size, which allows for up to
 * 1 million possible context IDs and allocations of up to 511 bytes.
 * This should be good enough that most allocations won't need an extended
 * header, but some will.
 */
#define CHUNK_CONTEXT_TYPE_BITS		3
#if MAXIMUM_ALIGNOF == 8
typedef uint64 chunk_unsigned;
#define CHUNK_CONTEXT_ID_BITS		29
#define CHUNK_SIZE_BITS				32
#else
typedef uint32 chunk_unsigned;
#define CHUNK_CONTEXT_ID_BITS		20
#define CHUNK_SIZE_BITS				9
#endif

/* Context type codes; must be less than 1 << CHUNK_CONTEXT_TYPE_BITS. */
#define CHUNK_CONTEXT_TYPE_ASET		0

/*
 * All chunks allocated by any memory context manager are required to be
 * preceded by a StandardChunkHeader at a spacing of STANDARDCHUNKHEADERSIZE,
 * which should be 8 bytes on systems where MAXIMUM_ALIGNOF is 8, and 4 bytes
 * everywhere else.
 *
 * The memory context machinery looks at chunk_context_type to figure out
 * which routine to call when memory is freed.
 *
 * The interpretation of the chunk_context_id is partially at the discretion
 * of the individual context implementation, but should not differ for two
 * chunks that are in fact part of the same context.
 *
 * The chunk_size should be the actual size of the allocated chunk, unless
 * it is zero, in which case the size may be anything.
 */
typedef struct StandardChunkHeader
{
	chunk_unsigned chunk_context_type:CHUNK_CONTEXT_TYPE_BITS;
	chunk_unsigned chunk_context_id:CHUNK_CONTEXT_ID_BITS;
	chunk_unsigned chunk_size:CHUNK_SIZE_BITS;
} StandardChunkHeader;

#define STANDARDCHUNKHEADERSIZE  MAXALIGN(sizeof(StandardChunkHeader))

/*
 * 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 MemoryContextSetParent(MemoryContext context,
					   MemoryContext new_parent);
extern Size GetMemoryChunkSpace(void *pointer);
extern MemoryContext GetMemoryChunkContext(void *pointer);
extern MemoryContext MemoryContextGetParent(MemoryContext context);
extern bool MemoryContextIsEmpty(MemoryContext context);
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);

/*
 * 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 MemoryContextSetup(MemoryContext node, MemoryContext parent);


/*
 * Memory-context-type-specific functions
 */

/* aset.c */
extern MemoryContext AllocSetContextCreate(MemoryContext parent,
					  const char *name,
					  Size minContextSize,
					  Size initBlockSize,
					  Size maxBlockSize);

/* Private methods only intended to be called from mcxt.c */
extern void AllocSetFree(void *pointer,
			 chunk_unsigned context_id,
			 chunk_unsigned size);
extern void *AllocSetRealloc(void *pointer,
				chunk_unsigned context_id,
				chunk_unsigned size);
extern Size AllocSetGetChunkSpace(void *pointer,
				chunk_unsigned context_id,
				chunk_unsigned size);
extern MemoryContext AllocSetGetChunkContext(void *pointer,
				chunk_unsigned context_id);

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

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

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

#endif   /* MEMUTILS_H */