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