Skip to content

Commit a1032ef

Browse files
committed
add some comments
1 parent 137c463 commit a1032ef

File tree

1 file changed

+82
-65
lines changed
  • malloclab-handout

1 file changed

+82
-65
lines changed

malloclab-handout/mm.c

Lines changed: 82 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@
2424
#endif
2525

2626

27+
/* The order of free block list.
28+
*
29+
* FIFO: first in first out.
30+
* LIFO: last in first out.
31+
* ADDRESS_ORDER: free block list in address order. Smaller address first.
32+
* SIZE_ORDER: free block list in size order. Smaller size first.
33+
*
34+
* According to the test, FIFO performs the best.
35+
*/
2736
#define FIFO
2837
#ifdef LIFO
2938
#define insert_free_block insert_free_block_lifo
@@ -55,9 +64,16 @@
5564
#define DSIZE 8
5665
#define ALIGNMENT 8
5766
#define CHUNKSIZE (1<<9)
67+
/*
68+
* The minimum free block size.
69+
* For each free block, we need to have a header and a footer, a successor and
70+
* a predecessor.
71+
* We store the successor as the offset from the beginning of the whole heap*
72+
* As the heap's max size is 2^31, we can store it in WSIZE bytes.
73+
*/
5874
#define MIN_FREE_BLOCK_SIZE (2*DSIZE)
5975
#define MIN_BLOCK_SIZE (2*DSIZE)
60-
#define MAX_BLOCK_SIZE INT_MAX /* TODO: better definition? */
76+
#define MAX_BLOCK_SIZE INT_MAX
6177

