1 #include "alloc.h" 2 #include "asm/page.h" 3 4 void *malloc(size_t size) 5 { 6 return memalign(sizeof(long), size); 7 } 8 9 static bool mult_overflow(size_t a, size_t b) 10 { 11 #if BITS_PER_LONG == 32 12 /* 32 bit system, easy case: just use u64 */ 13 return (u64)a * (u64)b >= (1ULL << 32); 14 #else 15 #ifdef __SIZEOF_INT128__ 16 /* if __int128 is available use it (like the u64 case above) */ 17 unsigned __int128 res = a; 18 res *= b; 19 res >>= 64; 20 return res != 0; 21 #else 22 u64 tmp; 23 24 if ((a >> 32) && (b >> 32)) 25 return true; 26 if (!(a >> 32) && !(b >> 32)) 27 return false; 28 tmp = (u32)a; 29 tmp *= (u32)b; 30 tmp >>= 32; 31 if (a < b) 32 tmp += a * (b >> 32); 33 else 34 tmp += b * (a >> 32); 35 return tmp >> 32; 36 #endif /* __SIZEOF_INT128__ */ 37 #endif /* BITS_PER_LONG == 32 */ 38 } 39 40 void *calloc(size_t nmemb, size_t size) 41 { 42 void *ptr; 43 44 assert(!mult_overflow(nmemb, size)); 45 ptr = malloc(nmemb * size); 46 if (ptr) 47 memset(ptr, 0, nmemb * size); 48 return ptr; 49 } 50 51 #define METADATA_EXTRA (2 * sizeof(uintptr_t)) 52 #define OFS_SLACK (-2 * sizeof(uintptr_t)) 53 #define OFS_SIZE (-sizeof(uintptr_t)) 54 55 static inline void *block_begin(void *mem) 56 { 57 uintptr_t slack = *(uintptr_t *)(mem + OFS_SLACK); 58 return mem - slack; 59 } 60 61 static inline uintptr_t block_size(void *mem) 62 { 63 return *(uintptr_t *)(mem + OFS_SIZE); 64 } 65 66 void free(void *ptr) 67 { 68 if (!alloc_ops->free) 69 return; 70 71 void *base = block_begin(ptr); 72 uintptr_t sz = block_size(ptr); 73 74 alloc_ops->free(base, sz); 75 } 76 77 void *memalign(size_t alignment, size_t size) 78 { 79 void *p; 80 uintptr_t blkalign; 81 uintptr_t mem; 82 83 if (!size) 84 return NULL; 85 86 assert(alignment >= sizeof(void *) && is_power_of_2(alignment)); 87 assert(alloc_ops && alloc_ops->memalign); 88 89 size += alignment - 1; 90 blkalign = MAX(alignment, alloc_ops->align_min); 91 size = ALIGN(size + METADATA_EXTRA, alloc_ops->align_min); 92 p = alloc_ops->memalign(blkalign, size); 93 assert(p); 94 95 /* Leave room for metadata before aligning the result. */ 96 mem = (uintptr_t)p + METADATA_EXTRA; 97 mem = ALIGN(mem, alignment); 98 99 /* Write the metadata */ 100 *(uintptr_t *)(mem + OFS_SLACK) = mem - (uintptr_t)p; 101 *(uintptr_t *)(mem + OFS_SIZE) = size; 102 return (void *)mem; 103 } 104