Patchwork [FYI,7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB

login
register
mail settings
Submitter Andreas Färber
Date Sept. 19, 2010, 10:50 p.m.
Message ID <1284936650-1203-8-git-send-email-andreas.faerber@web.de>
Download mbox | patch
Permalink /patch/65178/
State New
Headers show

Comments

Andreas Färber - Sept. 19, 2010, 10:50 p.m.
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 <mmlr@mlotz.ch>
---
 configure     |    1 +
 qemu-malloc.c |   53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 0 deletions(-)
Oliver Tappe - Sept. 20, 2010, 12:26 p.m.
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
Andreas Färber - Sept. 21, 2010, 10:29 p.m.
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

Patch

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;
 }