summaryrefslogtreecommitdiffstats
path: root/usr/klibc/sbrk.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/klibc/sbrk.c')
-rw-r--r--usr/klibc/sbrk.c45
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 */