Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * alignedalloc.c
4 : * Allocator functions to implement palloc_aligned
5 : *
6 : * This is not a fully-fledged MemoryContext type as there is no means to
7 : * create a MemoryContext of this type. The code here only serves to allow
8 : * operations such as pfree() and repalloc() to work correctly on a memory
9 : * chunk that was allocated by palloc_aligned().
10 : *
11 : * Portions Copyright (c) 2022-2023, PostgreSQL Global Development Group
12 : *
13 : * IDENTIFICATION
14 : * src/backend/utils/mmgr/alignedalloc.c
15 : *
16 : *-------------------------------------------------------------------------
17 : */
18 :
19 : #include "postgres.h"
20 :
21 : #include "utils/memdebug.h"
22 : #include "utils/memutils_memorychunk.h"
23 :
24 : /*
25 : * AlignedAllocFree
26 : * Frees allocated memory; memory is removed from its owning context.
27 : */
28 : void
108 drowley 29 GNC 234297 : AlignedAllocFree(void *pointer)
30 : {
31 234297 : MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
32 : void *unaligned;
33 :
34 234297 : Assert(!MemoryChunkIsExternal(chunk));
35 :
36 : /* obtain the original (unaligned) allocated pointer */
37 234297 : unaligned = MemoryChunkGetBlock(chunk);
38 :
39 : #ifdef MEMORY_CONTEXT_CHECKING
40 : /* Test for someone scribbling on unused space in chunk */
41 234297 : if (!sentinel_ok(pointer, chunk->requested_size))
108 drowley 42 UNC 0 : elog(WARNING, "detected write past chunk end in %s %p",
43 : GetMemoryChunkContext(unaligned)->name, chunk);
44 : #endif
45 :
108 drowley 46 GNC 234297 : pfree(unaligned);
47 234297 : }
48 :
49 : /*
50 : * AlignedAllocRealloc
51 : * Change the allocated size of a chunk and return possibly a different
52 : * pointer to a memory address aligned to the same boundary as the
53 : * originally requested alignment. The contents of 'pointer' will be
54 : * copied into the returned pointer up until 'size'. Any additional
55 : * memory will be uninitialized.
56 : */
57 : void *
108 drowley 58 UNC 0 : AlignedAllocRealloc(void *pointer, Size size)
59 : {
60 0 : MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
61 0 : Size alignto = MemoryChunkGetValue(redirchunk);
62 0 : void *unaligned = MemoryChunkGetBlock(redirchunk);
63 : MemoryContext ctx;
64 : Size old_size;
65 : void *newptr;
66 :
67 : /* sanity check this is a power of 2 value */
68 0 : Assert((alignto & (alignto - 1)) == 0);
69 :
70 : /*
71 : * Determine the size of the original allocation. We can't determine this
72 : * exactly as GetMemoryChunkSpace() returns the total space used for the
73 : * allocation, which for contexts like aset includes rounding up to the
74 : * next power of 2. However, this value is just used to memcpy() the old
75 : * data into the new allocation, so we only need to concern ourselves with
76 : * not reading beyond the end of the original allocation's memory. The
77 : * drawback here is that we may copy more bytes than we need to, which
78 : * only amounts to wasted effort. We can safely subtract the extra bytes
79 : * that we requested to allow us to align the pointer. We must also
80 : * subtract the space for the unaligned pointer's MemoryChunk since
81 : * GetMemoryChunkSpace should have included that. This does assume that
82 : * all context types use MemoryChunk as a chunk header.
83 : */
84 0 : old_size = GetMemoryChunkSpace(unaligned) -
85 : PallocAlignedExtraBytes(alignto) - sizeof(MemoryChunk);
86 :
87 : #ifdef MEMORY_CONTEXT_CHECKING
88 : /* check that GetMemoryChunkSpace returned something realistic */
89 0 : Assert(old_size >= redirchunk->requested_size);
90 : #endif
91 :
92 0 : ctx = GetMemoryChunkContext(unaligned);
93 0 : newptr = MemoryContextAllocAligned(ctx, size, alignto, 0);
94 :
95 : /*
96 : * We may memcpy beyond the end of the original allocation request size,
97 : * so we must mark the entire allocation as defined.
98 : */
99 : VALGRIND_MAKE_MEM_DEFINED(pointer, old_size);
100 0 : memcpy(newptr, pointer, Min(size, old_size));
101 0 : pfree(unaligned);
102 :
103 0 : return newptr;
104 : }
105 :
106 : /*
107 : * AlignedAllocGetChunkContext
108 : * Return the MemoryContext that 'pointer' belongs to.
109 : */
110 : MemoryContext
111 0 : AlignedAllocGetChunkContext(void *pointer)
112 : {
113 0 : MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
114 :
115 0 : Assert(!MemoryChunkIsExternal(chunk));
116 :
117 0 : return GetMemoryChunkContext(MemoryChunkGetBlock(chunk));
118 : }
119 :
120 : /*
121 : * AlignedAllocGetChunkSpace
122 : * Given a currently-allocated chunk, determine the total space
123 : * it occupies (including all memory-allocation overhead).
124 : */
125 : Size
126 0 : AlignedAllocGetChunkSpace(void *pointer)
127 : {
128 0 : MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
129 0 : void *unaligned = MemoryChunkGetBlock(redirchunk);
130 :
131 0 : return GetMemoryChunkSpace(unaligned);
132 : }
|