The minimum block size is 16 bytes. The free list is organized as
an implicit free list, with the invariant form shown as below:
The first word is an unused padding word aligned to a double-word
boundary.
The padding is followed by a special prologue block, which is an
8-byte allocated block consisting of only a header and a
footer. The prologue block is created during
initialization and is never freed.
The heap always ends with a special epilogue block, which is a
zero-size allocated block that consists of only a
header.
The allocator uses a single private(static) global
variable(heap_listp) that always points to the
prologue block.
2.Basic
Constants and Macros for Manipulating the Free List
#define WSIZE 4 /* Word and header/footer size (bytes) */ #define DSIZE 8 /* Double word size (bytes) */ #define CHUNKSIZE (1<<12) /* Extend heap by this amount (bytes) */
#define MAX(x, y) ((x) > (y)? (x) : (y))
/* Pack a size and allocated bit into a word */ #define PACK(size, alloc) ((size) | (alloc))
/* Read and write a word at address p */ #define GET(p) (*(unsigned int *)(p)) // The pointer points to p is dereferenced #define PUT(p, val) (*(unsigned int *)(p) = (val))
/* Read the size and allocated fields from address p */ #define GET_SIZE(p) (GET(p) & ~0x7) #define GET_ALLOC(p) (GET(p) & 0x1)
/* Given block ptr bp, compute address of its header and footer */ #define HDRP(bp) ((char *)(bp) - WSIZE) #define FTRP(bp) ((char *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) // Why DSIZE? Because both header and footer need to decline WSIZE, and 2*WSIZE=DSIZE
/* Given block ptr bp, compute address of next and previous blocks */ #define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char *)(bp) - WSIZE))) #define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char *)(bp) - DSIZE)))
/* Allocate an even number of words to maintain alignment */ size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE; if ((long)(bp = mem_sbrk(size)) == -1) returnNULL;
/* Coalesce if the previous block was free */ return coalesce(bp); }
Place enough space by invoking mem_sbrk.
Set the new space free by setting the allocate bit
0.
Set the block next to bp as the new epilogue
header.
Finally, in the likely case that the previous heap was
terminated by a free block, we call the coalesce
function to merge the two free blocks and return the block
pointer of the merged blocks.
To maintain alignment, extend_heap rounds up the requested
size to the nearest multiple of 2 words(8 bytes).
void *mm_malloc(size_t size) { size_t asize; /* Adjusted block size */ size_t extendsize; /* Amount to extend heap if no fit */ char *bp;
/* Ignore spurious requests */ if (size == 0) returnNULL;
/* Adjust block size to include overhead and alignment reqs. */ if (size <= DSIZE) asize = 2*DSIZE; else asize = DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
/* Search the free list for a fit */ if ((bp = find_fit(asize)) != NULL) { place(bp, asize); return bp; }
/* No fit found. Get more memory and place the block */ extendsize = MAX(asize, CHUNKSIZE); if ((bp = extend_heap(extendsize/WSIZE)) == NULL) returnNULL; place(bp, asize); return bp; }
The DSIZE * ((size + (DSIZE) + (DSIZE-1)) / DSIZE);
assures that the result is rounded up to the nearest multiple of
DSIZE.