diff options
Diffstat (limited to 'usr/klibc/realloc.c')
-rw-r--r-- | usr/klibc/realloc.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/usr/klibc/realloc.c b/usr/klibc/realloc.c new file mode 100644 index 0000000..14a2f2f --- /dev/null +++ b/usr/klibc/realloc.c @@ -0,0 +1,48 @@ +/* + * realloc.c + */ + +#include <stdlib.h> +#include <string.h> + +#include "malloc.h" + +/* FIXME: This is cheesy, it should be fixed later */ + +void *realloc(void *ptr, size_t size) +{ + struct free_arena_header *ah; + void *newptr; + size_t oldsize; + + if (!ptr) + return malloc(size); + + if (size == 0) { + free(ptr); + return NULL; + } + + /* Add the obligatory arena header, and round up */ + size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + + if (ah->a.size >= size && size >= (ah->a.size >> 2)) { + /* This field is a good size already. */ + return ptr; + } else { + /* Make me a new block. This is kind of bogus; we should + be checking the following block to see if we can do an + in-place adjustment... fix that later. */ + + oldsize = ah->a.size - sizeof(struct arena_header); + + newptr = malloc(size); + memcpy(newptr, ptr, (size < oldsize) ? size : oldsize); + free(ptr); + + return newptr; + } +} |