aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-13 08:14:32 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-13 08:14:32 +0000
commitd3d34ebb008dac8842f4903fdedf5a04588fada7 (patch)
tree0da21763855c1e807996a69c9da7929ab665ee93
parentd20f1d7701fae2cf2f0c4ae7720fea6bd302d415 (diff)
downloadlpsm-d3d34ebb008dac8842f4903fdedf5a04588fada7.tar.gz
lpsm-d3d34ebb008dac8842f4903fdedf5a04588fada7.tar.xz
lpsm-d3d34ebb008dac8842f4903fdedf5a04588fada7.zip
Mostly working allocator (slab and buddy), although extension of the
arena currently doesn't work. No deallocator yet, though.
-rw-r--r--Makefile13
-rw-r--r--alloc.c468
-rw-r--r--lpsm.h5
-rw-r--r--testalloc.c56
-rw-r--r--testbuddy.c113
5 files changed, 578 insertions, 77 deletions
diff --git a/Makefile b/Makefile
index a44be9f..35dcc87 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,13 @@
-TEST = teststore test_mmap ftrunctest
+TEST = teststore test_mmap ftrunctest testbuddy testalloc
SONAME = libobjstore.so.0
VERSION = 0.0.1
OBJSTORE = libobjstore.so libobjstore.a
-OSOBJ = objstore.o
+OSOBJ = objstore.o alloc.o
OSPICOBJ = $(patsubst %.o,%.pic.o,$(OSOBJ))
CC = gcc
-CFLAGS = -O2 -g
+CFLAGS = -Wall -O2 -g
PICFLAGS = $(CFLAGS) -fPIC
SOFLAGS = -shared
@@ -18,6 +18,7 @@ all: $(OBJSTORE) $(TEST)
clean:
rm -f *.o *~ core $(OBJSTORE) $(TEST)
+ rm -f libobjstore.so.*
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
@@ -38,6 +39,12 @@ libobjstore.a: $(OSOBJ)
teststore: teststore.o libobjstore.a
$(CC) $(LDFLAGS) -o $@ $< libobjstore.a
+testbuddy: testbuddy.o libobjstore.a
+ $(CC) $(LDFLAGS) -o $@ $< libobjstore.a
+
+testalloc: testalloc.o libobjstore.a
+ $(CC) $(LDFLAGS) -o $@ $< libobjstore.a
+
test_mmap: test_mmap.o
$(CC) $(LDFLAGS) -o $@ $<
diff --git a/alloc.c b/alloc.c
index 8736bed..fb05df5 100644
--- a/alloc.c
+++ b/alloc.c
@@ -1,7 +1,7 @@
#ident "$Id$"
/* ----------------------------------------------------------------------- *
*
- * Copyright 2000 H. Peter Anvin - All Rights Reserved
+ * 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 General Public License as published by
@@ -16,111 +16,431 @@
*
* Provide persistent storage versions of malloc(), realloc() and free().
*
- * This code uses a modified buddy system allocator. It's probably broken
- * if your byte size isn't at least a power of 2.
+ * 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.
*/
+#include <assert.h>
#include <stdlib.h>
#include <inttypes.h>
#include <limits.h>
+#include <stdio.h> /* For debugging printf() */
#include "objstore.h"
#include "internals.h"
-#define OBJSTORE_ARENA_MAGIC 0xd8319f45
+static const unsigned char objstore_arena_magic[16] =
+"\x4f\xd4\x5a\x16\xa0\xaf\xd5\x52\x56\xf1\x1c\x9c\x1c\xed\xcc";
+static const unsigned char objstore_arena_zero[16] =
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+#define SLAB_MAGIC 0xec2062ae
+
+struct slab_info {
+ int size; /* Size of SLAB */
+ int count; /* SLABs per page */
+ int data_offset; /* Start of data area */
+ struct slab_header *list;
+};
+
+/* This is <= 16 bytes on 32- and 64-bit architectures */
+struct slab_header {
+ uint32_t magic;
+ uint32_t free_count;
+ struct slab_header *next;
+};
-/* This is the minimal order worth allocating. This must be able
- to hold two pointers plus an integer. 2^4 = 16 bytes. */
-#define ORDER_MIN 4 /* This must be >= 1. */
+#define SLAB_INFO_COUNT 24
+
+struct arena_header {
+ unsigned char arena_magic[16];
+ uint32_t arena_byteorder;
+ uint16_t arena_bytesize;
+ uint16_t arena_ptrsize;
+ void *arena_base; /* Base of allocation */
+ void *root_data_ptr; /* Root data pointer - for the user */
+ void *bitmap_end_ptr; /* End of the allocation bitmap */
+ void *data_start; /* Beginning of data area */
+ int buddy_order_min; /* Minimum size of buddy allocation */
+ int arena_size_lg2; /* Current arena allocation size */
+ struct slab_info slab[SLAB_INFO_COUNT];
+};
+
+/* This is the minimal order before going to SLAB allocation. */
+#define BUDDY_ORDER_MIN 12
+#define BUDDY_SIZE_MIN (1U << BUDDY_ORDER_MIN)
/* This is the size of the alloc bitmask. It will usually be sparse. */
/* This is two bits per unit of the lowest order */
#define ALLOC_BITMAP_SIZE ((ARENA_LIMIT >> ORDER_MIN)*2/CHAR_BIT)
-/* This bit is set in the order marker to indicate an occupied cell. */
-#define OCCUPIED ((unsigned char)(1 << (CHAR_BIT-1)))
+/* Align allocations at least this large (2^n) to this boundary */
+#define MINIMUM_ALIGN_LG2 4
+#define MINIMUM_ALIGN (1 << MINIMUM_ALIGN_LG2)
+#define MINIMUM_ALIGN_MASK (MINIMUM_ALIGN-1)
+
+/* This is the size (2^n) allocated for a brand new arena.
+ This allocation will be sparse, so don't freak out too much! */
+#define ARENA_START_SIZE_LG2 (2*BUDDY_ORDER_MIN+2) /* 64 MB */
+#define ARENA_START_SIZE (1UL << ARENA_START_SIZE_LG2)
-/* How many address bits? */
-static const int orders = sizeof(void *) * CHAR_BIT;
+#define HEADER_SIZE BUDDY_SIZE_MIN /* Default size of the header */
+
+/* The data type to use for bitfield scanning. Typically should equal
+ the "natural" size on the machine... use autoconf for this? */
+typedef uint32_t bitscan_t;
+#define BITSCAN_SHIFT 5
+#define BITSCAN_BITS (1 << BITSCAN_SHIFT)
+#define BITSCAN_MASK (BITSCAN_BITS-1)
+#define BITSCAN_0 ((bitscan_t)0)
+#define BITSCAN_1 ((bitscan_t)1)
/*
- * Initalize the object store arena allocator. Note the argument
- * that allows a fixed-offset structure at the beginning. This is
- * essential, since otherwise we wouldn't be able to begin to
- * pick apart the object hierarchy.
+ * These should be revamped to be thread-safe at some point. That
+ * may mean doing things that are architecture-specific...
+ *
+ * Important: "bit" can be negative, and that needs to be handled
+ * correctly!
*/
-void *objstore_arena_init(size_t leadin_size)
+static inline int test_bit(const void *ptr, int bit)
{
- struct ObjStore *os = objstore_os_struct;
- void **order_list, **order_ptr;
- uintptr_t begin_data, end_data, order_size;
- int i;
-
- leadin_size = (leadin_size + os->pagesize - 1) & ~(os->pagesize - 1);
- order_list = (void **)((char *)os->arena + leadin_size);
- begin_data = (uintptr_t)(order_list + orders + 1);
- end_data = (uintptr_t)os->arena + os->arena_len;
+#if defined(__GNUC__) && defined(__i386__)
+ int rv;
+ asm("xorl %0,%0 ; btl %2,%1 ; adcl %0,%0"
+ : "=&r" (rv) : "m" (*(const bitscan_t *)ptr), "r" (bit) : "cc");
+ return rv;
+#else
+ const bitscan_t *cp;
+
+ cp = (const bitscan_t *)ptr + (bit >> BITSCAN_SHIFT);
+ return (int)((*cp >> (bit & BITSCAN_MASK)) & BITSCAN_1);
+#endif
+}
+
+static inline void set_bit(void *ptr, int bit)
+{
+#if defined(__GNUC__) && defined(__i386__)
+ asm volatile("btsl %1,%0" : "=m" (*(bitscan_t *)ptr) : "r" (bit) : "cc");
+#else
+ bitscan_t *cp;
+
+ cp = (bitscan_t *)ptr + (bit >> BITSCAN_SHIFT);
+ *cp |= (BITSCAN_1 << (bit & BITSCAN_MASK));
+#endif
+}
+
+static inline void clr_bit(void *ptr, int bit)
+{
+#if defined(__GNUC__) && defined(__i386__)
+ asm volatile("btcl %1,%0" : "=m" (*(bitscan_t *)ptr) : "r" (bit) : "cc");
+#else
+ bitscan_t *cp;
+
+ cp = (bitscan_t *)ptr + (bit >> BITSCAN_SHIFT);
+ *cp &= ~(BITSCAN_1 << (bit & BITSCAN_MASK));
+#endif
+}
+
+/* Finds a one bit somewhere between [start, start+count) bit indicies.
+ Returns the index, or "err" if no such bit is found. */
+static int find_set_bit(const void *ptr, int start, int count, int err)
+{
+ const bitscan_t *cp, *ecp;
+ bitscan_t mask, val;
+ int i, end;
+
+ end = start+count-1;
+
+ cp = (bitscan_t *)ptr + (start >> BITSCAN_SHIFT);
+
+ if ( ((start^end) & ~BITSCAN_MASK) == 0 ) {
+ /* All falls within a single bitscan_t quantum */
+ mask = BITSCAN_1 << (start & BITSCAN_MASK);
+ val = *cp;
+ for ( i = start ; i <= end ; i++ ) {
+ if ( val & mask )
+ return i;
+ mask <<= 1;
+ }
+ return err;
+ }
- if ( (uintptr_t)order_list[0] != (uintptr_t)OBJSTORE_ARENA_MAGIC ) {
- /* The arena is uninitialized. */
-
- /* Begin by initializing all the pointers to null */
- for ( i = 0 ; i < orders ; i++ )
- order_list[i] = NULL;
-
- /* Align the beginning and end to the lowest-supported order.
- Note that begin_data is adjusted +1 above, to handle the
- order/alloc marker of the first unit. */
- begin_data = (begin_data + ((uintptr_t)1 << ORDER_MIN) - 1) &
- ~(((uintptr_t)1 << ORDER_MIN) - 1);
- end_data = end_data & ~(((uintptr_t)1 << ORDER_MIN)-1);
-
- for ( i = ORDER_MIN ; i < orders ; i++ ) {
- order_size = (uintptr_t)1 << i;
- order_ptr = &order_list[i];
- if ( (begin_data & order_size) &&
- (end_data-begin_data) >= order_size ) {
- ((unsigned char *)begin_data)[-1] = i; /* Free object of order i */
- *order_ptr = (void *)begin_data;
- order_ptr = (void **)begin_data;
- *order_ptr = NULL;
- begin_data += order_size;
+ mask = ~BITSCAN_0 << (start & BITSCAN_MASK);
+ val = *cp++;
+ if ( val & mask ) {
+ end = start | BITSCAN_MASK;
+ mask = BITSCAN_1 << (start & BITSCAN_MASK);
+ for ( i = start ; i < end ; i++ ) {
+ if ( val & mask )
+ return i;
+ mask <<= 1;
+ }
+ assert(0); /* Internal error */
+ }
+
+ ecp = (bitscan_t *)ptr + (end >> BITSCAN_SHIFT);
+ start = (start & ~BITSCAN_MASK) + BITSCAN_BITS;
+
+ while ( cp < ecp ) {
+ val = *cp++;
+ if ( val ) {
+ mask = BITSCAN_1;
+ end = start | BITSCAN_MASK;
+ for ( i = start ; i < end ; i++ ) {
+ if ( val & mask )
+ return i;
+ mask <<= 1;
}
- if ( (end_data & order_size) &&
- (end_data-begin_data) >= order_size ) {
- end_data -= order_size;
- ((unsigned char *)begin_data)[-1] = i; /* Free object of order i */
- *order_ptr = (void *)end_data;
- order_ptr = (void **)end_data;
- *order_ptr = NULL;
+ assert(0); /* Internal error */
+ }
+ start += BITSCAN_BITS;
+ }
+
+ /* Scan final word */
+ val = *cp;
+ mask = BITSCAN_1;
+ for ( i = start ; i <= end ; i++ ) {
+ if ( val & mask )
+ return i;
+ mask <<= 1;
+ }
+ return err; /* Nothing found */
+}
+
+static struct ObjStore *os;
+static struct arena_header *ah;
+
+/*
+ * Initalize the object store arena allocator.
+ */
+void *objstore_arena_init(void)
+{
+ os = objstore_os_struct;
+ ah = (struct arena_header *)os->arena;
+
+ if ( memcmp(ah->arena_magic, objstore_arena_magic, 16) != 0 ) {
+ if ( memcmp(ah->arena_magic, objstore_arena_zero, 16) == 0 ) {
+ size_t total_size;
+ int i;
+
+ /* Uninitialized arena */
+ memcpy(ah->arena_magic, objstore_arena_magic, 16);
+ ah->arena_byteorder = 0x12345678;
+ ah->arena_bytesize = CHAR_BIT;
+ ah->arena_ptrsize = sizeof(void *);
+ ah->arena_base = (void *)ah;
+ ah->data_start = (char *)ah + HEADER_SIZE;
+ ah->buddy_order_min = BUDDY_ORDER_MIN;
+
+ ah->arena_size_lg2 = ARENA_START_SIZE_LG2;
+ total_size = HEADER_SIZE + ARENA_START_SIZE +
+ (1UL << (ARENA_START_SIZE_LG2-BUDDY_ORDER_MIN-2));
+ ah->bitmap_end_ptr = (char *)ah + total_size;
+
+ if ( objstore_extend(total_size) < 0 )
+ return NULL; /* Failed to establish initial arena */
+
+ /* Change these if BUDDY_ORDER_MIN or MINIMUM_ALIGN is changed */
+ /* These MUST be ordered in order of decreasing size */
+ ah->slab[0].size = 2032;
+ ah->slab[1].size = 1008;
+ ah->slab[2].size = 496;
+ ah->slab[3].size = 240;
+ ah->slab[4].size = 112;
+ ah->slab[5].size = 48;
+ ah->slab[6].size = 32;
+ ah->slab[7].size = 16;
+ ah->slab[8].size = 8;
+ ah->slab[9].size = 4;
+ ah->slab[10].size = 2;
+ ah->slab[11].size = 1;
+
+ for ( i = 0 ; i <= 11 ; i++ ) {
+ int header_size =
+ ((sizeof(struct slab_header)+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
+ int bytes = BUDDY_SIZE_MIN - header_size;
+ int size = ah->slab[i].size;
+ int count = bytes/size;
+ int bitmap_size;
+
+ while ( 1 ) {
+ /* Compute bitmap size in bytes; rounded up to MINIMUM_ALIGN */
+ bitmap_size = (count+7) >> 3;
+ bitmap_size = (bitmap_size+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK;
+
+ if ( bitmap_size+count*size <= bytes )
+ break;
+
+ count--;
+ }
+
+ ah->slab[i].count = count;
+ ah->slab[i].data_offset = header_size + bitmap_size;
}
+
+ /* The buddy itmask contains zeroes already; set the bit on the topmost order. */
+ set_bit(ah->bitmap_end_ptr, -1);
}
-
- /* Arena now initialized */
- order_list[0] = (void *)(uintptr_t)OBJSTORE_ARENA_MAGIC;
}
+
+ if ( memcmp(ah->arena_magic, objstore_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->data_start;
}
-void *objstore_malloc(size_t size)
+static int objstore_find_free_chunk(int rorder)
{
- int order_needed, order, i;
+ int rs, obit, xbit;
+
+ rs = 1 << rorder;
+ obit = 1-(rs+rs);
+
+ xbit = find_set_bit(ah->bitmap_end_ptr, obit, rs, 0);
+
+ if ( !xbit ) {
+ if ( rorder == 0 )
+ return 0; /* We're out */
+ xbit = objstore_find_free_chunk(rorder-1);
+ if ( !xbit )
+ return 0; /* All out of those, sir */
+ printf("buddy: splitting rorder %2d %8d -> %d %d\n", rorder-1, xbit, (xbit << 1)-1, (xbit << 1));
+ xbit <<= 1; /* Convert to address of fragments */
+ set_bit(ah->bitmap_end_ptr, xbit); /* Upper buddy is available */
+ xbit--; /* Return the lower buddy */
+ } else {
+ clr_bit(ah->bitmap_end_ptr, xbit); /* No longer available */
+ }
+ printf("buddy: allocated rorder %2d %8d\n", rorder, xbit);
+ return xbit;
+}
+
+static void *objstore_malloc_buddy(size_t size)
+{
+ int order = BUDDY_ORDER_MIN;
+ int rorder;
+ int xbit, obit;
+ void *p;
+
+ while ( size > (1UL << order) )
+ order++;
+
+ /* Now we know the order */
+ if ( order > ah->arena_size_lg2 ) {
+ /* Need to extend immediately */
+ return NULL; /* Not implemented yet */
+ }
+
+ /* Convert to order relative to the arena size order */
+ rorder = ah->arena_size_lg2 - order;
+ obit = 1-(2 << rorder);
+
+ printf("buddy: trying to allocate %d bytes, rorder = %d\n", size, rorder);
+
+ xbit = objstore_find_free_chunk(rorder);
+ if ( !xbit ) {
+ /* Need to extend */
+ return NULL; /* Not implemented yet */
+ }
+
+ p = (void *)((char *)ah->data_start +
+ ((uintptr_t)(xbit-obit) << order));
+
+ printf("buddy: allocated %u/%u bytes at %p\n", size, 1U << order, p);
+ return p;
+}
+
+static struct slab_header *objstore_make_new_slab(struct slab_info *si)
+{
+ struct slab_header *sh;
+ unsigned char *slab_bitmap;
+ int bitmap_all_set_bytes = si->count >> 3;
+ int bitmap_bits_left = si->count & 7;
+
+ /* Get a page from the buddy system allocator */
+ sh = objstore_malloc_buddy(BUDDY_SIZE_MIN);
+ if ( !sh )
+ return NULL;
+
+ printf("slab: allocating new page for size %d at %p\n", si->size, sh);
+
+ sh->magic = SLAB_MAGIC;
+ sh->free_count = si->count;
+ sh->next = si->list;
+
+ slab_bitmap = (unsigned char *)sh +
+ ((sizeof(struct slab_header)+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
- size += 1; /* Add 1 for bookkeeping byte */
+ /* Mark all SLABs as available */
+ memset(slab_bitmap, ~0, bitmap_all_set_bytes);
+ slab_bitmap[bitmap_all_set_bytes] = (1 << bitmap_bits_left)-1;
+
+ return (si->list = sh);
+}
+
+static void *objstore_malloc_slab(size_t size)
+{
+ int i;
+ int which;
+ struct slab_info *si;
+ struct slab_header *sh;
+ void *slab_bitmap;
+ void *p;
- /* Find the order needed */
- for ( order_needed = ORDER_MIN ;
- (size_t)(1UL << order_needed) < size ;
- order_needed++ );
+ /* POSIX sayeth: thou shalt return unique addresses for malloc(0); */
+ if ( size == 0 ) size = 1;
- /* Find the order available */
- for ( order = order_needed ; order < orders ; order++ ) {
- if ( order_list[order] )
+ si = &ah->slab[0];
+ for ( i = 1 ; i < SLAB_INFO_COUNT ; i++ ) {
+ if ( size <= si[1].size )
+ si++;
+ else
break;
}
- if ( order >= orders )
- return NULL; /* Nothing available */
+ /* Now si points to the slab_info header we want to allocate from */
+
+ printf("slab: trying to allocate %d bytes, slab size %d bytes\n",
+ size, si->size);
- /* Split orders down to the needed one */
- for ( i = order ; i < order_needed ; i++ ) {
-
+ sh = si->list;
+ if ( !sh ) {
+ /* Empty free list, need a new page */
+ if ( !(sh = objstore_make_new_slab(si)) )
+ return NULL; /* Unavailable to allocate new slab */
+ }
+
+ slab_bitmap = (char *)sh +
+ ((sizeof(struct slab_header)+MINIMUM_ALIGN-1) & ~MINIMUM_ALIGN_MASK);
+
+ which = find_set_bit(slab_bitmap, 0, si->count, -1);
+ assert(which >= 0); /* Otherwise something is bad... */
+
+ clr_bit(slab_bitmap, which); /* No longer available */
+
+ if ( --(sh->free_count) == 0 ) {
+ /* We just allocated the last slab, take off the free list */
+ si->list = sh->next;
+ }
+
+ p = (void *)((char *)sh + si->data_offset + which*si->size);
+ printf("slab: allocated %d/%d bytes at %p, %d slabs left\n",
+ size, si->size, p, sh->free_count);
+ return p;
+}
+
+void *objstore_malloc(size_t size)
+{
+ if ( size > ah->slab[0].size )
+ return objstore_malloc_buddy(size);
+ else
+ return objstore_malloc_slab(size);
+}
diff --git a/lpsm.h b/lpsm.h
index b014b20..e1761a6 100644
--- a/lpsm.h
+++ b/lpsm.h
@@ -26,8 +26,13 @@
struct Objstore;
+/* Core routines */
void *objstore_init(char *main_file, char *log_file, size_t *arena_len);
int objstore_checkpoint(double gc_factor);
int objstore_extend(size_t new_size);
+/* Alloc routines */
+void *objstore_arena_init(void);
+void *objstore_malloc(size_t size);
+
#endif
diff --git a/testalloc.c b/testalloc.c
new file mode 100644
index 0000000..455aac7
--- /dev/null
+++ b/testalloc.c
@@ -0,0 +1,56 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 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 General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+#include <limits.h>
+#include "objstore.h"
+
+#define COUNT 8192
+#define MAXLOG 26
+
+int main(int argc, char *argv[])
+{
+ void *areas[COUNT];
+ int sizes[COUNT];
+ void *buf;
+ int arena_len = 16384;
+ int i;
+ double rnd;
+
+ unlink("arena.dat");
+ unlink("arena.log");
+
+ buf = objstore_init("arena.dat", "arena.log", &arena_len);
+ if ( !objstore_arena_init() ) {
+ fprintf(stderr, "%s: objstore_arena_init() failed\n", argv[0]);
+ return 1;
+ }
+
+ objstore_checkpoint(0.0);
+
+ for ( i = 0 ; i < COUNT ; i++ ) {
+ rnd = (double)rand()/RAND_MAX;
+ sizes[i] = (int)pow(2.0, MAXLOG*rnd);
+ areas[i] = objstore_malloc(sizes[i]);
+ printf("Alloc: %8d (0x%08x) bytes at %p\n",
+ sizes[i], sizes[i], areas[i]);
+ }
+
+ objstore_checkpoint(0.0);
+
+ return 0;
+}
diff --git a/testbuddy.c b/testbuddy.c
new file mode 100644
index 0000000..00375b6
--- /dev/null
+++ b/testbuddy.c
@@ -0,0 +1,113 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2000 Transmeta Corporation - All Rights Reserved
+ *
+ * This source module contains confidential and proprietary information
+ * of Transmeta Corporation. It is not to be disclosed or used except
+ * in accordance with applicable agreements. This copyright notice does
+ * not evidence any actual or intended publication of such source code.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "objstore.h"
+
+static int testsizes[] = {
+ 265299,
+ 336285,
+ 53234,
+ 44195236,
+ 23108,
+ 360124,
+ 796226,
+ 1311075,
+ 7330,
+ 597660,
+ 6006,
+ 83645,
+ 4324,
+ 2820112,
+ 5911,
+ 461569,
+ 1163094,
+ 247678,
+ 18184,
+ 48348,
+ 2901068,
+ 52441197,
+ 4541251,
+ 2353734,
+ 384583,
+ 1421658,
+ 326213,
+ 7422104,
+ 13100,
+ 21201063,
+ 1159271,
+ 848463,
+ 106239,
+ 15066610,
+ 558764,
+ 599357,
+ 80851,
+ 6630,
+ 11709,
+ 144683,
+ 967341,
+ 17170,
+ 2954603,
+ 1021175,
+ 11821390,
+ 4263889,
+ 7024,
+ 204882,
+ 15737,
+ 31181,
+ 2418369,
+ 11145790,
+ 24366,
+ 163651,
+ 390920,
+ 2287775,
+ 56800676,
+ 31133580,
+ 253023,
+ 11087,
+ 9835735,
+ 4371,
+ 2296700,
+ 15571,
+};
+
+int main(int argc, char *argv[])
+{
+ void *areas[64];
+ void *buf;
+ int arena_len = 16384;
+ int i;
+
+ unlink("arena.dat");
+ unlink("arena.log");
+
+ buf = objstore_init("arena.dat", "arena.log", &arena_len);
+ if ( !objstore_arena_init() ) {
+ fprintf(stderr, "%s: objstore_arena_init() failed\n", argv[0]);
+ return 1;
+ }
+
+ objstore_checkpoint(0.0);
+
+ for ( i = 0 ; i < 64 ; i++ ) {
+ areas[i] = objstore_malloc(testsizes[i]);
+ printf("Alloc: %8d (0x%08x) bytes at %p\n",
+ testsizes[i], testsizes[i], areas[i]);
+ }
+
+ objstore_checkpoint(0.0);
+
+ return 0;
+}