📄 mcxt.c
字号:
(*context->methods->check) (context); for (child = context->firstchild; child != NULL; child = child->nextchild) MemoryContextCheck(child);}#endif/* * MemoryContextContains * Detect whether an allocated chunk of memory belongs to a given * context or not. * * 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. */boolMemoryContextContains(MemoryContext context, 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. */ if (pointer == NULL || pointer != (void *) MAXALIGN(pointer)) return false; /* * OK, it's probably safe to look at the chunk header. */ header = (StandardChunkHeader *) ((char *) pointer - STANDARDCHUNKHEADERSIZE); /* * If the context link doesn't match then we certainly have a non-member * chunk. Also check for a reasonable-looking size as extra guard against * being fooled by bogus pointers. */ if (header->context == context && AllocSizeIsValid(header->size)) return true; return false;}/*-------------------- * 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, * plus space for the name. If this fails we can ereport() with no * 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... * * Normally, the context node and the name are allocated from * TopMemoryContext (NOT from the parent context, since the node must * survive resets of its parent context!). However, this routine is itself * 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. *-------------------- */MemoryContextMemoryContextCreate(NodeTag tag, Size size, MemoryContextMethods *methods, MemoryContext parent, const char *name){ MemoryContext node; Size needed = size + strlen(name) + 1; /* 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); } /* 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; 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) */ if (parent) { node->parent = parent; node->nextchild = parent->firstchild; parent->firstchild = node; } /* Return to type-specific creation routine to finish up */ return node;}/* * MemoryContextAlloc * Allocate space within the specified context. * * This could be turned into a macro, but we'd have to import * nodes/memnodes.h into postgres.h which seems a bad idea. */void *MemoryContextAlloc(MemoryContext context, Size size){ AssertArg(MemoryContextIsValid(context)); if (!AllocSizeIsValid(size)) elog(ERROR, "invalid memory alloc request size %lu", (unsigned long) size); return (*context->methods->alloc) (context, size);}/* * MemoryContextAllocZero * Like MemoryContextAlloc, but clears allocated memory * * We could just call MemoryContextAlloc then clear the memory, but this * is a very common combination, so we provide the combined operation. */void *MemoryContextAllocZero(MemoryContext context, Size size){ void *ret; AssertArg(MemoryContextIsValid(context)); if (!AllocSizeIsValid(size)) elog(ERROR, "invalid memory alloc request size %lu", (unsigned long) size); ret = (*context->methods->alloc) (context, size); 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){ void *ret; AssertArg(MemoryContextIsValid(context)); if (!AllocSizeIsValid(size)) elog(ERROR, "invalid memory alloc request size %lu", (unsigned long) size); ret = (*context->methods->alloc) (context, size); MemSetLoop(ret, 0, size); return ret;}/* * pfree * Release an allocated chunk. */voidpfree(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)); (*header->context->methods->free_p) (header->context, pointer);}/* * repalloc * Adjust the size of a previously allocated chunk. */void *repalloc(void *pointer, Size size){ 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)); if (!AllocSizeIsValid(size)) elog(ERROR, "invalid memory alloc request size %lu", (unsigned long) size); return (*header->context->methods->realloc) (header->context, pointer, size);}/* * MemoryContextSwitchTo * Returns the current context; installs the given context. * * This is inlined when using GCC. * * TODO: investigate supporting inlining for some non-GCC compilers. */#ifndef __GNUC__MemoryContextMemoryContextSwitchTo(MemoryContext context){ MemoryContext old; AssertArg(MemoryContextIsValid(context)); old = CurrentMemoryContext; CurrentMemoryContext = context; return old;}#endif /* ! __GNUC__ *//* * MemoryContextStrdup * Like strdup(), but allocate from the specified context */char *MemoryContextStrdup(MemoryContext context, const char *string){ char *nstr; Size len = strlen(string) + 1; nstr = (char *) MemoryContextAlloc(context, len); memcpy(nstr, string, len); return nstr;}#if defined(WIN32) || defined(__CYGWIN__)/* * Memory support routines for libpgport on Win32 * * Win32 can't load a library that DLLIMPORTs a variable * if the link object files also DLLIMPORT the same variable. * For this reason, libpgport can't reference CurrentMemoryContext * in the palloc macro calls. * * To fix this, we create several functions here that allow us to * manage memory without doing the inline in libpgport. */void *pgport_palloc(Size sz){ return palloc(sz);}char *pgport_pstrdup(const char *str){ return pstrdup(str);}/* Doesn't reference a DLLIMPORT variable, but here for completeness. */voidpgport_pfree(void *pointer){ pfree(pointer);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -