mcxt.c 22.7 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * mcxt.c
4 5 6 7 8 9 10
 *	  POSTGRES memory context management code.
 *
 * This module handles context management operations that are independent
 * of the particular kind of context being operated on.  It calls
 * context-type-specific operations via the function pointers in a
 * context's MemoryContextMethods struct.
 *
11
 *
B
Bruce Momjian 已提交
12
 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
13
 * Portions Copyright (c) 1994, Regents of the University of California
14 15 16
 *
 *
 * IDENTIFICATION
17
 *	  src/backend/utils/mmgr/mcxt.c
18 19 20 21
 *
 *-------------------------------------------------------------------------
 */

A
Alvaro Herrera 已提交
22
/* see palloc.h.  Must be before postgres.h */
23 24
#define MCXT_INCLUDE_DEFINITIONS

A
Alvaro Herrera 已提交
25 26
#include "postgres.h"

27
#include "utils/memdebug.h"
28
#include "utils/memutils.h"
29 30 31


/*****************************************************************************
32
 *	  GLOBAL MEMORY															 *
33 34 35
 *****************************************************************************/

/*
B
Bruce Momjian 已提交
36
 * CurrentMemoryContext
37
 *		Default memory context for allocations.
38
 */
39
MemoryContext CurrentMemoryContext = NULL;
40 41

/*
42 43
 * Standard top-level contexts. For a description of the purpose of each
 * of these contexts, refer to src/backend/utils/mmgr/README
44
 */
45 46 47 48
MemoryContext TopMemoryContext = NULL;
MemoryContext ErrorContext = NULL;
MemoryContext PostmasterContext = NULL;
MemoryContext CacheMemoryContext = NULL;
49
MemoryContext MessageContext = NULL;
50
MemoryContext TopTransactionContext = NULL;
51
MemoryContext CurTransactionContext = NULL;
B
Bruce Momjian 已提交
52

53
/* This is a transient link to the active portal's memory context: */
54
MemoryContext PortalContext = NULL;
55

56 57
static void MemoryContextStatsInternal(MemoryContext context, int level);

58

59 60 61
/*****************************************************************************
 *	  EXPORTED ROUTINES														 *
 *****************************************************************************/
62 63 64


/*
65 66
 * MemoryContextInit
 *		Start up the memory-context subsystem.
67
 *
68 69 70
 * This must be called before creating contexts or allocating memory in
 * contexts.  TopMemoryContext and ErrorContext are initialized here;
 * other contexts must be created afterwards.
71
 *
72 73 74
 * In normal multi-backend operation, this is called once during
 * postmaster startup, and not at all by individual backend startup
 * (since the backends inherit an already-initialized context subsystem
75 76
 * by virtue of being forked off the postmaster).  But in an EXEC_BACKEND
 * build, each process must do this for itself.
77
 *
78
 * In a standalone backend this must be called during backend startup.
79 80
 */
void
81
MemoryContextInit(void)
82
{
83
	AssertState(TopMemoryContext == NULL);
B
Bruce Momjian 已提交
84

85
	/*
B
Bruce Momjian 已提交
86 87
	 * Initialize TopMemoryContext as an AllocSetContext with slow growth rate
	 * --- we don't really expect much to be allocated in it.
88 89 90 91 92
	 *
	 * (There is special-case code in MemoryContextCreate() for this call.)
	 */
	TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
											 "TopMemoryContext",
93
											 0,
94 95
											 8 * 1024,
											 8 * 1024);
B
Bruce Momjian 已提交
96

97
	/*
B
Bruce Momjian 已提交
98 99
	 * Not having any other place to point CurrentMemoryContext, make it point
	 * to TopMemoryContext.  Caller should change this soon!
100 101
	 */
	CurrentMemoryContext = TopMemoryContext;
B
Bruce Momjian 已提交
102

103
	/*
B
Bruce Momjian 已提交
104 105 106 107 108 109
	 * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
	 * we don't really expect much to be allocated in it. More to the point,
	 * require it to contain at least 8K at all times. This is the only case
	 * where retained memory in a context is *essential* --- we want to be
	 * sure ErrorContext still has some memory even if we've run out
	 * elsewhere!
110 111 112
	 *
	 * This should be the last step in this function, as elog.c assumes memory
	 * management works once ErrorContext is non-null.
113 114 115 116 117 118
	 */
	ErrorContext = AllocSetContextCreate(TopMemoryContext,
										 "ErrorContext",
										 8 * 1024,
										 8 * 1024,
										 8 * 1024);
119 120 121
}

/*
122 123 124
 * MemoryContextReset
 *		Release all space allocated within a context and its descendants,
 *		but don't delete the contexts themselves.
125
 *
126 127
 * The type-specific reset routine handles the context itself, but we
 * have to do the recursion for the children.
128
 */
129 130
void
MemoryContextReset(MemoryContext context)
131
{
T
Tom Lane 已提交
132 133
	AssertArg(MemoryContextIsValid(context));

134 135 136 137
	/* save a function call in common case where there are no children */
	if (context->firstchild != NULL)
		MemoryContextResetChildren(context);

138 139 140 141 142
	/* Nothing to do if no pallocs since startup or last reset */
	if (!context->isReset)
	{
		(*context->methods->reset) (context);
		context->isReset = true;
143 144
		VALGRIND_DESTROY_MEMPOOL(context);
		VALGRIND_CREATE_MEMPOOL(context, 0, false);
145
	}
146 147 148
}

/*
149 150 151 152
 * MemoryContextResetChildren
 *		Release all space allocated within a context's descendants,
 *		but don't delete the contexts themselves.  The named context
 *		itself is not touched.
153 154
 */
void
155
MemoryContextResetChildren(MemoryContext context)
156
{
B
Bruce Momjian 已提交
157
	MemoryContext child;
158

T
Tom Lane 已提交
159 160
	AssertArg(MemoryContextIsValid(context));

161 162
	for (child = context->firstchild; child != NULL; child = child->nextchild)
		MemoryContextReset(child);
163 164 165
}

/*
166 167 168
 * MemoryContextDelete
 *		Delete a context and its descendants, and release all space
 *		allocated therein.
169
 *
170 171
 * The type-specific delete routine removes all subsidiary storage
 * for the context, but we have to delete the context node itself,
B
Bruce Momjian 已提交
172
 * as well as recurse to get the children.	We must also delink the
173
 * node from its parent, if it has one.
174
 */
175 176
void
MemoryContextDelete(MemoryContext context)
177
{
T
Tom Lane 已提交
178
	AssertArg(MemoryContextIsValid(context));
179 180 181 182 183 184
	/* We had better not be deleting TopMemoryContext ... */
	Assert(context != TopMemoryContext);
	/* And not CurrentMemoryContext, either */
	Assert(context != CurrentMemoryContext);

	MemoryContextDeleteChildren(context);
B
Bruce Momjian 已提交
185

186
	/*
B
Bruce Momjian 已提交
187 188 189
	 * We delink the context from its parent before deleting it, so that if
	 * there's an error we won't have deleted/busted contexts still attached
	 * to the context tree.  Better a leak than a crash.
190
	 */
191
	MemoryContextSetParent(context, NULL);
192

193
	(*context->methods->delete_context) (context);
194
	VALGRIND_DESTROY_MEMPOOL(context);
195
	pfree(context);
196 197 198
}

/*
199 200 201
 * MemoryContextDeleteChildren
 *		Delete all the descendants of the named context and release all
 *		space allocated therein.  The named context itself is not touched.
202
 */
203 204
void
MemoryContextDeleteChildren(MemoryContext context)
205
{
T
Tom Lane 已提交
206
	AssertArg(MemoryContextIsValid(context));
B
Bruce Momjian 已提交
207

208
	/*
B
Bruce Momjian 已提交
209 210
	 * MemoryContextDelete will delink the child from me, so just iterate as
	 * long as there is a child.
211 212 213
	 */
	while (context->firstchild != NULL)
		MemoryContextDelete(context->firstchild);
214
}
215

216
/*
217 218 219
 * MemoryContextResetAndDeleteChildren
 *		Release all space allocated within a context and delete all
 *		its descendants.
220
 *
221 222
 * This is a common combination case where we want to preserve the
 * specific context but get rid of absolutely everything under it.
223
 */
224 225
void
MemoryContextResetAndDeleteChildren(MemoryContext context)
226
{
T
Tom Lane 已提交
227 228
	AssertArg(MemoryContextIsValid(context));

229
	MemoryContextDeleteChildren(context);
T
Tom Lane 已提交
230
	MemoryContextReset(context);
231
}
232

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
/*
 * MemoryContextSetParent
 *		Change a context to belong to a new parent (or no parent).
 *
 * We provide this as an API function because it is sometimes useful to
 * change a context's lifespan after creation.  For example, a context
 * might be created underneath a transient context, filled with data,
 * and then reparented underneath CacheMemoryContext to make it long-lived.
 * In this way no special effort is needed to get rid of the context in case
 * a failure occurs before its contents are completely set up.
 *
 * Callers often assume that this function cannot fail, so don't put any
 * elog(ERROR) calls in it.
 *
 * A possible caller error is to reparent a context under itself, creating
 * a loop in the context graph.  We assert here that context != new_parent,
 * but checking for multi-level loops seems more trouble than it's worth.
 */
