24
24
#endif
25
25
26
26
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
+ */
27
36
#define FIFO
28
37
#ifdef LIFO
29
38
#define insert_free_block insert_free_block_lifo
55
64
#define DSIZE 8
56
65
#define ALIGNMENT 8
57
66
#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
+ */
58
74
#define MIN_FREE_BLOCK_SIZE (2*DSIZE)
59
75
#define MIN_BLOCK_SIZE (2*DSIZE)
60
- #define MAX_BLOCK_SIZE INT_MAX /* TODO: better definition? */
76
+ #define MAX_BLOCK_SIZE INT_MAX
61
77
62
78
/* rounds up to the nearest multiple of ALIGNMENT */
63
79
#define ALIGN (p ) (((size_t)(p) + (ALIGNMENT-1)) & ~0x7)
103
119
/* iterate through every block between epilogue and prologue block */
104
120
#define for_each_block (ptr ) \
105
121
for ((ptr) = BEGIN_BLOCK; !IS_EPILOGUE(ptr); (ptr)=NEXT_BLKP(ptr))
122
+ /* iterate through every free block in the free list */
106
123
#define for_each_free_block (class_ptr , ptr ) \
107
124
for ((ptr) = SUCC_BLKP(class_ptr); (ptr) != (class_ptr); (ptr) = SUCC_BLKP(ptr))
108
125
/* enumerate free list in range */
@@ -126,8 +143,9 @@ static void *split_block(void *bp, size_t pack_v1, size_t pack_v2);
126
143
#define FREE_LIST_LEN 10
127
144
/* sentinel size(PREV | SUCC) */
128
145
#define FREE_LIST_SENTINEL_SIZE DSIZE
129
- // get the ith free list
146
+ /* get the ith free list */
130
147
#define FREE_LIST_REF (k ) (free_listp + (k) * FREE_LIST_SENTINEL_SIZE)
148
+ /* return the index of the free list pointer */
131
149
#define FREE_LIST_IDX (p ) (((char*)p - free_listp) / FREE_LIST_SENTINEL_SIZE)
132
150
/* get free list class ptr
133
151
* size: size of the free block.
@@ -137,7 +155,7 @@ inline static void *get_class_ptr(size_t size)
137
155
{
138
156
/*
139
157
* 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
141
159
* {2}, {3-4}, ..., {257, 512}, {513, +inf}
142
160
* 2^1, 2^2, 2^3, ...., 2^9, ...
143
161
*/
@@ -253,30 +271,49 @@ inline static void remove_free_block(void *bp)
253
271
/*
254
272
* Initialize: return -1 on error, 0 on success.
255
273
*/
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 ]
260
280
*/
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 ) {
262
286
return -1 ;
263
287
}
264
288
265
- /*
266
- * odd + 3 is even
267
- */
289
+ /* prologue and epilogue */
268
290
if ((heap_listp = mem_sbrk (4 * WSIZE )) == (void * ) - 1 ) {
269
291
return -1 ;
270
292
}
271
293
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
+ */
273
307
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
+ */
274
311
PUT (PRED (FREE_LIST_REF (i )), i * FREE_LIST_SENTINEL_SIZE );
275
312
PUT (SUCC (FREE_LIST_REF (i )), i * FREE_LIST_SENTINEL_SIZE );
276
313
}
277
314
278
315
279
- // initialize prologue
316
+ // initialize prologue and epilogue
280
317
PUT (heap_listp , 0 );
281
318
PUT (heap_listp + (1 * WSIZE ), PACK (DSIZE , 1 ));
282
319
PUT (heap_listp + (2 * WSIZE ), PACK (DSIZE , 1 ));
@@ -290,6 +327,9 @@ int mm_init(void) {
290
327
return 0 ;
291
328
}
292
329
330
+ /*
331
+ * extend_heap - extend the heap size
332
+ */
293
333
static void * extend_heap (size_t words )
294
334
{
295
335
char * bp ;
@@ -307,18 +347,21 @@ static void *extend_heap(size_t words)
307
347
PUT (HDRP (NEXT_BLKP (bp )), PACK (0 , 1 ));
308
348
309
349
bp = coalesce (bp );
310
- // printf("extend heap, %u\n", GET_SIZE(HDRP(bp)));
311
350
return bp ;
312
351
}
313
352
314
353
315
354
/*
355
+ * coalesce: coalesce the free block.
356
+ *
316
357
* after coalesce, we append the new free block
317
358
*/
318
359
static void * coalesce (void * bp )
319
360
{
361
+ // previous block
320
362
void * prev_bp = PREV_BLKP (bp );
321
363
size_t prev_alloc = GET_ALLOC (FTRP (prev_bp ));
364
+ // next block
322
365
void * next_bp = NEXT_BLKP (bp );
323
366
size_t next_alloc = GET_ALLOC (HDRP (next_bp ));
324
367
size_t size = GET_SIZE (HDRP (bp ));
@@ -345,15 +388,20 @@ static void *coalesce(void *bp)
345
388
PUT (FTRP (NEXT_BLKP (bp )), PACK (size , 0 ));
346
389
bp = PREV_BLKP (bp );
347
390
}
391
+ // insert the new free block
348
392
insert_free_block (bp );
349
393
return bp ;
350
394
}
351
395
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
+ */
352
401
inline size_t get_real_malloc_size (size_t size )
353
402
{
354
403
size_t asize ;
355
404
if (size <= DSIZE ) {
356
- // asize = MIN_BLOCK_SIZE;
357
405
asize = 2 * DSIZE ;
358
406
} else {
359
407
asize = DSIZE * ((size + DSIZE + DSIZE - 1 ) / DSIZE );
@@ -366,7 +414,6 @@ inline size_t get_real_malloc_size(size_t size)
366
414
*/
367
415
void * malloc (size_t size )
368
416
{
369
- // printf("malloc: %zu\n",size);
370
417
size_t asize ;
371
418
char * bp ;
372
419
size_t extendsize ;
@@ -437,13 +484,15 @@ static void *split_block(
437
484
438
485
/*
439
486
* 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.
440
489
*/
441
490
static void * find_fit (size_t size )
442
491
{
443
- // first fit
444
492
void * begin_class_ptr = get_class_ptr (size );
445
493
void * class_ptr ;
446
494
void * bp ;
495
+ /* enumerate all free list with blocksize >= "size" */
447
496
for_range_free_list (begin_class_ptr , END_CLASS_PTR , class_ptr ) {
448
497
for_each_free_block (class_ptr , bp ) {
449
498
size_t alloc = GET_ALLOC (HDRP (bp ));
@@ -469,8 +518,10 @@ void free (void *ptr)
469
518
470
519
/*
471
520
* 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...
474
525
*/
475
526
void * realloc (void * oldptr , size_t size )
476
527
{
@@ -490,6 +541,7 @@ void *realloc(void *oldptr, size_t size)
490
541
}
491
542
492
543
oldsize = GET_SIZE (HDRP (oldptr ));
544
+ /* if the block next to oldptr is a free block, we merge it */
493
545
void * next_bp = NEXT_BLKP (oldptr );
494
546
if (IS_FREE (next_bp )) {
495
547
// append next free block to the old block
@@ -503,6 +555,9 @@ void *realloc(void *oldptr, size_t size)
503
555
asize = get_real_malloc_size (size );
504
556
505
557
if (oldsize >= asize ) {
558
+ /* since oldsize is large enough, we don't need to find a new block
559
+ * of memory
560
+ */
506
561
if (oldsize >= asize + MIN_FREE_BLOCK_SIZE ) {
507
562
void * free_bp = split_block (
508
563
oldptr ,
@@ -529,30 +584,6 @@ void *realloc(void *oldptr, size_t size)
529
584
return newptr ;
530
585
}
531
586
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
-
556
587
/*
557
588
* calloc - you may want to look at mm-naive.c
558
589
* This function is not tested by mdriver, but it is
@@ -618,6 +649,10 @@ static int aligned(const void *p) {
618
649
}
619
650
620
651
652
+ /*
653
+ * check_block_consistency - check header/footer size and content, check
654
+ * minimum block size
655
+ */
621
656
static void check_block_consistency (const char * bp , int lineno )
622
657
{
623
658
const char * header , * footer ;
@@ -632,6 +667,10 @@ static void check_block_consistency(const char *bp, int lineno)
632
667
}
633
668
}
634
669
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
+ */
635
674
static void check_coalescing (const char * bp , int lineno )
636
675
{
637
676
if (IS_FREE (bp )) {
@@ -659,28 +698,6 @@ static void get_class_size_range(void *class_ptr, size_t *pmin_size, size_t *pma
659
698
}
660
699
}
661
700
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
-
684
701
/*
685
702
* mm_checkheap
686
703
*/
0 commit comments