1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-25 12:03:53 +03:00

Reduce size of common allocation header.

The new slab allocator needs different per-allocation information than
the classical aset.c.  The definition in 58b25e981 wasn't sufficiently
careful on 32 platforms with 8 byte alignment, leading to buildfarm
failures.  That's not entirely easy to fix by just adjusting the
definition.

As slab.c doesn't actually need the size part(s) of the common header,
all chunks are equally sized after all, it seems better to instead
reduce the header to the part needed by all allocators, namely which
context an allocation belongs to. That has the advantage of reducing
the overhead of slab allocations, and also allows for more flexibility
in future allocators.

To avoid spreading the logic about accessing a chunk's context around,
centralize it in GetMemoryChunkContext(), which allows to delete a
good number of lines.

A followup commit will revise the mmgr/README portion about
StandardChunkHeader, and more.

Author: Andres Freund
Discussion: https://postgr.es/m/20170228074420.aazv4iw6k562mnxg@alap3.anarazel.de
This commit is contained in:
Andres Freund
2017-02-27 23:32:22 -08:00
parent eb75f4fced
commit 7e3aa03b41
5 changed files with 97 additions and 218 deletions

View File

@@ -389,55 +389,10 @@ MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Size
GetMemoryChunkSpace(void *pointer)
{
StandardChunkHeader *header;
MemoryContext context = GetMemoryChunkContext(pointer);
/*
* 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);
}
/*
* 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;
return (context->methods->get_chunk_space) (context,
pointer);
}
/*
@@ -611,23 +566,9 @@ MemoryContextCheck(MemoryContext context)
bool
MemoryContextContains(MemoryContext context, void *pointer)
{
StandardChunkHeader *header;
MemoryContext ptr_context = GetMemoryChunkContext(pointer);
/*
* 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);
return header->context == context;
return ptr_context == context;
}
/*--------------------
@@ -991,23 +932,7 @@ palloc_extended(Size size, int flags)
void
pfree(void *pointer)
{
MemoryContext context;
/*
* 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.
*/
context = ((StandardChunkHeader *)
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
AssertArg(MemoryContextIsValid(context));
MemoryContext context = GetMemoryChunkContext(pointer);
(*context->methods->free_p) (context, pointer);
VALGRIND_MEMPOOL_FREE(context, pointer);
@@ -1020,27 +945,12 @@ pfree(void *pointer)
void *
repalloc(void *pointer, Size size)
{
MemoryContext context;
MemoryContext context = GetMemoryChunkContext(pointer);
void *ret;
if (!AllocSizeIsValid(size))
elog(ERROR, "invalid memory alloc request size %zu", size);
/*
* 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.
*/
context = ((StandardChunkHeader *)
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
AssertArg(MemoryContextIsValid(context));
AssertNotInCriticalSection(context);
/* isReset must be false already */
@@ -1103,27 +1013,12 @@ MemoryContextAllocHuge(MemoryContext context, Size size)
void *
repalloc_huge(void *pointer, Size size)
{
MemoryContext context;
MemoryContext context = GetMemoryChunkContext(pointer);
void *ret;
if (!AllocHugeSizeIsValid(size))
elog(ERROR, "invalid memory alloc request size %zu", size);
/*
* 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.
*/
context = ((StandardChunkHeader *)
((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
AssertArg(MemoryContextIsValid(context));
AssertNotInCriticalSection(context);
/* isReset must be false already */