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