420 26.AHighlyOptimizedPortableMemoryManager
Instead, we could store a value in an array at the end of the page, similar to how
the free block bit mask is stored, although that is quite expensive as well. Con-
sidering most of the allocations are larger than one block, many of the entries in
this array would be unused at any given time. Even if we stored the length per
block in one byte, it would be far too wasteful!
The solution: store a single bit in a bit mask that identifies whether a block is
at the end of an allocation. The pointer passed in to the
Free() function identi-
fies the start of the block already. Using these two pieces of information, we can
extrapolate the length of an allocation simply by scanning the bit mask forward
looking for a set bit. As a matter of standards, in the code provided, unallocated
blocks have their end-of-allocation bit set to zero, but it won’t ever be checked so
it shouldn’t matter. See Figure 26.3 for a more visual explanation.
HowAlloc()Works
Once a page is found, the MBA simply looks up the large block index in the
Tail structure, marks the range of bits as allocated in the free block bit mask,
and clears all the bits except the last one in the end-of-allocation bit mask. This is
enough information to allow the
Free() function to determine the length of the
original allocation given only the pointer address.
Now that the big block in the page has been at least partially allocated, we
have to find the new big block in the page. This entails scanning the free block
bit mask and finding the longest run of set bits, remembering the index and size
of the longest one. Once this is done, it is stored in the
Tail structure in the page
for future use.
The pointer to the allocation is returned to the memory manager. The
memory manager then must grab the big block size from the page and rearrange
that page to a different list based on the size of its big block, so future allocations
do not need to skip over insufficient memory pages.
HowFree()Works
Once the page manager has identified the page, the MBA begins by scanning the
end-of-allocation bit mask at the end of the page and counting 0 bits until a 1 bit
is found. This marks the end of the allocation and implicitly defines the length of
the allocation. We set the free block bit mask to one for all the blocks between
the start and end of the allocation, and clear the end-of-allocation bit to zero
(though this is not strictly necessary).
Since the memory region that was just released plus any adjacent free blocks
might sum to a larger big block, we update the big block size, just as was done in