diff options
Diffstat (limited to 'usr/klibc/sbrk.c')
-rw-r--r-- | usr/klibc/sbrk.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/usr/klibc/sbrk.c b/usr/klibc/sbrk.c new file mode 100644 index 0000000..4896ce0 --- /dev/null +++ b/usr/klibc/sbrk.c @@ -0,0 +1,45 @@ +/* sbrk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ +/* Modified 2003-2004 for klibc by H. Peter Anvin */ + +#include <stddef.h> +#include <unistd.h> +#include <inttypes.h> +#include <errno.h> +#include "malloc.h" + +#if !_KLIBC_NO_MMU /* uClinux doesn't have brk() */ + +char *__current_brk; /* Common with brk.c */ + +/* p is an address, a is alignment; must be a power of 2 */ +static inline void *align_up(void *p, uintptr_t a) +{ + return (void *)(((uintptr_t) p + a - 1) & ~(a - 1)); +} + +void *sbrk(ptrdiff_t increment) +{ + char *start, *end, *new_brk; + + if (!__current_brk) + __current_brk = __brk(NULL); + + start = align_up(__current_brk, _KLIBC_SBRK_ALIGNMENT); + end = start + increment; + + new_brk = __brk(end); + + if (new_brk == (void *)-1) + return (void *)-1; + else if (new_brk < end) { + errno = ENOMEM; + return (void *)-1; + } + + __current_brk = new_brk; + return start; +} + +#endif /* !_KLIBC_NO_MMU */ |