From 80d078af312082fcfc162b5b5f6d379083d10487 Mon Sep 17 00:00:00 2001
From: zesstra <zesstra@zesstra.de>
Date: Thu, 21 May 2009 17:22:26 +0200
Subject: [PATCH 1/3] Use mmap() for getting memory from the system (slaballoc).

sbrk() and brk() are obsoleted and some systems (like Darwin) don't have a
working implementation anymore. If sbrk/brk() are not usable, but mmap()
is available, use mmap() for mapping anonymous memory which we then use.
If mmap() is not available, use the old fallback (system malloc()).
Changes some precompiler checks for SBRK_OK, which should be REPLACE_MALLOC.

Signed-off-by: zesstra <zesstra@zesstra.de>
---
 src/slaballoc.c |   70 ++++++++++++++++++++++++++++++++++++++++++++----------
 src/xalloc.c    |    4 +-
 2 files changed, 59 insertions(+), 15 deletions(-)

diff --git a/src/slaballoc.c b/src/slaballoc.c
index 96858fd..e32f77e 100644
--- a/src/slaballoc.c
+++ b/src/slaballoc.c
@@ -25,10 +25,10 @@
  *
  *  -- Small Blocks --
  *
- * Small blocks are allocations of up to (SMALL_BLOCK_NUM+1)*4 Bytes, currently
- * 68 Bytes. Such block are allocated from larger memory blocks ('slabs')
- * sized rough multiples of 4KByte. The size is determined such that the slab
- * holds at least 100 blocks.
+ * Small blocks are allocations of up to (SMALL_BLOCK_NUM+1)*GRANULARITY Bytes,
+ * currently 68-136 Bytes. Such block are allocated from larger memory blocks 
+ * ('slabs') sized rough multiples of 4KByte. The size is determined such that
+ * the slab holds at least 100 blocks.
  *
  * A slab consists of a header, followed by the blocks themselves. Free blocks
  * within a slab are linked together in a free list. When a slab is freshly
@@ -200,13 +200,17 @@
 #include "driver.h"
 #include "typedefs.h"
 
-#ifdef HAVE_MADVISE
+#if defined(HAVE_MADVISE) || defined(HAVE_MMAP)
+#    include <sys/types.h>
 #    include <sys/mman.h>
 #    define MADVISE(new,old)  madvise(new,old,MADV_RANDOM)
 #else
 #    define MADVISE(new,old)  NOOP
 #endif
 
+// for sysconf()
+#include <unistd.h>
+
 #include "slaballoc.h"
 
 #include "mstrings.h"
@@ -246,7 +250,11 @@
 #  else
 #      undef SBRK_OK
 #  endif
-#endif
+#else if defined (HAVE_MMAP)
+#  ifdef MALLOC_SBRK
+#      define REPLACE_MALLOC
+#  endif
+#endif // SBRK_OK
 
 #define MEM_MAIN_THREADSAFE
 
@@ -344,7 +352,7 @@
     */
 
 
-#ifdef SBRK_OK
+#if defined(MALLOC_SBRK) && (defined(SBRK_OK) || defined (HAVE_MMAP))
 #    define CHUNK_SIZE          0x40000
 #else
     /* It seems to be advantagous to be just below a power of two
@@ -933,7 +941,7 @@ mem_dump_data (strbuf_t *sbuf)
                );
 
     dump_stat("\npermanent blocks:  %8lu        %10lu\n", perm_st);
-#ifdef SBRK_OK
+#ifdef REPLACE_MALLOC
     dump_stat("clib allocations:  %8lu        %10lu\n", clib_st);
 #else
     strbuf_addf(sbuf, "clib allocations:       n/a               n/a\n");
@@ -3442,7 +3450,7 @@ esbrk (word_t size, size_t * pExtra)
  *
 #ifdef SBRK_OK
  * It is system dependent how sbrk() aligns data, so we simpy use brk()
- * to insure that we have enough.
+ * to ensure that we have enough.
  * At the end of the newly expanded heap we create a fake allocated
  * block of 0 bytes so that large_malloc() knows where to stop.
 #else
@@ -3487,6 +3495,7 @@ esbrk (word_t size, size_t * pExtra)
 #else  /* not SBRK_OK */
 
     char *block;
+    size_t req_size = size; // the requested size of memory.
     word_t *p;    /* start of the fake block */
     const int overhead = TL_OVERHEAD;
     size_t overlap = 0;
@@ -3494,16 +3503,31 @@ esbrk (word_t size, size_t * pExtra)
        * the new allocation with the old one.
        */
 
-
     mdb_log_sbrk(size);
     size += overhead * GRANULARITY;  /* for the extra fake "allocated" block */
 
+    // get the new memory block
+#ifdef HAVE_MMAP
+    {
+        static size_t pagesize = 0; // pagesize - 1 for this system.
+        if (!pagesize)
+            pagesize = getpagesize() - 1;
+        // round to multiples of the real pagesize
+        if ((size & pagesize) != 0)
+        {
+            size += pagesize;
+            size &= ~pagesize;
+        }
+        // get new page(s)
+        block = mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+        if (block == MAP_FAILED)
+            return NULL;
+    }
+#else
     block = malloc(size);
     if (!block)
-    {
-        *pExtra = 0;
         return NULL;
-    }
+#endif    
 
     assert_stack_gap();
 
@@ -3643,7 +3667,12 @@ esbrk (word_t size, size_t * pExtra)
     count_up(&sbrk_stat, size);
     count_up(&large_wasted_stat, overhead * GRANULARITY);
 
+    // amount of additional memory that was allocated
+#ifdef HAVE_MMAP
+    *pExtra = overlap + (size - overhead * GRANULARITY - req_size);
+#else
     *pExtra = overlap;
+#endif
     return block + GRANULARITY;
 #endif /* !SBRK_OK */
 } /* esbrk() */
@@ -4371,4 +4400,19 @@ mem_consolidate (Bool force)
 #endif /* MALLOC_EXT_STATISTICS */
 } /* mem_consolidate() */
 
+/*-------------------------------------------------------------------------*/
+#if !defined(HAVE_GETPAGESIZE)
+static INLINE size_t
+getpagesize()
+/* get the pagesize for this system */
+{
+#ifdef(HAVE_SYSCONF)
+    return sysconf(_SC_PAGESIZE);
+#else
+#error Unable to find out the system pagesize. Please report this issue.
+#endif
+}
+#endif /* HAVE_GETPAGESIZE */
+
 /***************************************************************************/
+
diff --git a/src/xalloc.c b/src/xalloc.c
index 89e5b58..0ae0784 100644
--- a/src/xalloc.c
+++ b/src/xalloc.c
@@ -182,7 +182,7 @@ static t_stat xalloc_stat = {0,0};
   /* Total number and size of allocations done by the driver (incl overhead).
    */
 
-#if defined(SBRK_OK)
+#if defined(MALLOC_SBRK) && (defined(SBRK_OK) || defined(HAVE_MMAP))
 static t_stat clib_alloc_stat = {0,0};
   /* Number and size of allocations done through the clib emulation
    * functions (incl overhead).
@@ -1178,7 +1178,7 @@ dump_malloc_trace (int d
 
 /*                     CLIB ALLOCATION FUNCTIONS                           */
 
-#if defined(REPLACE_MALLOC) && defined(SBRK_OK)
+#if defined(REPLACE_MALLOC) && (defined(SBRK_OK) || defined(HAVE_MMAP))
 
 /*-------------------------------------------------------------------------*/
 static POINTER
-- 
1.6.1