void
MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
{
	AssertArg(MemoryContextIsValid(context));
	AssertArg(context != new_parent);

	/* Delink from existing parent, if any */
	if (context->parent)
	{
		MemoryContext parent = context->parent;

		if (context == parent->firstchild)
			parent->firstchild = context->nextchild;
		else
		{
			MemoryContext child;

			for (child = parent->firstchild; child; child = child->nextchild)
			{
				if (context == child->nextchild)
				{
					child->nextchild = context->nextchild;
					break;
				}
			}
		}
	}

	/* And relink */
	if (new_parent)
	{
		AssertArg(MemoryContextIsValid(new_parent));
		context->parent = new_parent;
		context->nextchild = new_parent->firstchild;
		new_parent->firstchild = context;
	}
	else
	{
		context->parent = NULL;
		context->nextchild = NULL;
	}
}

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
/*
 * GetMemoryChunkSpace
 *		Given a currently-allocated chunk, determine the total space
 *		it occupies (including all memory-allocation overhead).
 *
 * This is useful for measuring the total space occupied by a set of
 * allocated chunks.
 */
Size
GetMemoryChunkSpace(void *pointer)
{
	StandardChunkHeader *header;

	/*
	 * 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 chunk header.
	 */
	header = (StandardChunkHeader *)
		((char *) pointer - STANDARDCHUNKHEADERSIZE);

	AssertArg(MemoryContextIsValid(header->context));

	return (*header->context->methods->get_chunk_space) (header->context,
														 pointer);
}

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
/*
 * GetMemoryChunkContext
 *		Given a currently-allocated chunk, determine the context
 *		it belongs to.
 */
MemoryContext
GetMemoryChunkContext(void *pointer)
{
	StandardChunkHeader *header;

	/*
	 * 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 chunk header.
	 */
	header = (StandardChunkHeader *)
		((char *) pointer - STANDARDCHUNKHEADERSIZE);

	AssertArg(MemoryContextIsValid(header->context));

	return header->context;
}

356 357 358 359 360 361 362 363 364 365 366 367
/*
 * MemoryContextGetParent
 *		Get the parent context (if any) of the specified context
 */
MemoryContext
MemoryContextGetParent(MemoryContext context)
{
	AssertArg(MemoryContextIsValid(context));

	return context->parent;
}

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
/*
 * MemoryContextIsEmpty
 *		Is a memory context empty of any allocated space?
 */
bool
MemoryContextIsEmpty(MemoryContext context)
{
	AssertArg(MemoryContextIsValid(context));

	/*
	 * For now, we consider a memory context nonempty if it has any children;
	 * perhaps this should be changed later.
	 */
	if (context->firstchild != NULL)
		return false;
	/* Otherwise use the type-specific inquiry */
	return (*context->methods->is_empty) (context);
}

387
/*
388 389
 * MemoryContextStats
 *		Print statistics about the named context and all its descendants.
390
 *
391 392
 * This is just a debugging utility, so it's not fancy.  The statistics
 * are merely sent to stderr.
393
 */
394 395
void
MemoryContextStats(MemoryContext context)
396 397 398 399 400 401
{
	MemoryContextStatsInternal(context, 0);
}

static void
MemoryContextStatsInternal(MemoryContext context, int level)
402
{
B
Bruce Momjian 已提交
403
	MemoryContext child;
404

T
Tom Lane 已提交
405 406
	AssertArg(MemoryContextIsValid(context));

407
	(*context->methods->stats) (context, level);
408
	for (child = context->firstchild; child != NULL; child = child->nextchild)
409
		MemoryContextStatsInternal(child, level + 1);
410 411
}

412 413 414 415
/*
 * MemoryContextCheck
 *		Check all chunks in the named context.
 *
B
Bruce Momjian 已提交
416
 * This is just a debugging utility, so it's not fancy.
417 418 419 420 421
 */
