Works around a calloc() SEGV in Haiku's libroot. Cf. http://dev.haiku-os.org/ticket/6637
Ported to HEAD based on a patch by Michael "mmlr" Lotz. Also consider the limit when reallocating. Cc: Michael Lotz <m...@mlotz.ch> --- configure | 1 + qemu-malloc.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 0 deletions(-) diff --git a/configure b/configure index 2ba35a4..3a0d50e 100755 --- a/configure +++ b/configure @@ -2354,6 +2354,7 @@ if test "$solaris" = "yes" ; then fi if test "$haiku" = "yes" ; then echo "CONFIG_HAIKU=y" >> $config_host_mak + echo "CONFIG_HAIKU_USE_AREAS=y" >> $config_host_mak fi if test "$static" = "yes" ; then echo "CONFIG_STATIC=y" >> $config_host_mak diff --git a/qemu-malloc.c b/qemu-malloc.c index ecffb67..ea75a6a 100644 --- a/qemu-malloc.c +++ b/qemu-malloc.c @@ -25,6 +25,11 @@ #include "trace.h" #include <stdlib.h> +#ifdef CONFIG_HAIKU_USE_AREAS +#include <OS.h> +static area_id sHeapArea = 0; +#endif + static void *oom_check(void *ptr) { if (ptr == NULL) { @@ -36,7 +41,18 @@ static void *oom_check(void *ptr) void qemu_free(void *ptr) { trace_qemu_free(ptr); +#ifdef CONFIG_HAIKU_USE_AREAS + if (ptr != NULL) { + area_id area = area_for(ptr); + if (area == sHeapArea) { +#endif free(ptr); +#ifdef CONFIG_HAIKU_USE_AREAS + } else { + delete_area(area); + } + } +#endif } static int allow_zero_malloc(void) @@ -54,7 +70,23 @@ void *qemu_malloc(size_t size) if (!size && !allow_zero_malloc()) { abort(); } +#ifdef CONFIG_HAIKU_USE_AREAS + if (size >= 1024 * 1024) { + if (create_area("qemu large alloc area", &ptr, B_ANY_ADDRESS, + ((size + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE, + B_NO_LOCK, B_READ_AREA | B_WRITE_AREA) < B_OK) { + ptr = NULL; + } + ptr = oom_check(ptr); + } else { +#endif ptr = oom_check(malloc(size ? size : 1)); +#ifdef CONFIG_HAIKU_USE_AREAS + if (sHeapArea == 0) { + sHeapArea = area_for(ptr); + } + } +#endif trace_qemu_malloc(size, ptr); return ptr; } @@ -65,7 +97,28 @@ void *qemu_realloc(void *ptr, size_t size) if (!size && !allow_zero_malloc()) { abort(); } +#ifdef CONFIG_HAIKU_USE_AREAS + area_id area = 0; + if (ptr != NULL) { + area = area_for(ptr); + } + if ((area == 0 || area == sHeapArea) && size < 1024 * 1024) { +#endif newptr = oom_check(realloc(ptr, size ? size : 1)); +#ifdef CONFIG_HAIKU_USE_AREAS + } else if (area == 0 || area == sHeapArea) { + free(ptr); + newptr = qemu_malloc(size); + } else { + if (resize_area(area, + ((size + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE) == B_OK) { + newptr = ptr; + } else { + newptr = NULL; + } + newptr = oom_check(newptr); + } +#endif trace_qemu_realloc(ptr, size, newptr); return newptr; } -- 1.7.1.rc2.7.g3e7f1