123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- #include <errno.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <unistd.h>
- #define PAGE_4K_SHIFT 12
- #define PAGE_2M_SHIFT 21
- #define PAGE_1G_SHIFT 30
- #define PAGE_GDT_SHIFT 39
- #define PAGE_4K_SIZE (1UL << PAGE_4K_SHIFT)
- #define PAGE_2M_SIZE (1UL << PAGE_2M_SHIFT)
- #define PAGE_1G_SIZE (1UL << PAGE_1G_SHIFT)
- #define PAGE_4K_MASK (~(PAGE_4K_SIZE - 1))
- #define PAGE_2M_MASK (~(PAGE_2M_SIZE - 1))
- #define ALIGN_UP16(x) (((x) + 15) & ~15)
- #define PAGE_ALIGN_UP(x) (((x) + PAGE_4K_SIZE - 1) & PAGE_4K_MASK)
- typedef struct malloc_mem_chunk_t
- {
- uint64_t length;
- uint64_t padding;
- struct malloc_mem_chunk_t *prev;
- struct malloc_mem_chunk_t *next;
- } malloc_mem_chunk_t;
- static uint64_t brk_base_addr = 0;
- static uint64_t brk_max_addr = 0;
- static uint64_t brk_managed_addr = 0;
- static malloc_mem_chunk_t *malloc_free_list = NULL;
- static malloc_mem_chunk_t *malloc_free_list_end = NULL;
- static uint64_t count_last_free_size = 0;
- static void malloc_insert_free_list(malloc_mem_chunk_t *ck);
- static void release_brk();
- static malloc_mem_chunk_t *malloc_query_free_chunk_bf(uint64_t size)
- {
-
-
- if (malloc_free_list == NULL)
- {
- return NULL;
- }
- malloc_mem_chunk_t *ptr = malloc_free_list;
- malloc_mem_chunk_t *best = NULL;
-
- while (ptr != NULL)
- {
-
- if (ptr->length == size)
- {
- best = ptr;
- break;
- }
- if (ptr->length > size)
- {
- if (best == NULL)
- best = ptr;
- else if (best->length > ptr->length)
- best = ptr;
- }
- ptr = ptr->next;
- }
- return best;
- }
- static malloc_mem_chunk_t *malloc_query_free_chunk_ff(uint64_t size)
- {
- if (malloc_free_list == NULL)
- return NULL;
- malloc_mem_chunk_t *ptr = malloc_free_list;
- while (ptr)
- {
- if (ptr->length >= size)
- {
- return ptr;
- }
- ptr = ptr->next;
- }
- return NULL;
- }
- static int malloc_enlarge(int64_t size)
- {
- if (brk_base_addr == 0)
- {
- brk_base_addr = sbrk(0);
-
- brk_managed_addr = brk_base_addr;
- brk_max_addr = sbrk(0);
- }
- int64_t free_space = brk_max_addr - brk_managed_addr;
-
- if (free_space < size)
- {
- if (sbrk(PAGE_ALIGN_UP(size - free_space)) != (void *)(-1))
- brk_max_addr = sbrk((0));
- else
- {
-
- return -ENOMEM;
- }
-
- }
-
-
-
- malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)brk_managed_addr;
- new_ck->length = brk_max_addr - brk_managed_addr;
-
-
- new_ck->prev = NULL;
- new_ck->next = NULL;
- brk_managed_addr = brk_max_addr;
- malloc_insert_free_list(new_ck);
- return 0;
- }
- static void malloc_merge_free_chunk()
- {
- if (malloc_free_list == NULL)
- return;
- malloc_mem_chunk_t *ptr = malloc_free_list->next;
- while (ptr != NULL)
- {
-
- if (((uint64_t)(ptr->prev) + ptr->prev->length == (uint64_t)ptr))
- {
-
-
- ptr->prev->length += ptr->length;
- ptr->prev->next = ptr->next;
- if (ptr->next == NULL)
- malloc_free_list_end = ptr->prev;
- else
- ptr->next->prev = ptr->prev;
-
- ptr = ptr->prev;
- }
- ptr = ptr->next;
- }
- }
- static void malloc_insert_free_list(malloc_mem_chunk_t *ck)
- {
- if (malloc_free_list == NULL)
- {
- malloc_free_list = ck;
- malloc_free_list_end = ck;
- ck->prev = ck->next = NULL;
- return;
- }
- else
- {
- malloc_mem_chunk_t *ptr = malloc_free_list;
- while (ptr != NULL)
- {
- if ((uint64_t)ptr < (uint64_t)ck)
- {
- if (ptr->next == NULL)
- {
- ptr->next = ck;
- ck->next = NULL;
- ck->prev = ptr;
- malloc_free_list_end = ck;
- break;
- }
- else if ((uint64_t)(ptr->next) > (uint64_t)ck)
- {
- ck->prev = ptr;
- ck->next = ptr->next;
- ptr->next = ck;
- ck->next->prev = ck;
- break;
- }
- }
- else
- {
- if (ptr->prev == NULL)
- {
- malloc_free_list = ck;
- ck->prev = NULL;
- ck->next = ptr;
- ptr->prev = ck;
- break;
- }
- else
- {
- ck->prev = ptr->prev;
- ck->next = ptr;
- ck->prev->next = ck;
- ptr->prev = ck;
- break;
- }
- }
- ptr = ptr->next;
- }
- }
- }
- void *_dragonos_malloc(ssize_t size)
- {
-
- if (size < sizeof(malloc_mem_chunk_t) - 16)
- size = sizeof(malloc_mem_chunk_t);
- else
- {
- size += 16;
- }
-
- size = ALIGN_UP16(size);
-
- malloc_mem_chunk_t *ck = malloc_query_free_chunk_bf(size);
- if (ck == NULL)
- {
-
-
- malloc_merge_free_chunk();
- ck = malloc_query_free_chunk_bf(size);
-
- if (ck)
- goto found;
-
-
- if (malloc_enlarge(size) == -ENOMEM)
- return (void *)-ENOMEM;
- malloc_merge_free_chunk();
-
- ck = malloc_query_free_chunk_bf(size);
- }
- found:;
-
- if (ck == NULL)
- return (void *)-ENOMEM;
-
-
-
- if (ck->prev == NULL)
- {
- malloc_free_list = ck->next;
- }
- else
- ck->prev->next = ck->next;
- if (ck->next != NULL)
- ck->next->prev = ck->prev;
- else
- malloc_free_list_end = ck->prev;
-
- if ((int64_t)(ck->length) - size > sizeof(malloc_mem_chunk_t))
- {
-
- malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)(((uint64_t)ck) + size);
- new_ck->length = ck->length - size;
- new_ck->prev = new_ck->next = NULL;
-
- ck->length = size;
- malloc_insert_free_list(new_ck);
- }
-
-
- return (void *)((uint64_t)ck + 2 * sizeof(uint64_t));
- }
- static void release_brk()
- {
-
-
- if (malloc_free_list_end == NULL)
- {
- printf("release(): free list end is null. \n");
- return;
- }
- if ((uint64_t)malloc_free_list_end + malloc_free_list_end->length == brk_max_addr &&
- (uint64_t)malloc_free_list_end <= brk_max_addr - (PAGE_2M_SIZE << 1))
- {
- int64_t delta = ((brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK) - PAGE_2M_SIZE;
-
-
-
-
- if (delta <= 0)
- return;
- sbrk(-delta);
- brk_max_addr = sbrk(0);
- brk_managed_addr = brk_max_addr;
- malloc_free_list_end->length = brk_max_addr - (uint64_t)malloc_free_list_end;
- }
- }
- void _dragonos_free(void *ptr)
- {
-
- malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - 2 * sizeof(uint64_t));
-
- count_last_free_size += ck->length;
- malloc_insert_free_list(ck);
- if (count_last_free_size > PAGE_2M_SIZE)
- {
- count_last_free_size = 0;
- malloc_merge_free_chunk();
- release_brk();
- }
- }
- uint64_t _dragonos_chunk_length(void *ptr)
- {
- malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - 2 * sizeof(uint64_t));
- return ck->length;
- }
|