#ifdef MEMORY_CONTEXT_CHECKING
void
MemoryContextCheck(MemoryContext context)
{
B
Bruce Momjian 已提交
422
	MemoryContext child;
423

T
Tom Lane 已提交
424 425
	AssertArg(MemoryContextIsValid(context));

426 427 428 429 430 431
	(*context->methods->check) (context);
	for (child = context->firstchild; child != NULL; child = child->nextchild)
		MemoryContextCheck(child);
}
#endif

432
/*
433 434 435
 * MemoryContextContains
 *		Detect whether an allocated chunk of memory belongs to a given
 *		context or not.
436
 *
437 438 439 440 441
 * Caution: this test is reliable as long as 'pointer' does point to
 * a chunk of memory allocated from *some* context.  If 'pointer' points
 * at memory obtained in some other way, there is a small chance of a
 * false-positive result, since the bits right before it might look like
 * a valid chunk header by chance.
442
 */
443 444
bool
MemoryContextContains(MemoryContext context, void *pointer)
445
{
B
Bruce Momjian 已提交
446
	StandardChunkHeader *header;
447 448 449

	/*
	 * Try to detect bogus pointers handed to us, poorly though we can.
B
Bruce Momjian 已提交
450 451
	 * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
	 * allocated chunk.
452 453 454
	 */
	if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
		return false;
B
Bruce Momjian 已提交
455

456 457 458 459 460
	/*
	 * OK, it's probably safe to look at the chunk header.
	 */
	header = (StandardChunkHeader *)
		((char *) pointer - STANDARDCHUNKHEADERSIZE);
B
Bruce Momjian 已提交
461

462
	return header->context == context;
463 464
}

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
/*--------------------
 * MemoryContextCreate
 *		Context-type-independent part of context creation.
 *
 * This is only intended to be called by context-type-specific
 * context creation routines, not by the unwashed masses.
 *
 * The context creation procedure is a little bit tricky because
 * we want to be sure that we don't leave the context tree invalid
 * in case of failure (such as insufficient memory to allocate the
 * context node itself).  The procedure goes like this:
 *	1.	Context-type-specific routine first calls MemoryContextCreate(),
 *		passing the appropriate tag/size/methods values (the methods
 *		pointer will ordinarily point to statically allocated data).
 *		The parent and name parameters usually come from the caller.
 *	2.	MemoryContextCreate() attempts to allocate the context node,
481
 *		plus space for the name.  If this fails we can ereport() with no
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
 *		damage done.
 *	3.	We fill in all of the type-independent MemoryContext fields.
 *	4.	We call the type-specific init routine (using the methods pointer).
 *		The init routine is required to make the node minimally valid
 *		with zero chance of failure --- it can't allocate more memory,
 *		for example.
 *	5.	Now we have a minimally valid node that can behave correctly
 *		when told to reset or delete itself.  We link the node to its
 *		parent (if any), making the node part of the context tree.
 *	6.	We return to the context-type-specific routine, which finishes
 *		up type-specific initialization.  This routine can now do things
 *		that might fail (like allocate more memory), so long as it's
 *		sure the node is left in a state that delete will handle.
 *
 * This protocol doesn't prevent us from leaking memory if step 6 fails
 * during creation of a top-level context, since there's no parent link
 * in that case.  However, if you run out of memory while you're building
 * a top-level context, you might as well go home anyway...
500
 *
501 502
 * Normally, the context node and the name are allocated from
 * TopMemoryContext (NOT from the parent context, since the node must
B
Bruce Momjian 已提交
503
 * survive resets of its parent context!).	However, this routine is itself
504 505 506 507 508 509 510 511
 * used to create TopMemoryContext!  If we see that TopMemoryContext is NULL,
 * we assume we are creating TopMemoryContext and use malloc() to allocate
 * the node.
 *
 * Note that the name field of a MemoryContext does not point to
 * separately-allocated storage, so it should not be freed at context
 * deletion.
 *--------------------
512
 */
513 514 515 516 517
MemoryContext
MemoryContextCreate(NodeTag tag, Size size,
					MemoryContextMethods *methods,
					MemoryContext parent,
					const char *name)
518
{
B
Bruce Momjian 已提交
519 520
	MemoryContext node;
	Size		needed = size + strlen(name) + 1;
521

522 523 524 525 526 527 528 529 530 531 532 533 534
	/* Get space for node and name */
	if (TopMemoryContext != NULL)
	{
		/* Normal case: allocate the node in TopMemoryContext */
		node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
												  needed);
	}
	else
	{
		/* Special case for startup: use good ol' malloc */
		node = (MemoryContext) malloc(needed);
		Assert(node != NULL);
	}
535

536 537 538 539 540 541 542
	/* Initialize the node as best we can */
	MemSet(node, 0, size);
	node->type = tag;
	node->methods = methods;
	node->parent = NULL;		/* for the moment */
	node->firstchild = NULL;
	node->nextchild = NULL;
543
	node->isReset = true;
544 545 546 547 548 549 550
	node->name = ((char *) node) + size;
	strcpy(node->name, name);

	/* Type-specific routine finishes any other essential initialization */
	(*node->methods->init) (node);

	/* OK to link node to parent (if any) */
551
	/* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
552 553 554 555 556 557
	if (parent)
	{
		node->parent = parent;
		node->nextchild = parent->firstchild;
		parent->firstchild = node;
	}
558

559 560
	VALGRIND_CREATE_MEMPOOL(node, 0, false);

561 562
	/* Return to type-specific creation routine to finish up */
	return node;
563 564 565
}

/*
566 567
 * MemoryContextAlloc
 *		Allocate space within the specified context.
568
 *
569 570
 * This could be turned into a macro, but we'd have to import
 * nodes/memnodes.h into postgres.h which seems a bad idea.
571
 */
572 573
void *
MemoryContextAlloc(MemoryContext context, Size size)
574
{
575 576
	void	   *ret;

577
	AssertArg(MemoryContextIsValid(context));
578

579
	if (!AllocSizeIsValid(size))
580
		elog(ERROR, "invalid memory alloc request size %zu", size);
581

582
	context->isReset = false;
T
Tom Lane 已提交
583

584
	ret = (*context->methods->alloc) (context, size);
585
	VALGRIND_MEMPOOL_ALLOC(context, ret, size);
586 587

	return ret;
588 589
}

590
/*
591
 * MemoryContextAllocZero
592 593 594
 *		Like MemoryContextAlloc, but clears allocated memory
 *
 *	We could just call MemoryContextAlloc then clear the memory, but this
595
 *	is a very common combination, so we provide the combined operation.
596 597
 */
void *
598
MemoryContextAllocZero(MemoryContext context, Size size)
599
{
B
Bruce Momjian 已提交
600
	void	   *ret;
601 602 603 604

	AssertArg(MemoryContextIsValid(context));

	if (!AllocSizeIsValid(size))
605
		elog(ERROR, "invalid memory alloc request size %zu", size);
606

T
Tom Lane 已提交
607 608
	context->isReset = false;

609
	ret = (*context->methods->alloc) (context, size);
610
	VALGRIND_MEMPOOL_ALLOC(context, ret, size);
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626

	MemSetAligned(ret, 0, size);

	return ret;
}

/*
 * MemoryContextAllocZeroAligned
 *		MemoryContextAllocZero where length is suitable for MemSetLoop
 *
 *	This might seem overly specialized, but it's not because newNode()
 *	is so often called with compile-time-constant sizes.
 */
void *
MemoryContextAllocZeroAligned(MemoryContext context, Size size)
{
B
Bruce Momjian 已提交
627
	void	   *ret;
628 629 630 631

	AssertArg(MemoryContextIsValid(context));

	if (!AllocSizeIsValid(size))
632
		elog(ERROR, "invalid memory alloc request size %zu", size);
633

T
Tom Lane 已提交
634 635
	context->isReset = false;

636
	ret = (*context->methods->alloc) (context, size);
637
	VALGRIND_MEMPOOL_ALLOC(context, ret, size);
638

639
	MemSetLoop(ret, 0, size);
640

641 642 643
	return ret;
}

644 645 646 647
void *
palloc(Size size)
{
	/* duplicates MemoryContextAlloc to avoid increased overhead */
648 649
	void	   *ret;

650 651 652
	AssertArg(MemoryContextIsValid(CurrentMemoryContext));

	if (!AllocSizeIsValid(size))
653
		elog(ERROR, "invalid memory alloc request size %zu", size);
654 655 656

	CurrentMemoryContext->isReset = false;

657
	ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
658
	VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
659 660

	return ret;
661 662 663 664 665 666 667 668 669 670 671
}

void *
palloc0(Size size)
{
	/* duplicates MemoryContextAllocZero to avoid increased overhead */
	void	   *ret;

	AssertArg(MemoryContextIsValid(CurrentMemoryContext));

	if (!AllocSizeIsValid(size))
672
		elog(ERROR, "invalid memory alloc request size %zu", size);
673 674 675 676

	CurrentMemoryContext->isReset = false;

	ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
677
	VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
678 679 680 681 682 683

	MemSetAligned(ret, 0, size);

	return ret;
}

