#include "stdlib.h"
#include "unistd.h"
#include <string.h>
#include <stddef.h>
#define BITS (sizeof (size_t) * 8)
#define MEMORY_GROW 131072
struct block_struct {
size_t size;
void *data[1];
};
#define BLOCK_HEADER_SIZE (offsetof(struct block_struct, data))
static size_t min_block_size;
static void *memory_end;
static void *heap_end = NULL;
static inline size_t nextpow2(size_t n)
{
register unsigned int k;
n--;
for (k = 1; k < BITS; k <<= 1)
n = n | n >> k;
return n + 1;
}
static int init_memory(void **memory_start)
{
void *addr;
if ((addr = __sbrk(0)) == (void *)-1)
return -1;
*memory_start = memory_end = addr;
return 0;
}
static int resize_memory(void *end)
{
size_t incr;
void *addr;
if (end > memory_end) {
incr = (end - memory_end + (MEMORY_GROW - 1)) / MEMORY_GROW * MEMORY_GROW;
if ((addr = __sbrk(incr)) == (void *)-1)
return -1;
memory_end = addr + incr;
}
return 0;
}
static int setup_heap()
{
min_block_size = nextpow2(sizeof (struct block_struct));
if (init_memory(&heap_end) == -1)
return -1;
heap_end += BLOCK_HEADER_SIZE;
heap_end = (void *)(((intptr_t)heap_end | (sizeof (union {long l; double d;}) - 1)) + 1);
heap_end -= BLOCK_HEADER_SIZE;
return 0;
}
static int grow_heap(size_t incr)
{
if (resize_memory(heap_end + incr) == -1)
return -1;
heap_end += incr;
return 0;
}
static struct block_struct *alloc_block(size_t size)
{
struct block_struct *block;
block = heap_end;
if (grow_heap(size) == -1)
return NULL;
block->size = size;
return block;
}
static int resize_block(struct block_struct *block, size_t size)
{
if (size == block->size)
return 1;
else if (size > block->size)
return 0;
else {
block->size = size;
return 1;
}
}
void __attribute__ ((weak, visibility ("default"))) *malloc(size_t size)
{
struct block_struct *block;
if (!heap_end)
if (setup_heap() == -1)
return NULL;
size += BLOCK_HEADER_SIZE;
size = (size + (min_block_size - 1)) & ~(min_block_size - 1);
if (!(block = alloc_block(size)))
return NULL;
return block->data;
}
typeof (malloc) __malloc __attribute__ ((alias ("malloc")));
void __attribute__ ((weak, visibility ("default"))) *calloc(size_t nmemb, size_t size)
{
void *ptr;
if (!(ptr = __malloc(nmemb * size)))
return NULL;
memset(ptr, 0, nmemb * size);
return ptr;
}
typeof (calloc) __calloc __attribute__ ((alias ("calloc")));
void __attribute__ ((weak, visibility ("default"))) free(void *ptr) {}
typeof (free) __free __attribute__ ((alias ("free")));
void __attribute__ ((weak, visibility ("default"))) *realloc(void *ptr, size_t size)
{
struct block_struct *block, *new_block;
if (ptr == NULL)
return __malloc(size);
if (size == 0) {
__free(ptr);
return NULL;
}
size += BLOCK_HEADER_SIZE;
size = (size + (min_block_size - 1)) & ~(min_block_size - 1);
block = ptr - BLOCK_HEADER_SIZE;
if (resize_block(block, size))
return ptr;
if (!(new_block = alloc_block(size)))
return NULL;
memcpy(new_block->data, block->data, (size < block->size ? size : block->size) - BLOCK_HEADER_SIZE);
return new_block->data;
}
typeof (realloc) __realloc __attribute__ ((alias ("realloc")));