diff --git a/hw3/src/main.c b/hw3/src/main.c index 142a2c2..a1817ee 100644 --- a/hw3/src/main.c +++ b/hw3/src/main.c @@ -3,26 +3,7 @@ int main(int argc, char const *argv[]) { - size_t sz_x = sizeof(int); - void *x1 = sf_malloc(sz_x); - void *x2 = sf_malloc(sz_x); - void *x3 = sf_malloc(sz_x); - void *x4 = sf_malloc(sz_x); - void *x5 = sf_malloc(sz_x); - - sf_show_heap(); - - sf_free(x1); - sf_free(x2); - sf_free(x3); - sf_free(x4); - sf_free(x5); - - - void *x6 = sf_malloc(sz_x); - sf_show_heap(); - sf_free(x6); - - sf_show_heap(); + sf_malloc(sizeof(int)); + sf_free(((void *)(intptr_t)sf_mem_end()) - 2 * sizeof(sf_header)); return EXIT_SUCCESS; } diff --git a/hw3/src/sfmm.c b/hw3/src/sfmm.c index 50a70d5..df525a2 100644 --- a/hw3/src/sfmm.c +++ b/hw3/src/sfmm.c @@ -15,6 +15,10 @@ static sf_block *epi; static sf_size_t in_qklst = 0x00000001; static sf_size_t prv_alloc = 0x00000002; static sf_size_t alloc = 0x00000004; +// static sf_size_t total_payload = 0; +// static sf_size_t max_payload = 0; +// static sf_size_t total_block_size = 0; +static sf_size_t total_pages = 0; int sf_initialize(); void set_header(sf_block *block, sf_header value); @@ -52,7 +56,6 @@ void *sf_malloc(sf_size_t size) if (sf_mem_start() == sf_mem_end()) if (sf_initialize()) return NULL; - // sf_show_heap(); sf_size_t min_size = get_min_size(size); sf_size_t index = (min_size - 32) / 16; @@ -81,6 +84,7 @@ void *sf_malloc(sf_size_t size) set_entire_header(ptr, size, get_block_size(ptr->header), 1, get_prv_alloc(ptr->header), 0, 0); return ptr->body.payload; } + ptr = ptr->body.links.next; } } else @@ -95,7 +99,6 @@ void *sf_malloc(sf_size_t size) set_entire_header(ptr, size, min_size, 1, get_prv_alloc(ptr->header), 0, 0); set_entire_header(block, 0, block_size, 0, get_prv_alloc(block->header), 0, 0); put_block(block); - // sf_show_block(block); return ptr->body.payload; } ptr = ptr->body.links.next; @@ -113,6 +116,7 @@ void *sf_malloc(sf_size_t size) sf_errno = ENOMEM; return NULL; } + total_pages += 1024; if (last->body.links.next != NULL) remove_list(last); set_entire_header(last, 0, (get_block_size(last->header) + PAGE_SZ), 0, get_prv_alloc(last->header), 0, 0); @@ -130,8 +134,6 @@ void *sf_malloc(sf_size_t size) epi = (sf_block *)(((intptr_t)sf_mem_end()) - 2 * sizeof(sf_header)); set_entire_header(epi, 0, 0, 1, get_alloc(epi->prev_footer), 0, 1); - // sf_show_block(ptr); - // sf_show_block(epi); return last->body.payload; } @@ -170,11 +172,12 @@ void *sf_realloc(void *pp, sf_size_t rsize) valid_pointer(block); sf_size_t size = get_block_size(block->header); sf_size_t new_size = get_min_size(rsize); - if (new_size >= size) + if (new_size > size) { - sf_block *new = (sf_block *)(((intptr_t)sf_malloc(rsize)) - 2 * sizeof(sf_header)); - if (new == NULL) + sf_block *new; + if ((new = sf_malloc(rsize)) == NULL) return NULL; + new = (sf_block *)(((intptr_t)new) - 2 * sizeof(sf_header)); memcpy(new->body.payload, block->body.payload, size); sf_free(pp); return new->body.payload; @@ -216,13 +219,12 @@ int sf_initialize() sf_errno = ENOMEM; return 1; } + total_pages += 1024; pro = (sf_block *)sf_mem_start(); - // sf_show_block(pro); set_entire_header(pro, 0, 32, 1, 1, 0, 1); epi = (sf_block *)(((intptr_t)sf_mem_end()) - 2 * sizeof(sf_header)); set_entire_header(epi, 0, 0, 1, 1, 0, 1); - // sf_show_block(epi); for (size_t i = 0; i < NUM_FREE_LISTS; i++) { sf_free_list_heads[i].body.links.prev = &sf_free_list_heads[i]; @@ -412,7 +414,7 @@ void valid_pointer(sf_block *pp) abort(); if (get_block_size(pp->header) < 32 || get_block_size(pp->header) % 16 != 0) abort(); - if (((intptr_t)&pp->header) < (((intptr_t)&pro->header) + 32) || ((intptr_t)&pp->header) > (((intptr_t)&epi->header) - 8)) + if (((intptr_t)&pp->header) < (((intptr_t)&pro->header) + 32) || ((intptr_t)&pp->header) >= (((intptr_t)&epi->header) - 16)) abort(); if (get_alloc(pp->header) == 0 || (get_prv_alloc(pp->header) == 0 && get_alloc(pp->prev_footer) != 0)) abort(); diff --git a/hw3/tests/sfmm_tests.c b/hw3/tests/sfmm_tests.c index 2cec983..e680a71 100644 --- a/hw3/tests/sfmm_tests.c +++ b/hw3/tests/sfmm_tests.c @@ -9,57 +9,72 @@ * Assert the total number of free blocks of a specified size. * If size == 0, then assert the total number of all free blocks. */ -void assert_free_block_count(size_t size, int count) { - int cnt = 0; - for(int i = 0; i < NUM_FREE_LISTS; i++) { - sf_block *bp = sf_free_list_heads[i].body.links.next; - while(bp != &sf_free_list_heads[i]) { - if(size == 0 || size == ((bp->header ^ MAGIC) & 0xfffffff0)) - cnt++; - bp = bp->body.links.next; +void assert_free_block_count(size_t size, int count) +{ + int cnt = 0; + for (int i = 0; i < NUM_FREE_LISTS; i++) + { + sf_block *bp = sf_free_list_heads[i].body.links.next; + while (bp != &sf_free_list_heads[i]) + { + if (size == 0 || size == ((bp->header ^ MAGIC) & 0xfffffff0)) + cnt++; + bp = bp->body.links.next; + } + } + if (size == 0) + { + cr_assert_eq(cnt, count, "Wrong number of free blocks (exp=%d, found=%d)", + count, cnt); + } + else + { + cr_assert_eq(cnt, count, "Wrong number of free blocks of size %ld (exp=%d, found=%d)", + size, count, cnt); } - } - if(size == 0) { - cr_assert_eq(cnt, count, "Wrong number of free blocks (exp=%d, found=%d)", - count, cnt); - } else { - cr_assert_eq(cnt, count, "Wrong number of free blocks of size %ld (exp=%d, found=%d)", - size, count, cnt); - } } /* * Assert the total number of quick list blocks of a specified size. * If size == 0, then assert the total number of all quick list blocks. */ -void assert_quick_list_block_count(size_t size, int count) { - int cnt = 0; - for(int i = 0; i < NUM_QUICK_LISTS; i++) { - sf_block *bp = sf_quick_lists[i].first; - while(bp != NULL) { - if(size == 0 || size == ((bp->header ^ MAGIC) & 0xfffffff0)) { - cnt++; - if(size != 0) { - // Check that the block is in the correct list for its size. - int index = (size - 32) >> 4; - cr_assert_eq(index, i, "Block %p (size %ld) is in wrong quick list for its size " - "(expected %d, was %d)", - &bp->header, (bp->header ^ MAGIC) & 0xfffffff0, index, i); +void assert_quick_list_block_count(size_t size, int count) +{ + int cnt = 0; + for (int i = 0; i < NUM_QUICK_LISTS; i++) + { + sf_block *bp = sf_quick_lists[i].first; + while (bp != NULL) + { + if (size == 0 || size == ((bp->header ^ MAGIC) & 0xfffffff0)) + { + cnt++; + if (size != 0) + { + // Check that the block is in the correct list for its size. + int index = (size - 32) >> 4; + cr_assert_eq(index, i, "Block %p (size %ld) is in wrong quick list for its size " + "(expected %d, was %d)", + &bp->header, (bp->header ^ MAGIC) & 0xfffffff0, index, i); + } + } + bp = bp->body.links.next; } - } - bp = bp->body.links.next; } - } - if(size == 0) { - cr_assert_eq(cnt, count, "Wrong number of quick list blocks (exp=%d, found=%d)", - count, cnt); - } else { - cr_assert_eq(cnt, count, "Wrong number of quick list blocks of size %ld (exp=%d, found=%d)", - size, count, cnt); - } + if (size == 0) + { + cr_assert_eq(cnt, count, "Wrong number of quick list blocks (exp=%d, found=%d)", + count, cnt); + } + else + { + cr_assert_eq(cnt, count, "Wrong number of quick list blocks of size %ld (exp=%d, found=%d)", + size, count, cnt); + } } -Test(sfmm_basecode_suite, malloc_an_int, .timeout = TEST_TIMEOUT) { +Test(sfmm_basecode_suite, malloc_an_int, .timeout = TEST_TIMEOUT) +{ sf_errno = 0; size_t sz = sizeof(int); int *x = sf_malloc(sz); @@ -71,8 +86,8 @@ Test(sfmm_basecode_suite, malloc_an_int, .timeout = TEST_TIMEOUT) { cr_assert(*x == 4, "sf_malloc failed to give proper space for an int!"); sf_block *bp = (sf_block *)((char *)x - 16); cr_assert((((bp->header ^ MAGIC) >> 32) & 0xffffffff) == sz, - "Malloc'ed block payload size (%ld) not what was expected (%ld)!", - (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz); + "Malloc'ed block payload size (%ld) not what was expected (%ld)!", + (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz); assert_quick_list_block_count(0, 0); assert_free_block_count(0, 1); @@ -82,7 +97,8 @@ Test(sfmm_basecode_suite, malloc_an_int, .timeout = TEST_TIMEOUT) { cr_assert(sf_mem_start() + PAGE_SZ == sf_mem_end(), "Allocated more than necessary!"); } -Test(sfmm_basecode_suite, malloc_four_pages, .timeout = TEST_TIMEOUT) { +Test(sfmm_basecode_suite, malloc_four_pages, .timeout = TEST_TIMEOUT) +{ sf_errno = 0; void *x = sf_malloc(4032); @@ -92,7 +108,8 @@ Test(sfmm_basecode_suite, malloc_four_pages, .timeout = TEST_TIMEOUT) { cr_assert(sf_errno == 0, "sf_errno is not 0!"); } -Test(sfmm_basecode_suite, malloc_too_large, .timeout = TEST_TIMEOUT) { +Test(sfmm_basecode_suite, malloc_too_large, .timeout = TEST_TIMEOUT) +{ sf_errno = 0; void *x = sf_malloc(98304); @@ -103,7 +120,8 @@ Test(sfmm_basecode_suite, malloc_too_large, .timeout = TEST_TIMEOUT) { cr_assert(sf_errno == ENOMEM, "sf_errno is not ENOMEM!"); } -Test(sfmm_basecode_suite, free_quick, .timeout = TEST_TIMEOUT) { +Test(sfmm_basecode_suite, free_quick, .timeout = TEST_TIMEOUT) +{ sf_errno = 0; size_t sz_x = 8, sz_y = 32, sz_z = 1; /* void *x = */ sf_malloc(sz_x); @@ -119,7 +137,8 @@ Test(sfmm_basecode_suite, free_quick, .timeout = TEST_TIMEOUT) { cr_assert(sf_errno == 0, "sf_errno is not zero!"); } -Test(sfmm_basecode_suite, free_no_coalesce, .timeout = TEST_TIMEOUT) { +Test(sfmm_basecode_suite, free_no_coalesce, .timeout = TEST_TIMEOUT) +{ sf_errno = 0; size_t sz_x = 8, sz_y = 200, sz_z = 1; /* void *x = */ sf_malloc(sz_x); @@ -136,7 +155,8 @@ Test(sfmm_basecode_suite, free_no_coalesce, .timeout = TEST_TIMEOUT) { cr_assert(sf_errno == 0, "sf_errno is not zero!"); } -Test(sfmm_basecode_suite, free_coalesce, .timeout = TEST_TIMEOUT) { +Test(sfmm_basecode_suite, free_coalesce, .timeout = TEST_TIMEOUT) +{ sf_errno = 0; size_t sz_w = 8, sz_x = 200, sz_y = 300, sz_z = 4; /* void *w = */ sf_malloc(sz_w); @@ -155,8 +175,9 @@ Test(sfmm_basecode_suite, free_coalesce, .timeout = TEST_TIMEOUT) { cr_assert(sf_errno == 0, "sf_errno is not zero!"); } -Test(sfmm_basecode_suite, freelist, .timeout = TEST_TIMEOUT) { - size_t sz_u = 200, sz_v = 150, sz_w = 50, sz_x = 150, sz_y = 200, sz_z = 250; +Test(sfmm_basecode_suite, freelist, .timeout = TEST_TIMEOUT) +{ + size_t sz_u = 200, sz_v = 150, sz_w = 50, sz_x = 150, sz_y = 200, sz_z = 250; void *u = sf_malloc(sz_u); /* void *v = */ sf_malloc(sz_v); void *w = sf_malloc(sz_w); @@ -177,12 +198,13 @@ Test(sfmm_basecode_suite, freelist, .timeout = TEST_TIMEOUT) { int i = 3; sf_block *bp = sf_free_list_heads[i].body.links.next; cr_assert_eq(&bp->header, (char *)y - 8, - "Wrong first block in free list %d: (found=%p, exp=%p)", - i, &bp->header, (char *)y - 8); + "Wrong first block in free list %d: (found=%p, exp=%p)", + i, &bp->header, (char *)y - 8); } -Test(sfmm_basecode_suite, realloc_larger_block, .timeout = TEST_TIMEOUT) { - size_t sz_x = sizeof(int), sz_y = 10, sz_x1 = sizeof(int) * 20; +Test(sfmm_basecode_suite, realloc_larger_block, .timeout = TEST_TIMEOUT) +{ + size_t sz_x = sizeof(int), sz_y = 10, sz_x1 = sizeof(int) * 20; void *x = sf_malloc(sz_x); /* void *y = */ sf_malloc(sz_y); x = sf_realloc(x, sz_x1); @@ -191,11 +213,11 @@ Test(sfmm_basecode_suite, realloc_larger_block, .timeout = TEST_TIMEOUT) { sf_block *bp = (sf_block *)((char *)x - 16); cr_assert((bp->header ^ MAGIC) & THIS_BLOCK_ALLOCATED, "Allocated bit is not set!"); cr_assert(((bp->header ^ MAGIC) & 0xfffffff0) == 96, - "Realloc'ed block size (%ld) not what was expected (%ld)!", - (bp->header ^ MAGIC) & 0xfffffff0, 96); + "Realloc'ed block size (%ld) not what was expected (%ld)!", + (bp->header ^ MAGIC) & 0xfffffff0, 96); cr_assert((((bp->header ^ MAGIC) >> 32) & 0xffffffff) == sz_x1, - "Realloc'ed block payload size (%ld) not what was expected (%ld)!", - (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz_x1); + "Realloc'ed block payload size (%ld) not what was expected (%ld)!", + (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz_x1); assert_quick_list_block_count(0, 1); assert_quick_list_block_count(32, 1); @@ -203,8 +225,9 @@ Test(sfmm_basecode_suite, realloc_larger_block, .timeout = TEST_TIMEOUT) { assert_free_block_count(816, 1); } -Test(sfmm_basecode_suite, realloc_smaller_block_splinter, .timeout = TEST_TIMEOUT) { - size_t sz_x = sizeof(int) * 20, sz_y = sizeof(int) * 16; +Test(sfmm_basecode_suite, realloc_smaller_block_splinter, .timeout = TEST_TIMEOUT) +{ + size_t sz_x = sizeof(int) * 20, sz_y = sizeof(int) * 16; void *x = sf_malloc(sz_x); void *y = sf_realloc(x, sz_y); @@ -214,11 +237,11 @@ Test(sfmm_basecode_suite, realloc_smaller_block_splinter, .timeout = TEST_TIMEOU sf_block *bp = (sf_block *)((char *)x - 16); cr_assert((bp->header ^ MAGIC) & THIS_BLOCK_ALLOCATED, "Allocated bit is not set!"); cr_assert(((bp->header ^ MAGIC) & 0xfffffff0) == 96, - "Realloc'ed block size (%ld) not what was expected (%ld)!", - (bp->header ^ MAGIC) & 0xfffffff0, 96); + "Realloc'ed block size (%ld) not what was expected (%ld)!", + (bp->header ^ MAGIC) & 0xfffffff0, 96); cr_assert((((bp->header ^ MAGIC) >> 32) & 0xffffffff) == sz_y, - "Realloc'ed block payload size (%ld) not what was expected (%ld)!", - (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz_y); + "Realloc'ed block payload size (%ld) not what was expected (%ld)!", + (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz_y); // There should be only one free block. assert_quick_list_block_count(0, 0); @@ -226,8 +249,9 @@ Test(sfmm_basecode_suite, realloc_smaller_block_splinter, .timeout = TEST_TIMEOU assert_free_block_count(880, 1); } -Test(sfmm_basecode_suite, realloc_smaller_block_free_block, .timeout = TEST_TIMEOUT) { - size_t sz_x = sizeof(double) * 8, sz_y = sizeof(int); +Test(sfmm_basecode_suite, realloc_smaller_block_free_block, .timeout = TEST_TIMEOUT) +{ + size_t sz_x = sizeof(double) * 8, sz_y = sizeof(int); void *x = sf_malloc(sz_x); void *y = sf_realloc(x, sz_y); @@ -236,25 +260,123 @@ Test(sfmm_basecode_suite, realloc_smaller_block_free_block, .timeout = TEST_TIME sf_block *bp = (sf_block *)((char *)x - 16); cr_assert((bp->header ^ MAGIC) & THIS_BLOCK_ALLOCATED, "Allocated bit is not set!"); cr_assert(((bp->header ^ MAGIC) & 0xfffffff0) == 32, - "Realloc'ed block size (%ld) not what was expected (%ld)!", - (bp->header ^ MAGIC) & 0xfffffff0, 32); + "Realloc'ed block size (%ld) not what was expected (%ld)!", + (bp->header ^ MAGIC) & 0xfffffff0, 32); cr_assert((((bp->header ^ MAGIC) >> 32) & 0xffffffff) == sz_y, - "Realloc'ed block payload size (%ld) not what was expected (%ld)!", - (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz_y); + "Realloc'ed block payload size (%ld) not what was expected (%ld)!", + (((bp->header ^ MAGIC) >> 32) & 0xffffffff), sz_y); // After realloc'ing x, we can return a block of size 48 // to the freelist. This block will go into the main freelist and be coalesced. // Note that we don't put split blocks into the quick lists because their sizes are not sizes // that were requested by the client, so they are not very likely to satisfy a new request. - assert_quick_list_block_count(0, 0); + assert_quick_list_block_count(0, 0); assert_free_block_count(0, 1); assert_free_block_count(944, 1); } //############################################ -//STUDENT UNIT TESTS SHOULD BE WRITTEN BELOW -//DO NOT DELETE THESE COMMENTS +// STUDENT UNIT TESTS SHOULD BE WRITTEN BELOW +// DO NOT DELETE THESE COMMENTS //############################################ -//Test(sfmm_student_suite, student_test_1, .timeout = TEST_TIMEOUT) { -//} +// Test(sfmm_student_suite, student_test_1, .timeout = TEST_TIMEOUT) { +// } + +Test(sfmm_basecode_suite, quicklist1, .timeout = TEST_TIMEOUT) +{ + + size_t sz_x = sizeof(int); + void *x1 = sf_malloc(sz_x); + void *x2 = sf_malloc(sz_x); + void *x3 = sf_malloc(sz_x); + void *x4 = sf_malloc(sz_x); + void *x5 = sf_malloc(sz_x); + void *x6 = sf_malloc(sz_x); + + sf_free(x1); + sf_free(x2); + sf_free(x3); + sf_free(x4); + sf_free(x5); + sf_free(x6); + + assert_quick_list_block_count(0, 1); + assert_free_block_count(0, 2); + assert_free_block_count(160, 1); + assert_free_block_count(784, 1); + + // First block in list should be the most recently freed block not in quick list. + int i = 0; + sf_block *bp = sf_quick_lists[i].first; + cr_assert_eq(&bp->header, (char *)x6 - 8, + "Wrong first block in free list %d: (found=%p, exp=%p)", + i, &bp->header, (char *)x6 - 8); +} + +Test(sfmm_basecode_suite, quicklist2, .timeout = TEST_TIMEOUT) +{ + + size_t sz_x = sizeof(int); + void *x1 = sf_malloc(sz_x); + void *x2 = sf_malloc(sz_x); + void *x3 = sf_malloc(sz_x); + void *x4 = sf_malloc(sz_x); + void *x5 = sf_malloc(sz_x); + + sf_free(x5); + sf_free(x4); + sf_free(x3); + sf_free(x2); + sf_free(x1); + + assert_quick_list_block_count(0, 5); + assert_free_block_count(0, 1); + assert_free_block_count(816, 1); + + + // First block in list should be the most recently freed block not in quick list. + int i = 0; + sf_block *bp = sf_quick_lists[i].first; + cr_assert_eq(&bp->header, (char *)x1 - 8, + "Wrong first block in free list %d: (found=%p, exp=%p)", + i, &bp->header, (char *)x1 - 8); +} + +Test(sfmm_basecode_suite, realloc1, .timeout = TEST_TIMEOUT) { + char * x1 = sf_malloc(2000-8); + char * x2 = sf_malloc(10000-8); + sf_free(x1); + x2 = sf_realloc(x2, 12000-8); + assert_quick_list_block_count(0, 0); + assert_free_block_count(0, 2); + assert_free_block_count(12000, 1); + assert_free_block_count(528, 1); +} + +Test(sfmm_basecode_suite, realloc2, .timeout = TEST_TIMEOUT) { + int *x1 = sf_malloc(sizeof(int)); + sf_malloc(sizeof(int)); + *x1 = 114514; + int *x3 = sf_realloc(x1, sizeof(double)); + x3 = sf_realloc(x1, sizeof(long)); + x3 = sf_realloc(x1, 24000); + + assert_quick_list_block_count(0, 1); + assert_free_block_count(0, 1); + assert_free_block_count(448, 1); + + cr_assert_eq(114514, (int)*x3, + "Wrong value: (found=%d, exp=%d)", + 114514, (int)*x3); +} + +Test(sfmm_basecode_suite, freepro, .signal=SIGABRT, .timeout = TEST_TIMEOUT) { + sf_malloc(sizeof(int)); + sf_free(sf_mem_start()); +} + +Test(sfmm_basecode_suite, freeepi, .signal=SIGABRT, .timeout = TEST_TIMEOUT) { + sf_malloc(sizeof(int)); + sf_free(((void *)(intptr_t)sf_mem_end()) - 2 * sizeof(sf_header)); +} \ No newline at end of file