684
/*
685 686
 * pfree
 *		Release an allocated chunk.
687
 */
688 689
void
pfree(void *pointer)
690
{
691
	MemoryContext context;
692 693 694

	/*
	 * Try to detect bogus pointers handed to us, poorly though we can.
B
Bruce Momjian 已提交
695 696
	 * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
	 * allocated chunk.
697 698 699
	 */
	Assert(pointer != NULL);
	Assert(pointer == (void *) MAXALIGN(pointer));
B
Bruce Momjian 已提交
700

701 702 703
	/*
	 * OK, it's probably safe to look at the chunk header.
	 */
704 705
	context = ((StandardChunkHeader *)
			   ((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
706

707
	AssertArg(MemoryContextIsValid(context));
708

709
	(*context->methods->free_p) (context, pointer);
710
	VALGRIND_MEMPOOL_FREE(context, pointer);
711 712 713
}

/*
714
 * repalloc
715
 *		Adjust the size of a previously allocated chunk.
716
 */
717 718
void *
repalloc(void *pointer, Size size)
719
{
720 721 722 723
	MemoryContext context;
	void	   *ret;

	if (!AllocSizeIsValid(size))
724
		elog(ERROR, "invalid memory alloc request size %zu", size);
725 726 727

	/*
	 * Try to detect bogus pointers handed to us, poorly though we can.
B
Bruce Momjian 已提交
728 729
	 * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
	 * allocated chunk.
730 731 732
	 */
	Assert(pointer != NULL);
	Assert(pointer == (void *) MAXALIGN(pointer));
B
Bruce Momjian 已提交
733

734 735
	/*
	 * OK, it's probably safe to look at the chunk header.
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
	 */
	context = ((StandardChunkHeader *)
			   ((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;

	AssertArg(MemoryContextIsValid(context));

	/* isReset must be false already */
	Assert(!context->isReset);

	ret = (*context->methods->realloc) (context, pointer, size);
	VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);

	return ret;
}

/*
 * MemoryContextAllocHuge
 *		Allocate (possibly-expansive) space within the specified context.
 *
 * See considerations in comment at MaxAllocHugeSize.
 */
void *
MemoryContextAllocHuge(MemoryContext context, Size size)
{
	void	   *ret;

	AssertArg(MemoryContextIsValid(context));

	if (!AllocHugeSizeIsValid(size))
765
		elog(ERROR, "invalid memory alloc request size %zu", size);
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786

	context->isReset = false;

	ret = (*context->methods->alloc) (context, size);
	VALGRIND_MEMPOOL_ALLOC(context, ret, size);

	return ret;
}

/*
 * repalloc_huge
 *		Adjust the size of a previously allocated chunk, permitting a large
 *		value.  The previous allocation need not have been "huge".
 */
void *
repalloc_huge(void *pointer, Size size)
{
	MemoryContext context;
	void	   *ret;

	if (!AllocHugeSizeIsValid(size))
787
		elog(ERROR, "invalid memory alloc request size %zu", size);
788 789 790 791 792 793 794 795 796 797 798

	/*
	 * 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 chunk header.
799
	 */
800 801
	context = ((StandardChunkHeader *)
			   ((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
802

803
	AssertArg(MemoryContextIsValid(context));
804

805
	/* isReset must be false already */
806 807 808
	Assert(!context->isReset);

	ret = (*context->methods->realloc) (context, pointer, size);
809
	VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
810

811
	return ret;
812 813
}

814
/*
815 816
 * MemoryContextStrdup
 *		Like strdup(), but allocate from the specified context
817
 */
818 819
char *
MemoryContextStrdup(MemoryContext context, const char *string)
820
{
821 822
	char	   *nstr;
	Size		len = strlen(string) + 1;
823

824
	nstr = (char *) MemoryContextAlloc(context, len);
825

826 827 828
	memcpy(nstr, string, len);

	return nstr;
829
}
830

831 832 833 834 835 836
char *
pstrdup(const char *in)
{
	return MemoryContextStrdup(CurrentMemoryContext, in);
}

837 838 839 840 841 842 843 844 845 846 847 848 849 850
/*
 * pnstrdup
 *		Like pstrdup(), but append null byte to a
 *		not-necessarily-null-terminated input string.
 */
char *
pnstrdup(const char *in, Size len)
{
	char	   *out = palloc(len + 1);

	memcpy(out, in, len);
	out[len] = '\0';
	return out;
}