71{
74 void *unaligned;
77 void *newptr;
78
80
83
84 /* sanity check this is a power of 2 value */
85 Assert((alignto & (alignto - 1)) == 0);
86
87 /*
88 * Determine the size of the original allocation. We can't determine this
89 * exactly as GetMemoryChunkSpace() returns the total space used for the
90 * allocation, which for contexts like aset includes rounding up to the
91 * next power of 2. However, this value is just used to memcpy() the old
92 * data into the new allocation, so we only need to concern ourselves with
93 * not reading beyond the end of the original allocation's memory. The
94 * drawback here is that we may copy more bytes than we need to, which
95 * only amounts to wasted effort. We can safely subtract the extra bytes
96 * that we requested to allow us to align the pointer. We must also
97 * subtract the space for the unaligned pointer's MemoryChunk since
98 * GetMemoryChunkSpace should have included that. This does assume that
99 * all context types use MemoryChunk as a chunk header.
100 */
103
104#ifdef MEMORY_CONTEXT_CHECKING
105 /* check that GetMemoryChunkSpace returned something realistic */
106 Assert(old_size >= redirchunk->requested_size);
107#endif
108
109 /*
110 * To keep things simple, we always allocate a new aligned chunk and copy
111 * data into it. Because of the above inaccuracy, this may end in copying
112 * more data than was in the original allocation request size, but that
113 * should be OK.
114 */
117
118 /* Cope cleanly with OOM */
120 {
123 }
124
125 /*
126 * We may memcpy more than the original allocation request size, which
127 * would result in trying to copy trailing bytes that the original
128 * MemoryContextAllocAligned call marked NOACCESS. So we must mark the
129 * entire old_size as defined. That's slightly annoying, but probably not
130 * worth improving.
131 */
133 memcpy(newptr, pointer,
Min(size, old_size));
134
135 /*
136 * Create a dummy vchunk covering the start of the old unaligned chunk,
137 * but not overlapping the aligned chunk. This will be freed while
138 * pfree'ing the old unaligned chunk, keeping Valgrind happy. Then when
139 * we return to repalloc, it will move the vchunk for the aligned chunk.
140 */
142 (char *) pointer - (char *) unaligned);
143
145
146 return newptr;
147}
void * MemoryContextAllocAligned(MemoryContext context, Size size, Size alignto, int flags)
void * MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
#define PallocAlignedExtraBytes(alignto)
static Size MemoryChunkGetValue(MemoryChunk *chunk)
struct MemoryChunk MemoryChunk