aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-20 02:32:11 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-20 02:32:11 +0000
commitbe9d8ab8ec452c46777b2eb4ae925843d7361c7b (patch)
treeaad187010f9d0f268698c53273a86dc392207eb1
parent50cedb0ff19233273ef33cb5b5e8725025a35024 (diff)
downloadlpsm-be9d8ab8ec452c46777b2eb4ae925843d7361c7b.tar.gz
lpsm-be9d8ab8ec452c46777b2eb4ae925843d7361c7b.tar.xz
lpsm-be9d8ab8ec452c46777b2eb4ae925843d7361c7b.zip
Add calloc(), break alloc.c into free/malloc/mgmt files, add
automatic dependency generation.
-rw-r--r--Makefile21
-rw-r--r--calloc.c30
-rw-r--r--free.c155
-rw-r--r--malloc.c (renamed from alloc.c)240
-rw-r--r--mgmt.c137
5 files changed, 343 insertions, 240 deletions
diff --git a/Makefile b/Makefile
index f67108f..7208ca4 100644
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,10 @@ SONAME = libpsm.so.0
VERSION = 0.1.2
LIBPSM = libpsm.so libpsm.a
-OSOBJ = arena.o bitops.o alloc.o realloc.o zalloc.o stats.o
-OSPICOBJ = $(patsubst %.o,%.pic.o,$(OSOBJ))
+CFILES = arena.c bitops.c \
+ mgmt.c malloc.c free.c realloc.c zalloc.c calloc.c stats.c
+OSOBJ = $(patsubst %.c,%.o,$(CFILES))
+OSPICOBJ = $(patsubst %.c,%.pic.o,$(CFILES))
CC = gcc
# This is a reasonable set of flags for production
@@ -27,6 +29,9 @@ clean:
rm -f *.o *~ core *.dat *.log $(LIBPSM) $(TEST)
rm -f libpsm.so.*
+distclean: clean
+ rm -f *~ \#* .depend
+
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
@@ -60,3 +65,15 @@ test_mmap: test_mmap.o
ftrunctest: ftrunctest.o
$(CC) $(LDFLAGS) -o $@ $<
+
+.depend:
+ rm -f .depend
+ for cf in $(CFILES); do \
+ $(CC) $(CFLAGS) -E -Wp,-MM $$cf >> .depend ; \
+ $(CC) $(CFLAGS) -E -Wp,-MM $$cf | sed -e 's/\.o/\.pic\.o/' >> .depend ; \
+ done
+
+dep: .depend
+
+-include .depend
+
diff --git a/calloc.c b/calloc.c
new file mode 100644
index 0000000..b53c87f
--- /dev/null
+++ b/calloc.c
@@ -0,0 +1,30 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2000-2001 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, Inc.,
+ * 59 Temple Place Ste 330, Boston MA 02111-1307, USA, version 2.1,
+ * incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * calloc.c
+ *
+ * Wrapper around zalloc(). Necessary in case inlining is completely
+ * turned off in the user application.
+ *
+ */
+
+#include <stdlib.h>
+
+/* Do this rather than #include "lpms.h" so we don't get the inline... */
+extern void *lpsm_zalloc(size_t size);
+
+void *lpsm_calloc(size_t nmemb, size_t size)
+{
+ return lpsm_zalloc(nmemb*size);
+}
diff --git a/free.c b/free.c
new file mode 100644
index 0000000..627e53f
--- /dev/null
+++ b/free.c
@@ -0,0 +1,155 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2000-2001 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, Inc.,
+ * 59 Temple Place Ste 330, Boston MA 02111-1307, USA, version 2.1,
+ * incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * free.c
+ *
+ * Provides free() for the persistent memory allocator.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+
+#include "lpsm.h"
+#include "internals.h"
+#include "bitops.h"
+
+static void lpsm_free_chunk(int xbit, int rorder)
+{
+ if ( rorder > 0 ) {
+ int bxbit = xbit^1; /* Buddy xbit */
+ if ( test_bit(AH->free_bitmap, bxbit) ) {
+ /* Buddy is free. */
+ clr_bit(AH->free_bitmap, bxbit);
+ DPRINTF(("buddy: coalescing rorder %2d %d %d -> %2d %d\n",
+ rorder, xbit, bxbit, rorder-1, (xbit >> 1)));
+ lpsm_free_chunk((xbit >> 1), rorder-1);
+ return;
+ }
+ }
+ set_bit(AH->free_bitmap, xbit);
+}
+
+/*
+ * This routine finds the parameters for one particular
+ * buddy allocation from its address; used by free() and
+ * realloc().
+ */
+struct buddy_params lpsm_find_alloc_buddy(void *ptr)
+{
+ struct buddy_params bp;
+ uintptr_t offset = (uintptr_t)ptr - (uintptr_t)AH->data_start;
+ int order, rorder;
+ int xbit, obit;
+
+ assert(offset < (1UL << AH->arena_size_lg2)); /* Not inside the arena?? */
+
+ for ( rorder = 0, order = AH->arena_size_lg2 ;
+ order >= BUDDY_ORDER_MIN ;
+ rorder++, order-- ) {
+ if ( offset & ((1UL << order)-1) )
+ continue; /* Can't be this order */
+
+ obit = 1 << rorder;
+ xbit = obit + (offset >> order);
+
+ if ( test_bit(AH->alloc_bitmap, xbit) ) {
+ /* We're this order... */
+ bp.xbit = xbit; bp.rorder = rorder;
+ return bp;
+ }
+ }
+
+ abort(); /* Freeing bogus memory? */
+}
+
+void lpsm_free_buddy(void *ptr)
+{
+ struct buddy_params bp;
+
+ DPRINTF(("buddy: freeing allocation at %p\n", ptr));
+ bp = lpsm_find_alloc_buddy(ptr);
+ DPRINTF(("buddy: freeing rorder %2d %8d\n", bp.rorder, bp.xbit));
+ clr_bit(AH->alloc_bitmap, bp.xbit);
+ lpsm_free_chunk(bp.xbit, bp.rorder);
+}
+
+void lpsm_free_slab(void *ptr)
+{
+ struct slab_header *sh;
+ struct slab_info *si;
+ int offset, which, free_count;
+ unsigned char *slab_bitmap;
+
+ /* Slab header should be at the start of the page */
+ sh = (struct slab_header *)((uintptr_t)ptr & ~(BUDDY_SIZE_MIN-1));
+ assert(sh->magic == SLAB_MAGIC);
+ si = &AH->slab[sh->index];
+ slab_bitmap = (unsigned char *)sh +
+ ((sizeof(struct slab_header)+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
+
+ DPRINTF(("slab: Freeing size %d slab at %p, %d/%d allocated\n",
+ si->size, ptr, si->count-sh->free_count, si->count));
+
+ offset = ((uintptr_t)ptr & (BUDDY_SIZE_MIN-1)) - si->data_offset;
+ assert(offset >= 0);
+ which = offset/si->size;
+ assert(offset == which*si->size);
+
+ free_count = sh->free_count;
+ si->alloc_slabs--;
+
+ if ( free_count == si->count-1 ) {
+ /* Deallocated the entire page; give back to buddy system */
+ DPRINTF(("slab: Returning page %p back to the buddy system\n", sh));
+ *(sh->rev) = sh->next; /* Remove from free list */
+ if ( sh->next ) {
+ sh->next->rev = sh->rev;
+ assert(sh->next->index == sh->index);
+ }
+ si->total_pages--;
+#ifndef NDEBUG
+ /* This unfortunately makes the page dirty */
+ memset(sh, 0, BUDDY_SIZE_MIN);
+#endif
+ lpsm_free_buddy(sh);
+ } else {
+ set_bit(slab_bitmap, which);
+ sh->free_count = free_count+1;
+ if ( free_count == 0 ) {
+ /* Page is no longer full, add to free list */
+ DPRINTF(("slab: Adding page %p back onto free list for slab size %d\n",
+ sh, si->size));
+ assert(sh->index == si - &AH->slab[0]);
+ sh->rev = &(si->list);
+ sh->next = si->list;
+ if ( sh->next ) {
+ sh->next->rev = &(sh->next);
+ assert(sh->next->index == sh->index);
+ }
+ si->list = sh;
+ }
+ }
+}
+
+void lpsm_free(void *ptr)
+{
+ /* Buddy allocations are ALWAYS page-aligned, SLAB allocations never */
+ if ( (uintptr_t)ptr & (BUDDY_SIZE_MIN-1) )
+ lpsm_free_slab(ptr);
+ else
+ lpsm_free_buddy(ptr);
+}
diff --git a/alloc.c b/malloc.c
index 8a80e2e..e2ae112 100644
--- a/alloc.c
+++ b/malloc.c
@@ -12,16 +12,9 @@
* ----------------------------------------------------------------------- */
/*
- * alloc.c
+ * malloc.c
*
- * Provide persistent storage management (basic infrastructure.)
- *
- * This code uses a modified buddy system allocator for large allocations
- * and a SLAB allocator for small allocations.
- *
- * This generally assumes 8-bit bytes and 2's-complement arithmetric,
- * and that an all-zero bit pattern is a valid NULL. These days, that's
- * oh-such-a-strech...
+ * Provide malloc() for the persistent memory allocator.
*/
#include <assert.h>
@@ -34,108 +27,6 @@
#include "internals.h"
#include "bitops.h"
-struct arena_header *lpsm_arena_header;
-
-static const unsigned char lpsm_arena_magic[16] =
-"\x4f\xd4\x5a\x16\xa0\xaf\xd5\x52\x56\xf1\x1c\x9c\x1c\xed\xcc";
-static const unsigned char lpsm_arena_zero[16] =
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-
-/* Change these if BUDDY_ORDER_MIN or MINIMUM_ALIGN is changed */
-/* These MUST be ordered in order of decreasing size. 0 is end of list. */
-/* This particular set of slab sizes should work well for both a
- 16- and 24-byte header size. */
-static int slabsizes[] =
-{
- 2032, 1344, 1016, 800, 576, 448, 256, 192, 128, 96, 64, 48, 32, 16, 8, 4, 2, 1, 0
-};
-
-/*
- * Initalize the object store arena allocator. This returns NULL
- * on failure, or a pointer to the "root data pointer" array if
- * successful.
- */
-void **lpsm_init(const char *main_file, const char *log_file)
-{
- size_t arena_len = sizeof(struct arena_header); /* Minimum initial size */
-
- if ( !lpsm_arena_init(main_file, log_file, &arena_len) )
- return NULL; /* Failed to initialize arena */
-
- AH = (struct arena_header *)PM->arena;
-
- if ( memcmp(AH->arena_magic, lpsm_arena_magic, 16) != 0 ) {
- if ( memcmp(AH->arena_magic, lpsm_arena_zero, 16) == 0 ) {
- size_t total_size, bitmap_size;
- int i, header_pad;
-
- memset(AH, 0, sizeof(*AH)); /* Just in case */
-
- /* Uninitialized arena */
- memcpy(AH->arena_magic, lpsm_arena_magic, 16);
- AH->arena_byteorder = 0x12345678;
- AH->arena_bytesize = CHAR_BIT;
- AH->arena_ptrsize = sizeof(void *);
- AH->arena_base = (void *)AH;
- AH->buddy_order_min = BUDDY_ORDER_MIN;
-
- /* Header size must be padded to a multiple of BUDDY_SIZE_MIN
- as well as the hardware page size; this better be a power of 2! */
- header_pad = (PM->pagesize > BUDDY_SIZE_MIN)
- ? PM->pagesize : BUDDY_SIZE_MIN;
- assert((header_pad & (header_pad-1)) == 0);
- AH->header_size = (sizeof(struct arena_header) + header_pad - 1)
- & ~(header_pad-1);
-
- AH->data_start = (char *)AH + AH->header_size;
- AH->arena_size_lg2 = ARENA_START_SIZE_LG2;
- bitmap_size = 1UL << (ARENA_START_SIZE_LG2-BUDDY_ORDER_MIN-1);
- total_size = AH->header_size + ARENA_START_SIZE + (bitmap_size << 1);
- AH->free_bitmap = (char *)AH->data_start + ARENA_START_SIZE;
- AH->alloc_bitmap = (char *)AH->free_bitmap + bitmap_size;
-
- if ( lpsm_extend(total_size) < 0 )
- return NULL; /* Failed to establish initial arena */
-
- /* Compute SLAB definitions */
- for ( i = 0 ; slabsizes[i] ; i++ ) {
- int header_size = sizeof(struct slab_header);
- int bytes = BUDDY_SIZE_MIN - header_size;
- int size = slabsizes[i];
- int count = bytes/size;
- int data_offset;
-
- while ( 1 ) {
- /* Compute header+bitmap size in bytes; rounded up to MINIMUM_ALIGN */
- data_offset = header_size + ((count+7) >> 3);
- data_offset = ((data_offset+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
- if ( data_offset+count*size <= BUDDY_SIZE_MIN )
- break;
-
- count--;
- }
- AH->slab[i].size = size;
- AH->slab[i].count = count;
- AH->slab[i].data_offset = data_offset;
- }
-
- /* The bitmasks contains zeroes already; set the free bit on the topmost order. */
- set_bit(AH->free_bitmap, 1);
- }
- }
-
- if ( memcmp(AH->arena_magic, lpsm_arena_magic, 16) != 0 ||
- AH->arena_byteorder != 0x12345678 ||
- AH->arena_bytesize != CHAR_BIT ||
- AH->arena_ptrsize != sizeof(void *) ||
- AH->arena_base != (void *)AH ||
- AH->buddy_order_min != BUDDY_ORDER_MIN ) {
- return NULL; /* Incompatible or corrupt arena */
- }
-
- return AH->root_data_ptrs;
-}
-
/*
* This function expands a bitmap from oorder orders to norder orders.
* This will not operate properly on a bitmap (old or new) that covers
@@ -414,130 +305,3 @@ void *lpsm_malloc(size_t size)
else
return lpsm_malloc_slab(size);
}
-
-static void lpsm_free_chunk(int xbit, int rorder)
-{
- if ( rorder > 0 ) {
- int bxbit = xbit^1; /* Buddy xbit */
- if ( test_bit(AH->free_bitmap, bxbit) ) {
- /* Buddy is free. */
- clr_bit(AH->free_bitmap, bxbit);
- DPRINTF(("buddy: coalescing rorder %2d %d %d -> %2d %d\n",
- rorder, xbit, bxbit, rorder-1, (xbit >> 1)));
- lpsm_free_chunk((xbit >> 1), rorder-1);
- return;
- }
- }
- set_bit(AH->free_bitmap, xbit);
-}
-
-/*
- * This routine finds the parameters for one particular
- * buddy allocation from its address; used by free() and
- * realloc().
- */
-struct buddy_params lpsm_find_alloc_buddy(void *ptr)
-{
- struct buddy_params bp;
- uintptr_t offset = (uintptr_t)ptr - (uintptr_t)AH->data_start;
- int order, rorder;
- int xbit, obit;
-
- assert(offset < (1UL << AH->arena_size_lg2)); /* Not inside the arena?? */
-
- for ( rorder = 0, order = AH->arena_size_lg2 ;
- order >= BUDDY_ORDER_MIN ;
- rorder++, order-- ) {
- if ( offset & ((1UL << order)-1) )
- continue; /* Can't be this order */
-
- obit = 1 << rorder;
- xbit = obit + (offset >> order);
-
- if ( test_bit(AH->alloc_bitmap, xbit) ) {
- /* We're this order... */
- bp.xbit = xbit; bp.rorder = rorder;
- return bp;
- }
- }
-
- abort(); /* Freeing bogus memory? */
-}
-
-void lpsm_free_buddy(void *ptr)
-{
- struct buddy_params bp;
-
- DPRINTF(("buddy: freeing allocation at %p\n", ptr));
- bp = lpsm_find_alloc_buddy(ptr);
- DPRINTF(("buddy: freeing rorder %2d %8d\n", bp.rorder, bp.xbit));
- clr_bit(AH->alloc_bitmap, bp.xbit);
- lpsm_free_chunk(bp.xbit, bp.rorder);
-}
-
-void lpsm_free_slab(void *ptr)
-{
- struct slab_header *sh;
- struct slab_info *si;
- int offset, which, free_count;
- unsigned char *slab_bitmap;
-
- /* Slab header should be at the start of the page */
- sh = (struct slab_header *)((uintptr_t)ptr & ~(BUDDY_SIZE_MIN-1));
- assert(sh->magic == SLAB_MAGIC);
- si = &AH->slab[sh->index];
- slab_bitmap = (unsigned char *)sh +
- ((sizeof(struct slab_header)+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
-
- DPRINTF(("slab: Freeing size %d slab at %p, %d/%d allocated\n",
- si->size, ptr, si->count-sh->free_count, si->count));
-
- offset = ((uintptr_t)ptr & (BUDDY_SIZE_MIN-1)) - si->data_offset;
- assert(offset >= 0);
- which = offset/si->size;
- assert(offset == which*si->size);
-
- free_count = sh->free_count;
- si->alloc_slabs--;
-
- if ( free_count == si->count-1 ) {
- /* Deallocated the entire page; give back to buddy system */
- DPRINTF(("slab: Returning page %p back to the buddy system\n", sh));
- *(sh->rev) = sh->next; /* Remove from free list */
- if ( sh->next ) {
- sh->next->rev = sh->rev;
- assert(sh->next->index == sh->index);
- }
- si->total_pages--;
-#ifndef NDEBUG
- /* This unfortunately makes the page dirty */
- memset(sh, 0, BUDDY_SIZE_MIN);
-#endif
- lpsm_free_buddy(sh);
- } else {
- set_bit(slab_bitmap, which);
- sh->free_count = free_count+1;
- if ( free_count == 0 ) {
- /* Page is no longer full, add to free list */
- DPRINTF(("slab: Adding page %p back onto free list for slab size %d\n",
- sh, si->size));
- assert(sh->index == si - &AH->slab[0]);
- sh->rev = &(si->list);
- sh->next = si->list;
- if ( sh->next ) {
- sh->next->rev = &(sh->next);
- assert(sh->next->index == sh->index);
- }
- si->list = sh;
- }
- }
-}
-
-void lpsm_free(void *ptr)
-{
- /* Buddy allocations are ALWAYS page-aligned, SLAB allocations never */
- if ( (uintptr_t)ptr & (BUDDY_SIZE_MIN-1) )
- lpsm_free_slab(ptr);
- else
- lpsm_free_buddy(ptr);
-}
diff --git a/mgmt.c b/mgmt.c
new file mode 100644
index 0000000..c123d7d
--- /dev/null
+++ b/mgmt.c
@@ -0,0 +1,137 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2000-2001 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, Inc.,
+ * 59 Temple Place Ste 330, Boston MA 02111-1307, USA, version 2.1,
+ * incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mgmt.c
+ *
+ * Provide persistent storage management (basic infrastructure.)
+ *
+ * This code uses a modified buddy system allocator for large allocations
+ * and a SLAB allocator for small allocations.
+ *
+ * This generally assumes 8-bit bytes and 2's-complement arithmetric,
+ * and that an all-zero bit pattern is a valid NULL. These days, that's
+ * oh-such-a-strech...
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+
+#include "lpsm.h"
+#include "internals.h"
+#include "bitops.h"
+
+struct arena_header *lpsm_arena_header;
+
+static const unsigned char lpsm_arena_magic[16] =
+"\x4f\xd4\x5a\x16\xa0\xaf\xd5\x52\x56\xf1\x1c\x9c\x1c\xed\xcc";
+static const unsigned char lpsm_arena_zero[16] =
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+/* Change these if BUDDY_ORDER_MIN or MINIMUM_ALIGN is changed */
+/* These MUST be ordered in order of decreasing size. 0 is end of list. */
+/* This particular set of slab sizes should work well for both a
+ 16- and 24-byte header size. */
+static int slabsizes[] =
+{
+ 2032, 1344, 1016, 800, 576, 448, 256, 192, 128, 96, 64, 48, 32, 16, 8, 4, 2, 1, 0
+};
+
+/*
+ * Initalize the object store arena allocator. This returns NULL
+ * on failure, or a pointer to the "root data pointer" array if
+ * successful.
+ */
+void **lpsm_init(const char *main_file, const char *log_file)
+{
+ size_t arena_len = sizeof(struct arena_header); /* Minimum initial size */
+
+ if ( !lpsm_arena_init(main_file, log_file, &arena_len) )
+ return NULL; /* Failed to initialize arena */
+
+ AH = (struct arena_header *)PM->arena;
+
+ if ( memcmp(AH->arena_magic, lpsm_arena_magic, 16) != 0 ) {
+ if ( memcmp(AH->arena_magic, lpsm_arena_zero, 16) == 0 ) {
+ size_t total_size, bitmap_size;
+ int i, header_pad;
+
+ memset(AH, 0, sizeof(*AH)); /* Just in case */
+
+ /* Uninitialized arena */
+ memcpy(AH->arena_magic, lpsm_arena_magic, 16);
+ AH->arena_byteorder = 0x12345678;
+ AH->arena_bytesize = CHAR_BIT;
+ AH->arena_ptrsize = sizeof(void *);
+ AH->arena_base = (void *)AH;
+ AH->buddy_order_min = BUDDY_ORDER_MIN;
+
+ /* Header size must be padded to a multiple of BUDDY_SIZE_MIN
+ as well as the hardware page size; this better be a power of 2! */
+ header_pad = (PM->pagesize > BUDDY_SIZE_MIN)
+ ? PM->pagesize : BUDDY_SIZE_MIN;
+ assert((header_pad & (header_pad-1)) == 0);
+ AH->header_size = (sizeof(struct arena_header) + header_pad - 1)
+ & ~(header_pad-1);
+
+ AH->data_start = (char *)AH + AH->header_size;
+ AH->arena_size_lg2 = ARENA_START_SIZE_LG2;
+ bitmap_size = 1UL << (ARENA_START_SIZE_LG2-BUDDY_ORDER_MIN-1);
+ total_size = AH->header_size + ARENA_START_SIZE + (bitmap_size << 1);
+ AH->free_bitmap = (char *)AH->data_start + ARENA_START_SIZE;
+ AH->alloc_bitmap = (char *)AH->free_bitmap + bitmap_size;
+
+ if ( lpsm_extend(total_size) < 0 )
+ return NULL; /* Failed to establish initial arena */
+
+ /* Compute SLAB definitions */
+ for ( i = 0 ; slabsizes[i] ; i++ ) {
+ int header_size = sizeof(struct slab_header);
+ int bytes = BUDDY_SIZE_MIN - header_size;
+ int size = slabsizes[i];
+ int count = bytes/size;
+ int data_offset;
+
+ while ( 1 ) {
+ /* Compute header+bitmap size in bytes; rounded up to MINIMUM_ALIGN */
+ data_offset = header_size + ((count+7) >> 3);
+ data_offset = ((data_offset+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
+ if ( data_offset+count*size <= BUDDY_SIZE_MIN )
+ break;
+
+ count--;
+ }
+ AH->slab[i].size = size;
+ AH->slab[i].count = count;
+ AH->slab[i].data_offset = data_offset;
+ }
+
+ /* The bitmasks contains zeroes already; set the free bit on the topmost order. */
+ set_bit(AH->free_bitmap, 1);
+ }
+ }
+
+ if ( memcmp(AH->arena_magic, lpsm_arena_magic, 16) != 0 ||
+ AH->arena_byteorder != 0x12345678 ||
+ AH->arena_bytesize != CHAR_BIT ||
+ AH->arena_ptrsize != sizeof(void *) ||
+ AH->arena_base != (void *)AH ||
+ AH->buddy_order_min != BUDDY_ORDER_MIN ) {
+ return NULL; /* Incompatible or corrupt arena */
+ }
+
+ return AH->root_data_ptrs;
+}