Advertisement
tyler569

new malloc

Apr 5th, 2019
621
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.03 KB | None | 0 0
  1.  
  2. #include <basic.h>
  3. #include <debug.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. // #include <stdlib.h>
  7. #include <string.h>
  8. #include <mutex.h>
  9. #include <vmm.h>
  10. #include "malloc.h"
  11.  
  12. #if X86_64
  13. #define MALLOC_POOL (void*)0xFFFFFF0000000000
  14. #elif I686
  15. #define MALLOC_POOL (void*)0xC0000000
  16. #endif
  17.  
  18. #define ROUND_UP(x, to) ((x + to-1) & ~(to-1))
  19. #define PTR_ADD(p, off) (void*)(((char*)p) + off)
  20.  
  21. #define error_printf printf
  22.  
  23. void* malloc(size_t len);
  24. void* realloc(void* allocation, size_t len);
  25. void free(void* allocation);
  26. void* allogned_alloc(size_t alignment, size_t len);
  27.  
  28. #define MAGIC_NUMBER_1 (~12L)
  29. #define MAGIC_NUMBER_2 (0xDEADBEEFCAFEBABE)
  30.  
  31. #define STATUS_FREE  (1)
  32. #define STATUS_INUSE (2)
  33.  
  34. typedef struct mregion mregion;
  35. struct mregion {
  36.     unsigned long magic_number_1;
  37.     mregion* previous;
  38.     mregion* next;
  39.     unsigned long length;
  40.     int status;
  41.     unsigned long magic_number_2;
  42. };
  43.  
  44. #define MINIMUM_BLOCK (1 << 8) // 256B - is this too low (or high)?
  45.  
  46. // don't split a region if we're going to use most of it anyway
  47. // ( don't leave lots of tiny gaps )
  48. int should_split_mregion(mregion* orig, size_t candidiate);
  49.  
  50. mregion* split_mregion(mregion* orig, size_t split_at);
  51. mregion* merge_mregion(mregion* r1, mregion* r2);
  52.  
  53. // check magics and status are valid
  54. int validate_mregion(mregion* r);
  55.  
  56. #define POOL_LENGTH (1 << 24) // 16MB
  57.  
  58. void* pool = MALLOC_POOL;
  59. mregion* region_0;
  60.  
  61. void malloc_initialize() {
  62.     region_0 = pool;
  63.  
  64.     vmm_create_unbacked_range((uintptr_t)pool, POOL_LENGTH, PAGE_WRITEABLE);
  65.  
  66.     region_0->magic_number_1 = MAGIC_NUMBER_1;
  67.     region_0->previous = NULL;
  68.     region_0->next = NULL;
  69.     region_0->length = POOL_LENGTH - sizeof(mregion);
  70.     region_0->status = STATUS_FREE;
  71.     region_0->magic_number_2 = MAGIC_NUMBER_2;
  72. }
  73.  
  74. int validate_mregion(mregion* r) {
  75.     return
  76.         r->magic_number_1 == MAGIC_NUMBER_1 &&
  77.         r->magic_number_2 == MAGIC_NUMBER_2 &&
  78.         (r->status & !0x3) == 0;
  79. }
  80.  
  81. int should_split_mregion(mregion* r, size_t candidate) {
  82.     if (r->length < candidate) {
  83.         // not big enough
  84.         return 0;
  85.     }
  86.  
  87.     if (r->length - candidate < MINIMUM_BLOCK + sizeof(mregion)) {
  88.         // wouldn't leave enough space
  89.         return 0;
  90.     }
  91.     // should we split in the case that we leave only a 256b hole?
  92.     return 1;
  93. }
  94.  
  95. mregion* split_mregion(mregion* r, size_t split_at) {
  96.     size_t actual_offset = ROUND_UP(split_at, MINIMUM_BLOCK);
  97.  
  98.     if (!should_split_mregion(r, actual_offset)) {
  99.         return NULL;
  100.     }
  101.  
  102.     mregion* new_region = PTR_ADD(r, sizeof(mregion) + actual_offset);
  103.     new_region->magic_number_1 = MAGIC_NUMBER_1;
  104.     new_region->previous = r;
  105.     new_region->next = r->next;
  106.     new_region->length = r->length - actual_offset - sizeof(mregion);
  107.     new_region->status = STATUS_FREE;
  108.     new_region->magic_number_2 = MAGIC_NUMBER_2;
  109.  
  110.     r->next = new_region;
  111.     r->length = actual_offset;
  112.     if (new_region->next) {
  113.         new_region->next->previous = new_region;
  114.     }
  115.  
  116.     return new_region;
  117. }
  118.  
  119. mregion* merge_mregions(mregion* r1, mregion* r2) {
  120.     if (r1->status & STATUS_INUSE || r2->status & STATUS_INUSE) {
  121.         // can't update regions that are in use
  122.         return NULL;
  123.     }
  124.  
  125.     if (PTR_ADD(r1, sizeof(mregion) + r1->length) != r2) {
  126.         error_printf("tried to merge discontinuous regions (loc compare)\n");
  127.         return NULL;
  128.     }
  129.  
  130.     if (r2->previous != r1 || r1->next != r2) {
  131.         error_printf("tried to merge discontinuous regions (ptr compare)\n");
  132.         return NULL;
  133.     }
  134.  
  135.     r1->length += sizeof(mregion) + r2->length;
  136.     r1->next = r2->next;
  137.     if (r1->next) {
  138.         r1->next->previous = r1;
  139.     }
  140.    
  141.     return r1;
  142. }
  143.  
  144. void* malloc(size_t len) {
  145.     printf("malloc(%zu)\n", len);
  146.     mregion* cr;
  147.     for (cr=region_0; cr; cr=cr->next) {
  148.         if (cr->status == STATUS_FREE && cr->length >= len)
  149.             break;
  150.     }
  151.  
  152.     if (!cr) {
  153.         error_printf("no region available to handle malloc(%lu)\n", len);
  154.         return NULL;
  155.     }
  156.  
  157.     split_mregion(cr, len);
  158.  
  159.     cr->status = STATUS_INUSE;
  160.     return PTR_ADD(cr, sizeof(mregion));
  161. }
  162.  
  163. void* realloc(void* allocation, size_t len) {
  164.     if (!allocation) {
  165.         return malloc(len);
  166.     }
  167.  
  168.     mregion* to_realloc = PTR_ADD(allocation, -sizeof(mregion));
  169.     if (!validate_mregion(to_realloc)) {
  170.         error_printf("invalid pointer passed to realloc: %p\n", allocation);
  171.         return NULL;
  172.     }
  173.  
  174.     if (len < to_realloc->length) {
  175.         split_mregion(to_realloc, len);
  176.         return allocation;
  177.     }
  178.  
  179.     size_t old_len = to_realloc->length;
  180.  
  181.     if (merge_mregions(to_realloc, to_realloc->next)) {
  182.         if (len < to_realloc->length) {
  183.             split_mregion(to_realloc, len);
  184.         }
  185.        
  186.         return allocation;
  187.     }
  188.  
  189.     void* new_allocation = malloc(len);
  190.     if (!new_allocation)
  191.         return NULL;
  192.     memcpy(new_allocation, allocation, old_len);
  193.     free(allocation);
  194.     return new_allocation;
  195. }
  196.  
  197.  
  198. void* calloc(size_t count, size_t len) {
  199.     void* alloc = malloc(count * len);
  200.     if (!alloc)
  201.         return NULL;
  202.    
  203.     memset(alloc, 0, len);
  204.     return alloc;
  205. }
  206.  
  207. void free(void* allocation) {
  208.     if (!allocation) {
  209.         // free(NULL) is a nop
  210.         return;
  211.     }
  212.  
  213.     mregion* to_free = PTR_ADD(allocation, -sizeof(mregion));
  214.     if (!validate_mregion(to_free)) {
  215.         error_printf("invalid pointer passed to free: %p\n", allocation);
  216.         return;
  217.     }
  218.     to_free->status = STATUS_FREE;
  219.  
  220.     mregion* freed = to_free;
  221.     if (to_free->previous) {
  222.         freed = merge_mregions(to_free->previous, to_free);
  223.     }
  224.     if (freed && freed->next) {
  225.         merge_mregions(freed, freed->next);
  226.     } else if (!freed && to_free->next) {
  227.         merge_mregions(to_free, to_free->next);
  228.     }
  229.  
  230.     return;
  231. }
  232.  
  233.  
  234. // test stuff
  235.  
  236. void print_mregion(mregion* r) {
  237. }
  238.  
  239. void print_pool() {
  240.     printf("region, next, previous, length, status, valid\n");
  241.  
  242.     mregion* r;
  243.     for (r=region_0; r; r=r->next) {
  244.         printf("%p, %p, %p, %lu, %s, %s\n",
  245.                 r, r->next, r->previous, r->length,
  246.                   r->status == STATUS_FREE  ? "free" :
  247.                   r->status == STATUS_INUSE ? "used" : " BAD",
  248.                 validate_mregion(r) ? "valid" : "INVALID");
  249.     }
  250.     printf("**\n\n");
  251.  
  252.     return;
  253. }
  254.  
  255. void summarize_pool() {
  256.     size_t inuse_len = 0;
  257.     size_t total_len = 0;
  258.  
  259.     int inuse_regions = 0;
  260.     int total_regions = 0;
  261.  
  262.     mregion* r;
  263.     for (r=region_0; r; r=r->next) {
  264.         if (r->status == STATUS_INUSE) {
  265.             inuse_len += r->length;
  266.             inuse_regions++;
  267.         }
  268.         total_len += r->length;
  269.         total_regions++;
  270.  
  271.         if (!validate_mregion(r)) {
  272.             printf("INVALID_REGION: %p\n", r);
  273.         }
  274.     }
  275.  
  276.     printf("total len: %zu\n", total_len);
  277.     printf("inuse len: %zu\n", inuse_len);
  278.     printf("total regions: %i\n", total_regions);
  279.     printf("inuse regions: %i\n", inuse_regions);
  280. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement