Advertisement
Guest User

Untitled

a guest
Mar 28th, 2020
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.32 KB | None | 0 0
  1. // This adds coalescing of free blocks.
  2. // Improves performance to 54/100 ... takes less time.
  3.  
  4. /*-------------------------------------------------------------------
  5. * Malloc Lab Starter code:
  6. * single doubly-linked free block list with LIFO policy
  7. * with support for coalescing adjacent free blocks
  8. *
  9. * Terminology:
  10. * o We will implement an explicit free list allocator.
  11. * o We use "next" and "previous" to refer to blocks as ordered in
  12. * the free list.
  13. * o We use "following" and "preceding" to refer to adjacent blocks
  14. * in memory.
  15. *-------------------------------------------------------------------- */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <assert.h>
  20. #include <unistd.h>
  21.  
  22. #include "memlib.h"
  23. #include "mm.h"
  24.  
  25. /* Macros for unscaled pointer arithmetic to keep other code cleaner.
  26. Casting to a char* has the effect that pointer arithmetic happens at
  27. the byte granularity (i.e. POINTER_ADD(0x1, 1) would be 0x2). (By
  28. default, incrementing a pointer in C has the effect of incrementing
  29. it by the size of the type to which it points (e.g. Block).)
  30. We cast the result to void* to force you to cast back to the
  31. appropriate type and ensure you don't accidentally use the resulting
  32. pointer as a char* implicitly.
  33. */
  34. #define UNSCALED_POINTER_ADD(p, x) ((void*)((char*)(p) + (x)))
  35. #define UNSCALED_POINTER_SUB(p, x) ((void*)((char*)(p) - (x)))
  36.  
  37.  
  38. /******** FREE LIST IMPLEMENTATION ***********************************/
  39.  
  40.  
  41. /* An BlockInfo contains information about a block, including the size
  42. as well as pointers to the next and previous blocks in the free list.
  43. This is similar to the "explicit free list" structure illustrated in
  44. the lecture slides.
  45.  
  46. Note that the next pointer are only needed when the block is free. To
  47. achieve better utilization, mm_malloc should use the space for next as
  48. part of the space it returns.
  49.  
  50. +--------------+
  51. | size | <- Block pointers in free list point here
  52. | |
  53. | (header) |
  54. | |
  55. | prev |
  56. +--------------+
  57. | nextFree | <- Pointers returned by mm_malloc point here
  58. | prevFree |
  59. +--------------+ (allocated blocks do not have a 'nextFree' field)
  60. | space and | (this is a space optimization...)
  61. | padding |
  62. | ... | Free blocks write their nextFree/prevFree pointers in
  63. | ... | this space.
  64. +--------------+
  65.  
  66. */
  67. typedef struct _BlockInfo {
  68. // Size of the block and whether or not the block is in use or free.
  69. // When the size is negative, the block is currently free.
  70. long int size;
  71. // Pointer to the previous block in the list.
  72. struct _Block* prev;
  73. } BlockInfo;
  74.  
  75. /* A FreeBlockInfo structure contains metadata just for free blocks.
  76. * When you are ready, you can improve your naive implementation by
  77. * using these to maintain a separate list of free blocks.
  78. *
  79. * These are "kept" in the region of memory that is normally used by
  80. * the program when the block is allocated. That is, since that space
  81. * is free anyway, we can make good use of it to improve our malloc.
  82. */
  83. typedef struct _FreeBlockInfo {
  84. // Pointer to the next free block in the list.
  85. struct _Block* nextFree;
  86. // Pointer to the previous free block in the list.
  87. struct _Block* prevFree;
  88. } FreeBlockInfo;
  89.  
  90. /* This is a structure that can serve as all kinds of nodes.
  91. */
  92. typedef struct _Block {
  93. BlockInfo info;
  94. FreeBlockInfo freeNode;
  95. } Block;
  96.  
  97. /* Pointer to the first FreeBlockInfo in the free list, the list's head. */
  98. static Block* free_list_head = NULL;
  99. static Block* malloc_list_tail = NULL;
  100.  
  101. static size_t heap_size = 0;
  102.  
  103. /* Size of a word on this architecture. */
  104. #define WORD_SIZE sizeof(void*)
  105.  
  106. /* Alignment of blocks returned by mm_malloc.
  107. * (We need each allocation to at least be big enough for the free space
  108. * metadata... so let's just align by that.) */
  109. #define ALIGNMENT (sizeof(FreeBlockInfo))
  110.  
  111. /* This function will have the OS allocate more space for our heap.
  112. *
  113. * It returns a pointer to that new space. That pointer will always be
  114. * larger than the last request and be continuous in memory.
  115. */
  116. void* requestMoreSpace(size_t reqSize);
  117.  
  118. /* This function will get the first block or returns NULL if there is not
  119. * one.
  120. *
  121. * You can use this to start your through search for a block.
  122. */
  123. Block* first_block();
  124.  
  125. /* This function will get the adjacent block or returns NULL if there is not
  126. * one.
  127. *
  128. * You can use this to move along your malloc list one block at a time.
  129. */
  130. Block* next_block(Block* block);
  131.  
  132. /* Use this function to print a thorough listing of your heap data structures.
  133. */
  134. void examine_heap();
  135.  
  136. /* Checks the heap for any issues and prints out errors as it finds them.
  137. *
  138. * Use this when you are debugging to check for consistency issues. */
  139. int check_heap();
  140.  
  141. Block* searchList(size_t reqSize) {
  142. Block* ptrFreeBlock = first_block();
  143. long int checkSize = -reqSize;
  144.  
  145. // ptrFreeBlock will point to the beginning of the memory heap!
  146. // end will point to the end of the memory heap.
  147. //
  148. // You want to go through every block until you hit the end.
  149. // Make sure you read the explanation for the next_block function above.
  150. // It should come in handy!
  151.  
  152. // YOUR CODE HERE!
  153. while(ptrFreeBlock != NULL) {
  154. if( ptrFreeBlock->info.size <= checkSize ) {
  155. //printf("Block of size %li is available for reqsize %li\n",ptrFreeBlock->info.size, checkSize);
  156. return ptrFreeBlock;
  157. }// Get next block
  158. else {
  159. //printf("Getting next block\n");
  160. ptrFreeBlock = next_block(ptrFreeBlock);
  161. }
  162. }
  163.  
  164. // To begin, you can ignore the free list and just go through every single
  165. // block in your memory looking for a free space big enough.
  166. //
  167. // Return NULL when you cannot find any available node big enough.
  168. return NULL;
  169. }
  170.  
  171. /* Find a free block of at least the requested size in the free list. Returns
  172. NULL if no free block is large enough. */
  173. Block* searchFreeList(size_t reqSize) {
  174. Block* ptrFreeBlock = free_list_head;
  175. long int checkSize = -reqSize;
  176.  
  177. //
  178. // YOUR CODE HERE!
  179. //
  180.  
  181. // When you are ready, you can implement the free list.
  182.  
  183. return NULL;
  184. }
  185.  
  186. // TOP-LEVEL ALLOCATOR INTERFACE ------------------------------------
  187.  
  188. /* Allocate a block of size size and return a pointer to it. If size is zero,
  189. * returns null.
  190. */
  191. void* mm_malloc(size_t size) {
  192. // You can change or remove the declarations
  193. // They are included as minor hints.
  194. Block* ptrFreeBlock = NULL;
  195. Block* splitBlock = NULL;
  196. long int reqSize;
  197.  
  198. // Zero-size requests get NULL.
  199. if (size == 0) {
  200. return NULL;
  201. }
  202. // Determine the amount of memory we want to allocate
  203. reqSize = size;
  204.  
  205. // Round up for correct alignment
  206. reqSize = ALIGNMENT * ((reqSize + ALIGNMENT - 1) / ALIGNMENT);
  207.  
  208. // Implement mm_malloc. You can change or remove any of the above
  209. // code. It is included as a suggestion of where to start.
  210. //
  211. // Remember to maintain your free_list_head
  212. // When you are ready to implement a free list, remove the searchList call
  213. // and uncomment the searchFreeList call below it.
  214. // YOUR CODE HERE! (ignore size and use reqSize for the amount to allocate!)
  215.  
  216. // Find Free Block of reqSize
  217. ptrFreeBlock = searchList(reqSize);
  218.  
  219. // Not Found, Req more Space
  220. if(ptrFreeBlock == NULL) {
  221. // Set Free block to given space
  222. ptrFreeBlock = (Block*)requestMoreSpace(reqSize + sizeof(BlockInfo));
  223. // Set size (will be positive)
  224. ptrFreeBlock->info.size = reqSize;
  225. // Keep track of very last block
  226. ptrFreeBlock->info.prev = malloc_list_tail;
  227. malloc_list_tail = ptrFreeBlock;
  228. //int check = check_heap();
  229. return UNSCALED_POINTER_ADD(ptrFreeBlock, sizeof(BlockInfo));
  230. } // Free block found
  231. else {
  232. unsigned long int minSplitSize = reqSize + sizeof(BlockInfo);
  233. // Check to see if can split
  234. if((ptrFreeBlock->info.size) <= - minSplitSize){
  235. long int tempSize = ptrFreeBlock->info.size;
  236. ptrFreeBlock->info.size = reqSize;
  237. splitBlock = (Block*)UNSCALED_POINTER_ADD(ptrFreeBlock, reqSize + sizeof(BlockInfo));
  238. splitBlock->info.prev = ptrFreeBlock;
  239. splitBlock->info.size = (tempSize + minSplitSize);
  240.  
  241. if(next_block(splitBlock) == NULL){
  242. malloc_list_tail = splitBlock;
  243. } else {
  244. next_block(splitBlock)->info.prev = splitBlock;
  245. }
  246. //int check = check_heap();
  247. return UNSCALED_POINTER_ADD(ptrFreeBlock, sizeof(BlockInfo));
  248. } else {
  249. ptrFreeBlock->info.size = -ptrFreeBlock->info.size;
  250. //int check = check_heap();
  251. return UNSCALED_POINTER_ADD(ptrFreeBlock, sizeof(BlockInfo));
  252. }
  253. }
  254. }
  255.  
  256. // Given a free block, coalesce with its neighbors if they are also free
  257. void coalesce(Block* blockInfo) {
  258. Block* nextBlock = next_block(blockInfo);
  259. Block* previousBlock = blockInfo->info.prev;
  260. Block* tmpBlock = NULL;
  261.  
  262. //long int newSize = blockInfo->info.size;
  263. //
  264. // YOUR CODE HERE!
  265. //if(nextBlock->info.size < 0) { nextBlockIsFree = true; }
  266. //if(previousBlock->info.size < 0) { prevBlockIsFree = true; }
  267.  
  268. // You can change or remove the declarations
  269. // above. They are included as minor hints.
  270. }
  271.  
  272. /* Free the block referenced by ptr. */
  273. void mm_free(void* ptr) {
  274. Block* blockInfo = (Block*)UNSCALED_POINTER_SUB(ptr, sizeof(BlockInfo));
  275.  
  276. //
  277. // YOUR CODE HERE!
  278. blockInfo->info.size = blockInfo->info.size*-1;
  279.  
  280. // You can change or remove the declarations
  281. // above. They are included as minor hints.
  282. //
  283. // Remember to maintain your free_list_head (Phase 3)
  284.  
  285. // When you are ready... you will want to implement coalescing:
  286. //coalesce(blockInfo);
  287. }
  288.  
  289. // PROVIDED FUNCTIONS -----------------------------------------------
  290. //
  291. // You do not need to modify these, but they might be helpful to read
  292. // over.
  293.  
  294. /* Get more heap space of exact size reqSize. */
  295. void* requestMoreSpace(size_t reqSize) {
  296. void* ret = UNSCALED_POINTER_ADD(mem_heap_lo(), heap_size);
  297. heap_size += reqSize;
  298.  
  299. void* mem_sbrk_result = mem_sbrk(reqSize);
  300. if ((size_t)mem_sbrk_result == -1) {
  301. printf("ERROR: mem_sbrk failed in requestMoreSpace\n");
  302. exit(0);
  303. }
  304.  
  305. return ret;
  306. }
  307.  
  308. /* Initialize the allocator. */
  309. int mm_init() {
  310. free_list_head = NULL;
  311. malloc_list_tail = NULL;
  312. heap_size = 0;
  313.  
  314. return 0;
  315. }
  316.  
  317. /* Gets the first block in the heap or returns NULL if there is not one. */
  318. Block* first_block() {
  319. Block* first = (Block*)mem_heap_lo();
  320. if (heap_size == 0) {
  321. return NULL;
  322. }
  323.  
  324. return first;
  325. }
  326.  
  327. /* Gets the adjacent block or returns NULL if there is not one. */
  328. Block* next_block(Block* block) {
  329. size_t distance = (block->info.size > 0) ? block->info.size : -block->info.size;
  330.  
  331. Block* end = (Block*)UNSCALED_POINTER_ADD(mem_heap_lo(), heap_size);
  332. Block* next = (Block*)UNSCALED_POINTER_ADD(block, sizeof(BlockInfo) + distance);
  333. if (next >= end) {
  334. return NULL;
  335. }
  336.  
  337. return next;
  338. }
  339.  
  340. /* Print the heap by iterating through it as an implicit free list. */
  341. void examine_heap() {
  342. /* print to stderr so output isn't buffered and not output if we crash */
  343. Block* curr = (Block*)mem_heap_lo();
  344. Block* end = (Block*)UNSCALED_POINTER_ADD(mem_heap_lo(), heap_size);
  345. fprintf(stderr, "heap size:\t0x%lx\n", heap_size);
  346. fprintf(stderr, "heap start:\t%p\n", curr);
  347. fprintf(stderr, "heap end:\t%p\n", end);
  348.  
  349. fprintf(stderr, "free_list_head: %p\n", (void*)free_list_head);
  350.  
  351. fprintf(stderr, "malloc_list_tail: %p\n", (void*)malloc_list_tail);
  352.  
  353. while(curr && curr < end) {
  354. /* print out common block attributes */
  355. fprintf(stderr, "%p: %ld\t", (void*)curr, curr->info.size);
  356.  
  357. /* and allocated/free specific data */
  358. if (curr->info.size > 0) {
  359. fprintf(stderr, "ALLOCATED\tprev: %p\n", (void*)curr->info.prev);
  360. } else {
  361. fprintf(stderr, "FREE\tnextFree: %p, prevFree: %p, prev: %p\n", (void*)curr->freeNode.nextFree, (void*)curr->freeNode.prevFree, (void*)curr->info.prev);
  362. }
  363.  
  364. curr = next_block(curr);
  365. }
  366. fprintf(stderr, "END OF HEAP\n\n");
  367.  
  368. curr = free_list_head;
  369. fprintf(stderr, "Head ");
  370. while(curr) {
  371. fprintf(stderr, "-> %p ", curr);
  372. curr = curr->freeNode.nextFree;
  373. }
  374. fprintf(stderr, "\n");
  375. }
  376.  
  377. /* Checks the heap data structure for consistency. */
  378. int check_heap() {
  379. Block* curr = (Block*)mem_heap_lo();
  380. Block* end = (Block*)UNSCALED_POINTER_ADD(mem_heap_lo(), heap_size);
  381. Block* last = NULL;
  382. long int free_count = 0;
  383.  
  384. while(curr && curr < end) {
  385. if (curr->info.prev != last) {
  386. fprintf(stderr, "check_heap: Error: previous link not correct.\n");
  387. examine_heap();
  388. }
  389.  
  390. if (curr->info.size <= 0) {
  391. // Free
  392. free_count++;
  393. }
  394.  
  395. last = curr;
  396. curr = next_block(curr);
  397. }
  398.  
  399. curr = free_list_head;
  400. last = NULL;
  401. while(curr) {
  402. if (curr == last) {
  403. fprintf(stderr, "check_heap: Error: free list is circular.\n");
  404. examine_heap();
  405. }
  406. last = curr;
  407. curr = curr->freeNode.nextFree;
  408. if (free_count == 0) {
  409. fprintf(stderr, "check_heap: Error: free list has more items than expected.\n");
  410. examine_heap();
  411. }
  412. free_count--;
  413. }
  414.  
  415. return 0;
  416. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement