github.com/afumu/libc@v0.0.6/musl/src/malloc/lite_malloc.c (about) 1 #include <stdlib.h> 2 #include <stdint.h> 3 #include <limits.h> 4 #include <errno.h> 5 #include <sys/mman.h> 6 #include "libc.h" 7 #include "lock.h" 8 #include "syscall.h" 9 10 #define ALIGN 16 11 12 /* This function returns true if the interval [old,new] 13 * intersects the 'len'-sized interval below &libc.auxv 14 * (interpreted as the main-thread stack) or below &b 15 * (the current stack). It is used to defend against 16 * buggy brk implementations that can cross the stack. */ 17 18 static int traverses_stack_p(uintptr_t old, uintptr_t new) 19 { 20 const uintptr_t len = 8<<20; 21 uintptr_t a, b; 22 23 b = (uintptr_t)libc.auxv; 24 a = b > len ? b-len : 0; 25 if (new>a && old<b) return 1; 26 27 b = (uintptr_t)&b; 28 a = b > len ? b-len : 0; 29 if (new>a && old<b) return 1; 30 31 return 0; 32 } 33 34 static void *__simple_malloc(size_t n) 35 { 36 static uintptr_t brk, cur, end; 37 static volatile int lock[1]; 38 static unsigned mmap_step; 39 size_t align=1; 40 void *p; 41 42 if (n > SIZE_MAX/2) { 43 errno = ENOMEM; 44 return 0; 45 } 46 47 if (!n) n++; 48 while (align<n && align<ALIGN) 49 align += align; 50 51 LOCK(lock); 52 53 cur += -cur & align-1; 54 55 if (n > end-cur) { 56 size_t req = n - (end-cur) + PAGE_SIZE-1 & -PAGE_SIZE; 57 58 if (!cur) { 59 brk = __syscall(SYS_brk, 0); 60 brk += -brk & PAGE_SIZE-1; 61 cur = end = brk; 62 } 63 64 if (brk == end && req < SIZE_MAX-brk 65 && !traverses_stack_p(brk, brk+req) 66 && __syscall(SYS_brk, brk+req)==brk+req) { 67 brk = end += req; 68 } else { 69 int new_area = 0; 70 req = n + PAGE_SIZE-1 & -PAGE_SIZE; 71 /* Only make a new area rather than individual mmap 72 * if wasted space would be over 1/8 of the map. */ 73 if (req-n > req/8) { 74 /* Geometric area size growth up to 64 pages, 75 * bounding waste by 1/8 of the area. */ 76 size_t min = PAGE_SIZE<<(mmap_step/2); 77 if (min-n > end-cur) { 78 if (req < min) { 79 req = min; 80 if (mmap_step < 12) 81 mmap_step++; 82 } 83 new_area = 1; 84 } 85 } 86 void *mem = __mmap(0, req, PROT_READ|PROT_WRITE, 87 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 88 if (mem == MAP_FAILED || !new_area) { 89 UNLOCK(lock); 90 return mem==MAP_FAILED ? 0 : mem; 91 } 92 cur = (uintptr_t)mem; 93 end = cur + req; 94 } 95 } 96 97 p = (void *)cur; 98 cur += n; 99 UNLOCK(lock); 100 return p; 101 } 102 103 weak_alias(__simple_malloc, malloc);