diff options
author | H. Peter Anvin <hpa@zytor.com> | 2001-10-13 08:14:32 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2001-10-13 08:14:32 +0000 |
commit | d3d34ebb008dac8842f4903fdedf5a04588fada7 (patch) | |
tree | 0da21763855c1e807996a69c9da7929ab665ee93 | |
parent | d20f1d7701fae2cf2f0c4ae7720fea6bd302d415 (diff) | |
download | lpsm-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-- | Makefile | 13 | ||||
-rw-r--r-- | alloc.c | 468 | ||||
-rw-r--r-- | lpsm.h | 5 | ||||
-rw-r--r-- | testalloc.c | 56 | ||||
-rw-r--r-- | testbuddy.c | 113 |
5 files changed, 578 insertions, 77 deletions
@@ -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 $@ $< @@ -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); +} @@ -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; +} |