| #include "alloc.h" |
| #include "asm/page.h" |
| |
| void *malloc(size_t size) |
| { |
| return memalign(sizeof(long), size); |
| } |
| |
| void *calloc(size_t nmemb, size_t size) |
| { |
| void *ptr = malloc(nmemb * size); |
| if (ptr) |
| memset(ptr, 0, nmemb * size); |
| return ptr; |
| } |
| |
| #define METADATA_EXTRA (2 * sizeof(uintptr_t)) |
| #define OFS_SLACK (-2 * sizeof(uintptr_t)) |
| #define OFS_SIZE (-sizeof(uintptr_t)) |
| |
| static inline void *block_begin(void *mem) |
| { |
| uintptr_t slack = *(uintptr_t *)(mem + OFS_SLACK); |
| return mem - slack; |
| } |
| |
| static inline uintptr_t block_size(void *mem) |
| { |
| return *(uintptr_t *)(mem + OFS_SIZE); |
| } |
| |
| void free(void *ptr) |
| { |
| if (!alloc_ops->free) |
| return; |
| |
| void *base = block_begin(ptr); |
| uintptr_t sz = block_size(ptr); |
| |
| alloc_ops->free(base, sz); |
| } |
| |
| void *memalign(size_t alignment, size_t size) |
| { |
| void *p; |
| uintptr_t blkalign; |
| uintptr_t mem; |
| |
| if (!size) |
| return NULL; |
| |
| assert(alignment >= sizeof(void *) && is_power_of_2(alignment)); |
| assert(alloc_ops && alloc_ops->memalign); |
| |
| size += alignment - 1; |
| blkalign = MAX(alignment, alloc_ops->align_min); |
| size = ALIGN(size + METADATA_EXTRA, alloc_ops->align_min); |
| p = alloc_ops->memalign(blkalign, size); |
| assert(p); |
| |
| /* Leave room for metadata before aligning the result. */ |
| mem = (uintptr_t)p + METADATA_EXTRA; |
| mem = ALIGN(mem, alignment); |
| |
| /* Write the metadata */ |
| *(uintptr_t *)(mem + OFS_SLACK) = mem - (uintptr_t)p; |
| *(uintptr_t *)(mem + OFS_SIZE) = size; |
| return (void *)mem; |
| } |