211
In most implementations, the number of additional bytes allocated is
equal to the alignment. For example, if the request is for a 16-byte aligned
memory block, we would allocate 16 additional bytes. This allows for the
worst-case address adjustment of 15 bytes, plus one extra byte so that we can
use the same calculations even if the original block is already aligned. This
simplifi es and speeds up the code at the expense of one wasted byte per al-
location. It’s also important because, as we’ll see below, we’ll need those extra
bytes to store some additional information that will be used when the block
is freed.
We determine the amount by which the block’s address must be adjusted
by masking off the least-signifi cant bits of the original block’s memory ad-
dress, subtracting this from the desired alignment, and using the result as
the adjustment off set. The alignment should always be a power of two (four-
byte and 16-byte alignments are typical), so to generate the mask we simply
subtract one from the alignment. For example, if the request is for a 16-byte
aligned block, then the mask would be (16 – 1) = 15 = 0x0000000F. Taking
the bitwise AND of this mask and any misaligned address will yield the
amount by which the address is misaligned. For example, if the originally-
allocated block’s address is 0x50341233, ANDing this address with the mask
0x0000000F yields 0x00000003, so the address is misaligned by three bytes.
To align the address, we add (alignment – misalignment) = (16 – 3) = 13 =
0xD bytes to it. The fi nal aligned address is therefore 0x50341233 + 0xD =
0x50341240.
Here’s one possible implementation of an aligned memory allocator:
// Aligned allocation function. IMPORTANT: 'alignment'
// must be a power of 2 (typically 4 or 16).
void*allocateAligned(U32 size_bytes, U32 alignment)
{
// Determine total amount of memory to allocate.
U32 expandedSize_bytes = size_bytes + alignment;
// Allocate an unaligned block & convert address to a
// U32.
U32 rawAddress
= (U32)allocateUnaligned(expandedSize_bytes);
// Calculate the adjustment by masking off the lower
// bits of the address, to determine how "misaligned"
// it is.
U32 mask = (alignment – 1);
U32 misalignment = (rawAddress & mask);
U32 adjustment = alignment – misalignment;
5.2. Memory Management