about summary refs log tree commit diff
path: root/src/malloc/lite_malloc.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-03-30 09:29:49 -0400
committerRich Felker <dalias@aerifal.cx>2011-03-30 09:29:49 -0400
commit620a1346382f9e10b516bc168f86d499b6716769 (patch)
tree6dab9801089447ca15d25620d7d002a461079dca /src/malloc/lite_malloc.c
parent02084109f0f0d6e0a7fe4a8cb3a90a422725e264 (diff)
downloadmusl-620a1346382f9e10b516bc168f86d499b6716769.tar.gz
musl-620a1346382f9e10b516bc168f86d499b6716769.tar.xz
musl-620a1346382f9e10b516bc168f86d499b6716769.zip
rename __simple_malloc.c to lite_malloc.c - yes this affects behavior!
why does this affect behavior? well, the linker seems to traverse
archive files starting from its current position when resolving
symbols. since calloc.c comes alphabetically (and thus in sequence in
the archive file) between __simple_malloc.c and malloc.c, attempts to
resolve the "malloc" symbol for use by calloc.c were pulling in the
full malloc.c implementation rather than the __simple_malloc.c
implementation.

as of now, lite_malloc.c and malloc.c are adjacent in the archive and
in the correct order, so malloc.c should never be used to resolve
"malloc" unless it's already needed to resolve another symbol ("free"
or "realloc").
Diffstat (limited to 'src/malloc/lite_malloc.c')
-rw-r--r--src/malloc/lite_malloc.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/malloc/lite_malloc.c b/src/malloc/lite_malloc.c
new file mode 100644
index 00000000..c8293908
--- /dev/null
+++ b/src/malloc/lite_malloc.c
@@ -0,0 +1,46 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <errno.h>
+#include "libc.h"
+
+uintptr_t __brk(uintptr_t);
+
+#define ALIGN 16
+
+void *__simple_malloc(size_t n)
+{
+	static uintptr_t cur, brk;
+	uintptr_t base, new;
+	static int lock;
+	size_t align=1;
+
+	if (!n) n++;
+	if (n > SIZE_MAX/2) goto toobig;
+
+	while (align<n && align<ALIGN)
+		align += align;
+	n = n + align - 1 & -align;
+
+	LOCK(&lock);
+	if (!cur) cur = brk = __brk(0)+16;
+	base = cur + align-1 & -align;
+	if (n > SIZE_MAX - PAGE_SIZE - base) goto fail;
+	if (base+n > brk) {
+		new = base+n + PAGE_SIZE-1 & -PAGE_SIZE;
+		if (__brk(new) != new) goto fail;
+		brk = new;
+	}
+	cur = base+n;
+	UNLOCK(&lock);
+
+	return (void *)base;
+
+fail:
+	UNLOCK(&lock);
+toobig:
+	errno = ENOMEM;
+	return 0;
+}
+
+weak_alias(__simple_malloc, malloc);