Block allocator
The block allocator, declared in threads/malloc.h
, can allocate blocks of any size. It is layered on top of the page allocator described in the previous section. Blocks returned by the block allocator are obtained from the kernel pool.
The block allocator uses two different strategies for allocating memory. The first strategy applies to blocks that are 1 KiB or smaller (one-fourth of the page size). These allocations are rounded up to the nearest power of 2, or 16 bytes, whichever is larger. Then they are grouped into a page used only for allocations of that size.
The second strategy applies to blocks larger than 1 KiB. These allocations (plus a small amount of overhead) are rounded up to the nearest page in size, and then the block allocator requests that number of contiguous pages from the page allocator.
In either case, the difference between the allocation requested size and the actual block size is wasted. A real operating system would carefully tune its allocator to minimize this waste, but this is unimportant in an instructional system like Pintos.
As long as a page can be obtained from the page allocator, small allocations always succeed. Most small allocations do not require a new page from the page allocator at all, because they are satisfied using part of a page already allocated. However, large allocations always require calling into the page allocator, and any allocation that needs more than one contiguous page can fail due to fragmentation, as already discussed in the previous section. Thus, you should minimize the number of large allocations in your code, especially those over approximately 4 KiB each.
When a block is freed, all of its bytes are cleared to 0xcc
, as a debugging aid.
The block allocator may not be called from interrupt context.
The block allocator functions are described below. Their interfaces are the same as the standard C library functions of the same names.
void * malloc (size_t size)
Obtains and returns a new block, from the kernel pool, at least
size
bytes long. Returns a null pointer ifsize
is zero or if memory is not available.
void * calloc (size_t a, size_t b)
Obtains a returns a new block, from the kernel pool, at least
a * b
bytes long. The block’s contents will be cleared to zeros. Returns a null pointer ifa
orb
is zero or if insufficient memory is available.
void * realloc (void *block, size_t new_size)
Attempts to resize
block
tonew_size
bytes, possibly moving it in the process. If successful, returns the new block, in which case the old block must no longer be accessed. On failure, returns a null pointer, and the old block remains valid.
A call with
block
null is equivalent tomalloc
. A call withnew_size
zero is equivalent tofree
.
void free (void *block)
Frees
block
, which must have been previously returned bymalloc
,calloc
, orrealloc
(and not yet freed).