Message ID | 1284936650-1203-8-git-send-email-andreas.faerber@web.de |
---|---|
State | New |
Headers | show |
Hi Andreas, On 2010-09-20 at 00:50:49 [+0200], Andreas Färber <andreas.faerber@web.de> wrote: > 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. Were you able to run any image in qemu on haiku with this? I'm asking because of haiku ticket #6606, which is about some problematic behaviour with respect to qemu not being able to resize an area (in effect aborting). Looking at the patch, I'd say it should still do the same ... cheers, Oliver
Hi, Am 20.09.2010 um 14:26 schrieb Oliver Tappe: > On 2010-09-20 at 00:50:49 [+0200], Andreas Färber <andreas.faerber@web.de > > wrote: >> 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. > > Were you able to run any image in qemu on haiku with this? As indicated, I built the ppc-softmmu system emulation. I was able to both play around in OpenBIOS [1] and to try booting Haiku/ppc [2], which doesn't go far due to OpenBIOS ofmem issues (cf. #6071). i386-softmmu needs more patches to compile. Haiku's math.h is missing some POSIX macros like isless[equal], isgreater, isunordered. That should be fixed in Haiku imo instead of being worked around in QEMU. QEMU's softfloat code has a wild mix of int32 and int though that may need to be remedied then, I have a patch in preparation for that. [1] qemu-system-ppc /dev/null [2] qemu-system-ppc -boot d -cdrom path/to/haiku-boot-cd-ppc.iso > I'm asking because of haiku ticket #6606, which is about some > problematic behaviour > with respect to qemu not being able to resize an area (in effect > aborting). Looking at > the patch, I'd say it should still do the same ... I had taken a look at #6606 and tried LD_PRELOAD=libroot-icu-addon.so qemu-system-ppc /dev/null -nographic without any luck. Note that vanilla QEMU does not use any areas at all, it uses malloc(), calloc(), realloc() and free(). The areas were just a workaround my mmlr and, to not miscredit him, he had the following explanation in his patch: +/* + The reason for the following mess is that somehow large allocations seem + to cause memory curruption. Most likely this is a bug in either Haiku or + QEMU. Since I wasn't able to repoduce the issue with other Haiku software + my first guess would go to QEMU, but who knows. In any case the hack below + makes larger allocations (>= 1MB) using areas instead of using the heap + to work around said issue. TODO: remove this when the reason is found/fixed! +*/ (I personally rather believe it's a bug in Haiku and that most BeOS/ Haiku apps don't encounter it since they use C++ new/new[]/delete/ delete[] but no realloc. But no one knows for sure until we've found out.) As seen in this patch of mine, QEMU has a new tracing framework that should (once it compiles - Haiku doesn't have clock_gettime) show us all successful (re)allocations and a build configured with --disable- strip shows us the crashing calloc args in gdb, so we could exactly reproduce the allocations and find out if that triggers it or not. Andreas
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; }