qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [FYI 7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB


From: Andreas Färber
Subject: [Qemu-devel] [FYI 7/8] qemu_malloc: Use areas on Haiku for sizes > 1 MiB
Date: Mon, 20 Sep 2010 00:50:49 +0200

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]