6278
/* rounds up to the nearest multiple of ALIGNMENT */
6379
#define ALIGN(p) (((size_t)(p) + (ALIGNMENT-1)) & ~0x7)
@@ -103,6 +119,7 @@
103119
/* iterate through every block between epilogue and prologue block */
104120
#define for_each_block(ptr) \
105121
for ((ptr) = BEGIN_BLOCK; !IS_EPILOGUE(ptr); (ptr)=NEXT_BLKP(ptr))
122+
/* iterate through every free block in the free list */
106123
#define for_each_free_block(class_ptr, ptr) \
107124
for ((ptr) = SUCC_BLKP(class_ptr); (ptr) != (class_ptr); (ptr) = SUCC_BLKP(ptr))
108125
/* enumerate free list in range */
@@ -126,8 +143,9 @@ static void *split_block(void *bp, size_t pack_v1, size_t pack_v2);
126143
#define FREE_LIST_LEN 10
127144
/* sentinel size(PREV | SUCC) */
128145
#define FREE_LIST_SENTINEL_SIZE DSIZE
129-
// get the ith free list
146+
/* get the ith free list */
130147
#define FREE_LIST_REF(k) (free_listp + (k) * FREE_LIST_SENTINEL_SIZE)
148+
/* return the index of the free list pointer */
131149
#define FREE_LIST_IDX(p) (((char*)p - free_listp) / FREE_LIST_SENTINEL_SIZE)
132150
/* get free list class ptr
133151
* size: size of the free block.
@@ -137,7 +155,7 @@ inline static void *get_class_ptr(size_t size)
137155
{
138156
/*
139157
* size is a multiple of 8. size = k * 8.
140-
* We have k >= 2.
158+
* We have k >= 2 since MIN_FREE_BLOCK_SIZE is 2*DSIZE
141159
* {2}, {3-4}, ..., {257, 512}, {513, +inf}
142160
* 2^1, 2^2, 2^3, ...., 2^9, ...
143161
*/
@@ -253,30 +271,49 @@ inline static void remove_free_block(void *bp)
253271
/*
254272
* Initialize: return -1 on error, 0 on success.
255273
*/
256-
int mm_init(void) {
257-
int i;
258-
/* This part is tricky.
259-
* FREE_LIST_LEN is odd number.
274+
int mm_init(void)
275+
{
276+
/*
277+
* Generally structure of the heap is:
278+
*
279+
* [ FREE LIST POINTERS | PRELOGUE BLOCK | HEAP MEMORY | EPILOGUE BLOCK ]
260280
*/
261-
if ((free_listp = mem_sbrk(FREE_LIST_LEN*FREE_LIST_SENTINEL_SIZE)) == (void*)-1) {
281+
int i;
282+
283+
/* allocate memory for free block pointers */
284+
if ((free_listp = mem_sbrk(
285+
FREE_LIST_LEN*FREE_LIST_SENTINEL_SIZE)) == (void*)-1) {
262286
return -1;
263287
}
264288

265-
/*
266-
* odd + 3 is even
267-
*/
289+
/* prologue and epilogue */
268290
if ((heap_listp = mem_sbrk(4*WSIZE)) == (void*) - 1) {
269291
return -1;
270292
}
271293

272-
// initialize free list
294+
/* initialize free list pointers
295+
*
296+
* Each free list pointer has DSIZE bytes consisting of predecessor and
297+
* successor.
298+
*
299+
* [PRED | SUCC].
300+
*
301+
* The PRED points to the last free block while SUCC points to the
302+
* first free block.
303+
* Generally, the free list pointer works as the sentinel for the free list.
304+
* Use both PRED and SUCC makes the code easier to maintain and less
305+
* if/else conditional judgements.
306+
*/
273307
for (i = 0; i < FREE_LIST_LEN; i++) {
308+
/* initially, as each free list is empty, the free list pointer
309+
* just points to the sentinel
310+
*/
274311
PUT(PRED(FREE_LIST_REF(i)), i * FREE_LIST_SENTINEL_SIZE);
275312
PUT(SUCC(FREE_LIST_REF(i)), i * FREE_LIST_SENTINEL_SIZE);
276313
}
277314

278315

279-
// initialize prologue
316+
// initialize prologue and epilogue
280317
PUT(heap_listp, 0);
281318
PUT(heap_listp + (1*WSIZE), PACK(DSIZE, 1));
282319
PUT(heap_listp + (2*WSIZE), PACK(DSIZE, 1));
@@ -290,6 +327,9 @@ int mm_init(void) {
290327
return 0;
291328
}
292329

330+
/*
331+
* extend_heap - extend the heap size
332+
*/
293333
static void *extend_heap(size_t words)
294334
{
295335
char *bp;
@@ -307,18 +347,21 @@ static void *extend_heap(size_t words)
307347
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
308348

309349
bp = coalesce(bp);
310-
// printf("extend heap, %u\n", GET_SIZE(HDRP(bp)));
311350
return bp;
312351
}
313352

314353

315354
/*
355+
* coalesce: coalesce the free block.
356+
*
316357
* after coalesce, we append the new free block
317358
*/
318359
static void *coalesce(void *bp)
319360
{
361+
// previous block
320362
void *prev_bp = PREV_BLKP(bp);
321363
size_t prev_alloc = GET_ALLOC(FTRP(prev_bp));
364+
// next block
322365
void *next_bp = NEXT_BLKP(bp);
323366
size_t next_alloc = GET_ALLOC(HDRP(next_bp));
324367
size_t size = GET_SIZE(HDRP(bp));
@@ -345,15 +388,20 @@ static void *coalesce(void *bp)
345388
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
346389
bp = PREV_BLKP(bp);
347390
}
391+
// insert the new free block
348392
insert_free_block(bp);
349393
return bp;
350394
}
351395

396+
/*
397+
* Generally, the allocated size is larger than the size we want since
398+
* we need to store the header and footer. This function return
399+
* the real size we need to allocate.
400+
*/
352401
inline size_t get_real_malloc_size(size_t size)
353402
{
354403
size_t asize;
355404
if (size <= DSIZE) {
356-
// asize = MIN_BLOCK_SIZE;
357405
asize = 2*DSIZE;
358406
} else {
359407
asize = DSIZE * ((size + DSIZE + DSIZE - 1) / DSIZE);
@@ -366,7 +414,6 @@ inline size_t get_real_malloc_size(size_t size)
366414
*/
367415
void *malloc (size_t size)
368416
{
369-
// printf("malloc: %zu\n",size);
370417
size_t asize;
371418
char *bp;
372419
size_t extendsize;
@@ -437,13 +484,15 @@ static void *split_block(
437484

438485
/*
439486
* find a block of memory with size >= "size"
487+
* We use first fit stratergy. I have tried other strategies,
488+
* but first fit works very well.
440489
*/
441490
static void *find_fit(size_t size)
442491
{
443-
// first fit
444492
void *begin_class_ptr = get_class_ptr(size);
445493
void *class_ptr;
446494
void *bp;
495+
/* enumerate all free list with blocksize >= "size" */
447496
for_range_free_list(begin_class_ptr, END_CLASS_PTR, class_ptr) {
448497
for_each_free_block(class_ptr, bp) {
449498
size_t alloc = GET_ALLOC(HDRP(bp));
@@ -469,8 +518,10 @@ void free (void *ptr)
469518

470519
/*
471520
* realloc - Change the size of the block by mallocing a new block,
472-
* copying its data, and freeing the old block. I'm too lazy
473-
* to do better.
521+
* copying its data, and freeing the old block.
522+
*
523+
* This is an optimized realloc implementation, but it performs the same
524+
* as the unoptimized version...
474525
*/
475526
void *realloc(void *oldptr, size_t size)
476527
{
@@ -490,6 +541,7 @@ void *realloc(void *oldptr, size_t size)
490541
}
491542

492543
oldsize = GET_SIZE(HDRP(oldptr));
544+
/* if the block next to oldptr is a free block, we merge it */
493545
void *next_bp = NEXT_BLKP(oldptr);
494546
if (IS_FREE(next_bp)) {
495547
// append next free block to the old block
@@ -503,6 +555,9 @@ void *realloc(void *oldptr, size_t size)
503555
asize = get_real_malloc_size(size);
504556

505557
if (oldsize >= asize) {
558+
/* since oldsize is large enough, we don't need to find a new block
559+
* of memory
560+
*/
506561
if (oldsize >= asize + MIN_FREE_BLOCK_SIZE) {
507562
void *free_bp = split_block(
508563
oldptr,
@@ -529,30 +584,6 @@ void *realloc(void *oldptr, size_t size)
529584
return newptr;
530585
}
531586

532-
#if 0
533-
void *realloc1(void *oldptr, size_t size)
534-
{
535-
size_t oldsize;
536-
void *newptr;
537-
538-
/* If size == 0 then this is just free, and we return NULL. */
539-
if(size == 0) {
540-
free(oldptr);
541-
return 0;
542-
}
543-
544-
/* If oldptr is NULL, then this is just malloc. */
545-
if(oldptr == NULL) {
546-
return malloc(size);
547-
}
548-
549-
550-
oldsize = GET_SIZE(HDRP(oldptr));
551-
552-
return 0;
553-
}
554-
#endif
555-
556587
/*
557588
* calloc - you may want to look at mm-naive.c
558589
* This function is not tested by mdriver, but it is
@@ -618,6 +649,10 @@ static int aligned(const void *p) {
618649
}
619650

620651

652+
/*
653+
* check_block_consistency - check header/footer size and content, check
654+
* minimum block size
655+
*/
621656
static void check_block_consistency(const char *bp, int lineno)
622657
{
623658
const char *header, *footer;
@@ -632,6 +667,10 @@ static void check_block_consistency(const char *bp, int lineno)
632667
}
633668
}
634669

670+
/*
671+
* check_coalescing - check whether every free block is coalesced, i.e.,
672+
* there should be no free blocks next to every free block
673+
*/
635674
static void check_coalescing(const char *bp, int lineno)
636675
{
637676
if (IS_FREE(bp)) {
@@ -659,28 +698,6 @@ static void get_class_size_range(void *class_ptr, size_t *pmin_size, size_t *pma
659698
}
660699
}
661700

662-
/* test code */
663-
#if 0
664-
static void test_class_ptr()
665-
{
666-
for (int i = 0; i < FREE_LIST_LEN; i++) {
667-
void *class_ptr = FREE_LIST_REF(i);
668-
size_t min_size, max_size;
669-
get_class_size_range(class_ptr, &min_size, &max_size);
670-
printf("%zu %zu\n", min_size, max_size);
671-
}
672-
673-
for (size_t i = MIN_BLOCK_SIZE; i <= 4096 + DSIZE; i+=DSIZE) {
674-
void *class_ptr = get_class_ptr(i);
675-
int offset = ((char *)class_ptr - free_listp) / FREE_LIST_SENTINEL_SIZE;
676-
size_t min_size, max_size;
677-
get_class_size_range(FREE_LIST_REF(offset), &min_size, &max_size);
678-
CHECK_LESS_EQUAL(i, max_size, __LINE__, "max size");
679-
CHECK_GREATER_EQUAL(i, min_size, __LINE__, "min_size");
680-
}
681-
}
682-
#endif
683-
684701
/*
685702
* mm_checkheap
686703
*/

0 commit comments

Comments
 (0)