Advertisement
jkonefal

Untitled

Jan 17th, 2023
1,281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.09 KB | None | 0 0
  1. /*
  2.  * mm-naive.c - The fastest, least memory-efficient malloc package.
  3.  *
  4.  * In this naive approach, a block is allocated by simply incrementing
  5.  * the brk pointer.  Blocks are never coalesced or reused.  The size of
  6.  * a block is found at the first aligned word before the block (we need
  7.  * it for realloc).
  8.  *
  9.  * This code is correct and blazingly fast, but very bad usage-wise since
  10.  * it never frees anything.
  11.  */
  12. #include <assert.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <stdbool.h>
  17. #include <stdint.h>
  18. #include <stddef.h>
  19. #include <unistd.h>
  20.  
  21. #include "mm.h"
  22. #include "memlib.h"
  23.  
  24. /* If you want debugging output, use the following macro.  When you hand
  25.  * in, remove the #define DEBUG line. */
  26. #define DEBUG
  27. #ifdef DEBUG
  28. #define debug(...) printf(__VA_ARGS__)
  29. #else
  30. #define debug(...)
  31. #endif
  32.  
  33. /* do not change the following! */
  34. #ifdef DRIVER
  35. /* create aliases for driver tests */
  36. #define malloc mm_malloc
  37. #define free mm_free
  38. #define realloc mm_realloc
  39. #define calloc mm_calloc
  40. #endif /* def DRIVER */
  41.  
  42. static uint8_t *heap_begin; // first byte of heap
  43. static uint8_t *heap_end;   // first byte after the heap
  44.  
  45. typedef struct {
  46.   int32_t header;
  47.   /*
  48.    * We don't know what the size of the payload will be, so we will
  49.    * declare it as a zero-length array.  This allow us to obtain a
  50.    * pointer to the start of the payload.
  51.    */
  52.   uint8_t payload[];
  53. } block_t;
  54.  
  55. static size_t round_up(size_t size) {
  56.   return (size + ALIGNMENT - 1) & -ALIGNMENT;
  57. }
  58.  
  59. static size_t get_size(block_t *block) {
  60.   return block->header & -2;
  61. }
  62.  
  63. static size_t get_size_of_payload(block_t *block) {
  64.   return get_size(block) - 2 * offsetof(block_t, payload);
  65. }
  66.  
  67. static block_t *move_right(block_t *ptr, size_t how_much) {
  68.   uint8_t *help_ptr = (uint8_t *)ptr;
  69.   help_ptr += how_much;
  70.   return (block_t *)help_ptr;
  71. }
  72.  
  73. static block_t *move_left(block_t *ptr, size_t how_much) {
  74.   uint8_t *help_ptr = (uint8_t *)ptr;
  75.   help_ptr -= how_much;
  76.   return (block_t *)help_ptr;
  77. }
  78.  
  79. static void set_header(block_t *block, size_t size, bool current_is_allocated) {
  80.   block->header = size | current_is_allocated;
  81. }
  82.  
  83. static void set_footer(block_t *block, size_t size, bool is_allocated) {
  84.   block = move_right(block, size - sizeof(block_t));
  85.   block->header = size | is_allocated;
  86. }
  87.  
  88. static bool expand_heap(size_t size) {
  89.   // creates a free block at the end of heap of size at least 'size'
  90.   // returns true on success
  91.   size = round_up(2 * sizeof(block_t) + size);
  92.   block_t *free_block = mem_sbrk(size);
  93.   if ((long)free_block < 0)
  94.     return false;
  95.  
  96.   heap_end += size;
  97.   set_header(free_block, size, false);
  98.   set_footer(free_block, size, false);
  99.   return true;
  100. }
  101.  
  102. static bool next_is_free(block_t *block_next){
  103.   return block_next < (block_t *)heap_end && (!(block_next->header & 1));
  104. }
  105.  
  106. static void coalesce_with_next(block_t* left_block_ptr){
  107.   size_t left_size = get_size(left_block_ptr);
  108.   block_t *block_next = move_right(left_block_ptr, left_size);
  109.   size_t size_sum = left_size;
  110.   if (next_is_free(block_next)) {
  111.     size_sum += get_size(block_next);
  112.   }
  113.   set_header(left_block_ptr, size_sum, false);
  114.   set_footer(left_block_ptr, size_sum, false);
  115. }
  116.  
  117. static void coalesce_with_prev(block_t* right_block_ptr){
  118.   block_t *block_prev = right_block_ptr - 1;
  119.   if (right_block_ptr > (block_t *)heap_begin && (!(block_prev->header & 1))) {
  120.     block_t *block_prev_start =
  121.       move_left(block_prev, get_size(block_prev) - sizeof(block_t));
  122.     size_t size_sum = get_size(right_block_ptr) + get_size(block_prev_start);
  123.     set_header(block_prev_start, size_sum, false);
  124.     set_footer(block_prev_start, size_sum, false);
  125.   }
  126. }
  127.  
  128. static void split_blocks(block_t *block_ptr, size_t size){
  129.   size_t final_block_size = get_size(block_ptr);
  130.   size_t needed_size = round_up(2 * sizeof(block_t) + size);
  131.   if (get_size(block_ptr) - 2 * sizeof(block_t) > needed_size) {
  132.     block_t *new_block_ptr = move_right(block_ptr, needed_size);
  133.     size_t  new_block_size = get_size(block_ptr) - needed_size;
  134.     // if next block is free, we merge it with the current block
  135.     set_header(new_block_ptr, new_block_size, false);
  136.     set_footer(new_block_ptr, new_block_size, false);
  137.     final_block_size = needed_size;
  138.   }
  139.   set_header(block_ptr, final_block_size, true);
  140.   set_footer(block_ptr, final_block_size, true);
  141. }
  142. /*
  143.  * mm_init - Called when a new trace starts.
  144.  */
  145. int mm_init(void) {
  146.   /* Pad heap start so first payload is at ALIGNMENT. */
  147.   size_t offset = ALIGNMENT - sizeof(block_t);
  148.   uint8_t *fake_begin = mem_sbrk(offset);
  149.   if ((long)fake_begin < 0)
  150.     return -1;
  151.   heap_begin = fake_begin + offset;
  152.   heap_end = heap_begin;
  153.   return 0;
  154. }
  155.  
  156. /*
  157.  * malloc - Allocate a block by incrementing the brk pointer.
  158.  *      Always allocate a block whose size is a multiple of the alignment.
  159.  */
  160. void *malloc(size_t size) {
  161.   uint8_t *cur_ptr = heap_begin;
  162.   while (cur_ptr < heap_end) {
  163.     block_t *block_ptr = (block_t *)cur_ptr;
  164.     if (!(block_ptr->header & 1) && get_size_of_payload(block_ptr) >= size) {
  165.       break;
  166.     }
  167.     cur_ptr += get_size(block_ptr);
  168.   }
  169.   if (cur_ptr == heap_end) {
  170.     if (!expand_heap(size))
  171.       return NULL;
  172.   }
  173.  
  174.   block_t *block_ptr = (block_t *)cur_ptr;
  175.   split_blocks(block_ptr, size);
  176.   return block_ptr->payload;
  177. }
  178.  
  179. /*
  180.  * free - We don't know how to free a block.  So we ignore this call.
  181.  *      Computers have big memories; surely it won't be a problem.
  182.  */
  183. void free(void *ptr) {
  184.   if (ptr == NULL)
  185.     return;
  186.   block_t *block_ptr = (block_t *)ptr;
  187.   block_ptr -= 1;
  188.   coalesce_with_next(block_ptr);
  189.   coalesce_with_prev(block_ptr);
  190. }
  191.  
  192. /*
  193.  * realloc - Change the size of the block by mallocing a new block,
  194.  *      copying its data, and freeing the old block.
  195.  **/
  196. void *realloc(void *old_ptr, size_t size) {
  197.   /* If size == 0 then this is just free, and we return NULL. */
  198.   if (size == 0) {
  199.     free(old_ptr);
  200.     return NULL;
  201.   }
  202.  
  203.   /* If old_ptr is NULL, then this is just malloc. */
  204.   if (!old_ptr)
  205.     return malloc(size);
  206.  
  207.  
  208.   // /* Free the old block. */
  209.   // free(old_ptr);
  210.   block_t *old_block_ptr = (block_t *)old_ptr;
  211.   old_block_ptr -= 1;
  212.   size_t old_size = get_size(old_block_ptr);
  213.   if (size < old_size) {
  214.     split_blocks(old_block_ptr, size);
  215.     coalesce_with_next(move_right(old_block_ptr, get_size(old_block_ptr)));
  216.     return old_block_ptr;
  217.   }
  218.  
  219.   else {
  220.   void *new_ptr = malloc(size);
  221.  
  222.   /* If malloc() fails, the original block is left untouched. */
  223.   if (!new_ptr)
  224.     return NULL;
  225.  
  226.   /* Copy the old data. */
  227.   // if (size < old_size)
  228.   //   old_size = size;
  229.   memcpy(new_ptr, old_ptr, old_size);
  230.   free(old_ptr);
  231.   return new_ptr;
  232.   }
  233.  
  234. }
  235.  
  236. /*
  237.  * calloc - Allocate the block and set it to zero.
  238.  */
  239. void *calloc(size_t nmemb, size_t size) {
  240.   size_t bytes = nmemb * size;
  241.   void *new_ptr = malloc(bytes);
  242.  
  243.   /* If malloc() fails, skip zeroing out the memory. */
  244.   if (new_ptr)
  245.     memset(new_ptr, 0, bytes);
  246.  
  247.   return new_ptr;
  248. }
  249.  
  250. /*
  251.  * mm_checkheap - So simple, it doesn't need a checker!
  252.  */
  253. void mm_checkheap(int verbose) {
  254. }
  255.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement