From: Pekka Riikonen Date: Tue, 3 Jul 2007 19:47:12 +0000 (+0000) Subject: Added concept of child stacks to SilcStack. Supports now full X-Git-Tag: 1.2.beta1~214 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=3d836f704311455db019d48b0666bb11a52a5a88;p=runtime.git Added concept of child stacks to SilcStack. Supports now full memory pool system. --- diff --git a/lib/silcutil/silcstack.c b/lib/silcutil/silcstack.c index 85575e51..7f179eb4 100644 --- a/lib/silcutil/silcstack.c +++ b/lib/silcutil/silcstack.c @@ -17,46 +17,228 @@ */ -/* #define SILC_STACK_DEBUG 1 */ - #include "silc.h" -/* Allocate the stack */ +/************************** Types and definitions ***************************/ + +/* The SilcStack context */ +struct SilcStackStruct { + SilcStack parent; /* Parent stack */ + SilcList stacks; /* List of stacks */ + SilcStackDataEntry stack; /* Allocated stack blocks */ + SilcStackFrame *frames; /* Allocated stack frames */ + SilcStackFrame *frame; /* Current stack frame */ + SilcUInt32 stack_size; /* Default stack size */ + SilcUInt32 alignment; /* Memory alignment */ +#ifdef SILC_DIST_INPLACE + /* Statistics */ + SilcUInt32 snum_malloc; + SilcUInt32 sbytes_malloc; + SilcUInt32 snum_errors; +#endif /* SILC_DIST_INPLACE */ +}; + +/************************ Static utility functions **************************/ + +/* Compute stack block index for the `size'. */ -SilcStack silc_stack_alloc(SilcUInt32 stack_size) +static SilcUInt32 silc_stack_get_index(SilcUInt32 size, SilcUInt32 *ret_bsize) { - SilcStack stack; + SilcUInt32 bsize, si; - stack = silc_calloc(1, sizeof(*stack)); - if (!stack) - return NULL; + if (size < SILC_STACK_DEFAULT_SIZE) + size = SILC_STACK_DEFAULT_SIZE; + si = 0; + bsize = SILC_STACK_DEFAULT_SIZE; + while (bsize < size) { + bsize <<= 1; + si++; + } - stack->frames = silc_calloc(SILC_STACK_DEFAULT_NUM, - sizeof(*stack->frames)); - if (!stack->frames) { - silc_free(stack); - return NULL; + *ret_bsize = bsize; + + return si; +} + +/* Get stack from `stack' or allocate new one. */ + +static SilcStackDataEntry silc_stack_ref_stack(SilcStack stack, + SilcUInt32 size, + SilcUInt32 *ret_si, + SilcUInt32 *ret_bsize) +{ + SilcStackDataEntry e; + SilcUInt32 si, bsize; + + /* Get stack block index and block size for requested size */ + si = silc_stack_get_index(size, &bsize); + *ret_si = si; + *ret_bsize = bsize; + + SILC_ST_DEBUG(("Get stack block, si %d, size %lu", si, bsize)); + + /* Get stack that has block that can house our size requirement. */ + silc_list_start(stack->stacks); + while ((e = silc_list_get(stack->stacks))) { + if (!e->data[si]) + continue; + + silc_list_del(stack->stacks, e); + SILC_ST_DEBUG(("Got stack blocks %p from stack %p", e->data, stack)); + return e; } - stack->alignment = SILC_STACK_DEFAULT_ALIGN; - - /* Create initial stack */ - stack->stack_size = stack_size ? stack_size : SILC_STACK_DEFAULT_SIZE; - stack->stack[0] = silc_malloc(stack->stack_size + - SILC_STACK_ALIGN(sizeof(*stack->stack[0]), - stack->alignment)); - if (!stack->stack[0]) { - silc_free(stack->frames); - silc_free(stack); + + SILC_ST_DEBUG(("Allocate new stack blocks")); + + /* Allocate new stack blocks */ + e = silc_calloc(1, sizeof(*e)); + if (!e) + return NULL; + e->data[si] = silc_malloc(bsize + SILC_STACK_ALIGN(sizeof(*e->data[0]), + stack->alignment)); + if (!e->data[si]) { + silc_free(e); return NULL; } - stack->stack[0]->bytes_left = stack->stack_size; + e->data[si]->bytes_left = bsize; + e->si = si; + e->bsize = bsize; + + SILC_ST_DEBUG(("Got stack blocks %p from stack %p", e->data, stack)); + return e; +} + +/* Return the `data' back to the `stack'. */ + +static void silc_stack_unref_stack(SilcStack stack, SilcStackDataEntry e) +{ + int i; + + SILC_LOG_DEBUG(("Release stack blocks %p to stack %p, si %d", + e->data, stack, e->si)); + + /* Release all blocks from allocations */ + for (i = e->si; i < SILC_STACK_BLOCK_NUM; i++) { + if (!e->data[i]) + continue; + if (!i) + e->data[i]->bytes_left = e->bsize; + else + e->data[i]->bytes_left = SILC_STACK_BLOCK_SIZE(stack, i); + } + + silc_list_add(stack->stacks, e); +} + +/* Allocate memory from a specific stack block */ + +static void *silc_stack_alloc_block(SilcStack stack, SilcStackDataEntry e, + SilcUInt32 items, SilcUInt32 size) +{ + SilcUInt32 asize; + void *ptr; + + /* Get pointer and consume the stack block */ + asize = SILC_STACK_ALIGN(items * size, stack->alignment); + ptr = SILC_STACK_DATA_EXT(e->data, e->si, e->bsize, stack->alignment); + e->data[e->si]->bytes_left -= asize; + memset(ptr, 0, items * size); + + return ptr; +} + +/***************************** SilcStack API ********************************/ + +/* Allocate the stack */ + +SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent) +{ + SilcStack stack; + SilcStackDataEntry e; + SilcUInt32 si = 0, bsize = 0; + + stack_size = stack_size ? stack_size : SILC_STACK_DEFAULT_SIZE; + if (stack_size < SILC_STACK_DEFAULT_SIZE) + stack_size = SILC_STACK_DEFAULT_SIZE; + + if (parent) { + /* Get stack from parent. The stack itself is allocated from the + parent. */ + e = silc_stack_ref_stack(parent, stack_size, &si, &bsize); + if (!e) + return NULL; + + /* Allocate stack from the parent */ + stack = silc_stack_alloc_block(parent, e, 1, sizeof(*stack)); + if (!stack) { + silc_stack_unref_stack(parent, e); + return NULL; + } + + stack->parent = parent; + stack->stack_size = stack_size; + stack->alignment = SILC_STACK_DEFAULT_ALIGN; + silc_list_init(stack->stacks, struct SilcStackDataEntryStruct, next); + + /* Allocate stack frames from the parent */ + stack->frames = silc_stack_alloc_block(parent, e, SILC_STACK_BLOCK_NUM, + sizeof(*stack->frames)); + if (!stack->frames) { + silc_stack_unref_stack(parent, e); + return NULL; + } + + /* Set the initial stack */ + stack->stack = e; + } else { + /* Dynamically allocate new stack */ + stack = silc_calloc(1, sizeof(*stack)); + if (!stack) + return NULL; + + stack->stack_size = stack_size; + stack->alignment = SILC_STACK_DEFAULT_ALIGN; + silc_list_init(stack->stacks, struct SilcStackDataEntryStruct, next); + + /* Create initial stack */ + stack->stack = silc_calloc(1, sizeof(*stack->stack)); + if (!stack->stack) { + silc_free(stack); + return NULL; + } + stack->stack->data[0] = + silc_malloc(stack->stack_size + + SILC_STACK_ALIGN(sizeof(*stack->stack->data[0]), + stack->alignment)); + if (!stack->stack->data[0]) { + silc_free(stack->stack); + silc_free(stack); + return NULL; + } + stack->stack->data[0]->bytes_left = stack->stack_size; + stack->stack->si = 0; + stack->stack->bsize = stack->stack_size; + + /* Allocate stack frames from the stack itself */ + stack->frames = silc_stack_alloc_block(stack, stack->stack, + SILC_STACK_DEFAULT_NUM, + sizeof(*stack->frames)); + if (!stack->frames) { + silc_free(stack->stack->data[0]); + silc_free(stack->stack); + silc_free(stack); + return NULL; + } + } /* Use the allocated stack in first stack frame */ stack->frame = &stack->frames[0]; stack->frame->prev = NULL; stack->frame->bytes_used = stack->stack_size; stack->frame->sp = 1; - stack->frame->si = 0; + stack->frame->si = si; + + SILC_LOG_DEBUG(("New stack %p, size %d bytes", stack, stack->stack_size)); return stack; } @@ -65,12 +247,31 @@ SilcStack silc_stack_alloc(SilcUInt32 stack_size) void silc_stack_free(SilcStack stack) { + SilcStackDataEntry e; int i; - silc_free(stack->frames); - for (i = 0; i < SILC_STACK_BLOCK_NUM; i++) - silc_free(stack->stack[i]); - silc_free(stack); + SILC_LOG_DEBUG(("Free stack %p", stack)); + + if (!stack->parent) { + silc_list_start(stack->stacks); + while ((e = silc_list_get(stack->stacks))) { + for (i = 0; i < SILC_STACK_BLOCK_NUM; i++) + silc_free(e->data[i]); + silc_free(e); + } + + for (i = 0; i < SILC_STACK_BLOCK_NUM; i++) + silc_free(stack->stack->data[i]); + silc_free(stack->stack); + + silc_free(stack); + } else { + silc_list_start(stack->stacks); + while ((e = silc_list_get(stack->stacks))) + silc_stack_unref_stack(stack->parent, e); + + silc_stack_unref_stack(stack->parent, stack->stack); + } } /* Push to next stack frame */ @@ -81,23 +282,11 @@ SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame) return 0; if (!frame) { - /* See if all frames are in use, and allocate SILC_STACK_DEFAULT_NUM - many new frames if needed. */ if (stack->frame->sp >= SILC_STACK_ALIGN(stack->frame->sp, SILC_STACK_DEFAULT_NUM)) { - int i = stack->frame->sp; - SILC_LOG_DEBUG(("Allocating more stack frames")); - frame = silc_realloc(stack->frames, - SILC_STACK_ALIGN(i + 1, SILC_STACK_DEFAULT_NUM) * - sizeof(*stack->frames)); - if (!frame) - return 0; - stack->frames = frame; - stack->frame = &stack->frames[i - 1]; - - /* The prev pointers may become invalid in silc_realloc() */ - for (i = 1; i < stack->frame->sp; i++) - stack->frames[i].prev = &stack->frames[i - 1]; + SILC_LOG_DEBUG(("SilcStack %p running out of frames, cannot push", + stack)); + return stack->frame->sp; } frame = &stack->frames[stack->frame->sp]; @@ -107,7 +296,7 @@ SilcUInt32 silc_stack_push(SilcStack stack, SilcStackFrame *frame) frame->prev = stack->frame; frame->sp = stack->frame->sp + 1; frame->si = stack->frame->si; - frame->bytes_used = stack->stack[frame->si]->bytes_left; + frame->bytes_used = stack->stack->data[frame->si]->bytes_left; stack->frame = frame; SILC_ST_DEBUG(("Push %p: sp %d -> %d, si %d", stack, frame->prev->sp, @@ -122,18 +311,17 @@ SilcUInt32 silc_stack_pop(SilcStack stack) { SilcUInt32 si; - if (!stack) + if (!stack || !stack->frame->prev) return 0; /* Pop */ - assert(stack->frame->prev); si = stack->frame->si; while (si > stack->frame->prev->si) { - if (stack->stack[si]) - stack->stack[si]->bytes_left = SILC_STACK_BLOCK_SIZE(stack, si); + if (stack->stack->data[si]) + stack->stack->data[si]->bytes_left = SILC_STACK_BLOCK_SIZE(stack, si); si--; } - stack->stack[si]->bytes_left = stack->frame->bytes_used; + stack->stack->data[si]->bytes_left = stack->frame->bytes_used; stack->frame = stack->frame->prev; SILC_ST_DEBUG(("Pop %p: sp %d -> %d, si %d", stack, stack->frame->sp + 1, @@ -172,10 +360,10 @@ void *silc_stack_malloc(SilcStack stack, SilcUInt32 size) bsize = SILC_STACK_BLOCK_SIZE(stack, si); /* See if there is space in the current stack block */ - if (stack->stack[si]->bytes_left >= size) { + if (stack->stack->data[si]->bytes_left >= size) { /* Get pointer to the memory */ ptr = SILC_STACK_DATA(stack, si, bsize); - stack->stack[si]->bytes_left -= size; + stack->stack->data[si]->bytes_left -= size; SILC_STACK_STAT(stack, bytes_malloc, size); return ptr; } @@ -198,23 +386,24 @@ void *silc_stack_malloc(SilcStack stack, SilcUInt32 size) } /* Allocate the block if it doesn't exist yet */ - if (!stack->stack[si]) { + if (!stack->stack->data[si]) { SILC_ST_DEBUG(("Allocating new stack block, %d bytes", bsize2)); - stack->stack[si] = silc_malloc(bsize2 + - SILC_STACK_ALIGN(sizeof(**stack->stack), - stack->alignment)); - if (silc_unlikely(!stack->stack[si])) { + stack->stack->data[si] = + silc_malloc(bsize2 + + SILC_STACK_ALIGN(sizeof(**stack->stack->data), + stack->alignment)); + if (silc_unlikely(!stack->stack->data[si])) { SILC_STACK_STAT(stack, num_errors, 1); return NULL; } - stack->stack[si]->bytes_left = bsize2; + stack->stack->data[si]->bytes_left = bsize2; } /* Now return memory from this new block. It is guaranteed that in this block there is enough space for this memory. */ - assert(stack->stack[si]->bytes_left >= size); + assert(stack->stack->data[si]->bytes_left >= size); ptr = SILC_STACK_DATA(stack, si, bsize2); - stack->stack[si]->bytes_left -= size; + stack->stack->data[si]->bytes_left -= size; stack->frame->si = si; SILC_STACK_STAT(stack, bytes_malloc, size); @@ -260,9 +449,9 @@ void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size, bsize = SILC_STACK_BLOCK_SIZE(stack, si); /* Check that `ptr' is last allocation */ - sptr = (unsigned char *)stack->stack[si] + - SILC_STACK_ALIGN(sizeof(**stack->stack), stack->alignment); - if (stack->stack[si]->bytes_left + old_size + + sptr = (unsigned char *)stack->stack->data[si] + + SILC_STACK_ALIGN(sizeof(**stack->stack->data), stack->alignment); + if (stack->stack->data[si]->bytes_left + old_size + ((unsigned char *)ptr - (unsigned char *)sptr) != bsize) { SILC_LOG_DEBUG(("Cannot reallocate")); SILC_STACK_STAT(stack, num_errors, 1); @@ -270,10 +459,10 @@ void *silc_stack_realloc(SilcStack stack, SilcUInt32 old_size, } /* Now check that the new size fits to this block */ - if (stack->stack[si]->bytes_left >= size) { + if (stack->stack->data[si]->bytes_left >= size) { /* It fits, so simply return the old pointer */ size = SILC_STACK_ALIGN(size, stack->alignment); - stack->stack[si]->bytes_left -= (size - old_size); + stack->stack->data[si]->bytes_left -= (size - old_size); SILC_STACK_STAT(stack, bytes_malloc, (size - old_size)); return ptr; } @@ -303,11 +492,12 @@ SilcUInt32 silc_stack_get_alignment(SilcStack stack) void silc_stack_stats(SilcStack stack) { + SilcStackDataEntry e; SilcUInt32 stack_size = 0; int i, c = 0; for (i = 0; i < SILC_STACK_BLOCK_NUM; i++) { - if (!stack->stack[i]) + if (!stack->stack->data[i]) continue; stack_size += SILC_STACK_BLOCK_SIZE(stack, i); c++; @@ -330,5 +520,22 @@ void silc_stack_stats(SilcStack stack) (unsigned int)SILC_STACK_ALIGN(stack->frame->sp, SILC_STACK_DEFAULT_NUM)); fprintf(stdout, " Number of blocks : %u\n", c); + fprintf(stdout, " Number of stacks : %d\n", + silc_list_count(stack->stacks)); + + silc_list_start(stack->stacks); + while ((e = silc_list_get(stack->stacks))) { + stack_size = 0; + c = 0; + for (i = 0; i < SILC_STACK_BLOCK_NUM; i++) { + if (!e->data[i]) + continue; + stack_size += e->data[i]->bytes_left; + c++; + } + fprintf(stdout, "\n Size of stack : %u\n", + (unsigned int)stack_size); + fprintf(stdout, " Number of blocks : %u\n", c); + } } #endif /* SILC_DIST_INPLACE */ diff --git a/lib/silcutil/silcstack.h b/lib/silcutil/silcstack.h index 46a00a2f..8003666f 100644 --- a/lib/silcutil/silcstack.h +++ b/lib/silcutil/silcstack.h @@ -36,6 +36,12 @@ * the stack. This allows the caller to use special alignment for memory * allocations, if needed. * + * SilcStack is also a full featured memory pool which allows user to group + * together multiple stacks. Child stacks may be created from a parent stack + * without consuming the parent stack. When the child is freed, its memory + * is returned back to the parent and can be used again by other childs. + * It is also possible to create child stacks from another child stack. + * * A basic set of utility functions are provided for application that wish * to use the SilcStack as their primary memory allocation source. The * following functions support SilcStack: @@ -44,7 +50,8 @@ * silc_sfree, silc_sstrdup, silc_buffer_salloc, silc_buffer_salloc_size, * silc_buffer_srealloc, silc_buffer_srealloc_size, silc_buffer_scopy, * silc_buffer_sclone, silc_buffer_sformat, silc_buffer_sformat_vp, - * silc_buffer_sstrformat, silc_buffer_senlarge, silc_mp_sinit + * silc_buffer_sstrformat, silc_buffer_senlarge, silc_mp_sinit, + * silc_dlist_sinit, silc_hash_table_alloc * * The SilcStack context is not thread-safe. If the same SilcStack must be * used in multithreaded environment concurrency control must be employed. @@ -81,13 +88,10 @@ typedef struct SilcStackStruct *SilcStack; * * Static stack frame context that optionally can be used as stack * frame in SilcStack. By default silc_stack_push use pre-allocated - * stack frame (or allocates new one if all frames are reserved), but - * user may also use statically allocated SilcStackFrame instead. This - * is recommended when using SilcStack in recursive routine and the - * recursion may become deep. Using static frame assures that during - * recursion frames never run out and silc_stack_push never allocates - * any memory. In other normal usage statically allocated SilcStackFrame - * is not needed, unless performance is critical. + * stack frame, but user may also use statically allocated SilcStackFrame + * instead. This is recommended when using SilcStack in recursive routine + * and the recursion may become deep. Using static frame assures that + * during recursion frames never run out. * ***/ typedef struct SilcStackFrameStruct SilcStackFrame; @@ -96,7 +100,7 @@ typedef struct SilcStackFrameStruct SilcStackFrame; * * SYNOPSIS * - * SilcStack silc_stack_alloc(SilcUInt32 stack_size); + * SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent); * * DESCRIPTION * @@ -104,11 +108,19 @@ typedef struct SilcStackFrameStruct SilcStackFrame; * allocation by various routines. Returns the pointer to the stack * that must be freed with silc_stack_free function when it is not * needed anymore. If the `stack_size' is zero (0) by default a - * 1 kilobyte (1024 bytes) stack is allocated. If the `stack_size' + * 2 kilobytes (2048 bytes) stack is allocated. If the `stack_size' * is non-zero the byte value must be multiple by 8. * + * If `parent' is non-NULL the created stack is a child of the `parent' + * stack. All of childs the memory is allocated from the `parent' and + * will be returned back to the parent when the child is freed. Note + * that, even though child allocated memory from the parent, the parent's + * stack is not consumed. + * + * Returns NULL on error. + * ***/ -SilcStack silc_stack_alloc(SilcUInt32 stack_size); +SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent); /****f* silcutil/SilcStackAPI/silc_stack_free * @@ -121,6 +133,9 @@ SilcStack silc_stack_alloc(SilcUInt32 stack_size); * Frees the data stack context. The stack cannot be used anymore after * this and all allocated memory are freed. * + * If `stack' is a child stack, its memory is returned back to its + * parent. + * ***/ void silc_stack_free(SilcStack stack); diff --git a/lib/silcutil/silcstack_i.h b/lib/silcutil/silcstack_i.h index c7ee81d8..03bc8986 100644 --- a/lib/silcutil/silcstack_i.h +++ b/lib/silcutil/silcstack_i.h @@ -25,18 +25,19 @@ #endif /* The default stack size when stack is created */ -#define SILC_STACK_DEFAULT_SIZE 1024 +#define SILC_STACK_DEFAULT_SIZE 2048 -/* Number of pre-allocated stack frames */ -#define SILC_STACK_DEFAULT_NUM 8 +/* Number of pre-allocated stack frames. Frames are allocated from the + stack itself. */ +#define SILC_STACK_DEFAULT_NUM 32 /* Default alignment */ -#define SILC_STACK_DEFAULT_ALIGN sizeof(unsigned long) +#define SILC_STACK_DEFAULT_ALIGN sizeof(unsigned long) -/* Maximum allocation that can be made with SilcStack. This is - SILC_STACK_DEFAULT_SIZE * (2 ^ (SILC_STACK_BLOCK_NUM - 1)). */ -#define SILC_STACK_MAX_ALLOC 0x02000000 -#define SILC_STACK_BLOCK_NUM 16 +/* Maximum allocation that can be made with SilcStack. */ +#define SILC_STACK_BLOCK_NUM 20 +#define SILC_STACK_MAX_ALLOC \ + (SILC_STACK_DEFAULT_SIZE * (1L << (SILC_STACK_BLOCK_NUM - 1)) << 1) /* Stack frame data area */ typedef struct SilcStackDataStruct { @@ -44,6 +45,14 @@ typedef struct SilcStackDataStruct { /* Stack data area starts here */ } *SilcStackData; +/* Stack data entry */ +typedef struct SilcStackDataEntryStruct { + struct SilcStackDataEntryStruct *next; + SilcStackData data[SILC_STACK_BLOCK_NUM]; /* Blocks */ + SilcUInt32 bsize; /* Default block size */ + SilcUInt32 si; /* Default block index */ +} *SilcStackDataEntry; + /* Stack frame */ struct SilcStackFrameStruct { struct SilcStackFrameStruct *prev; /* Pointer to previous frame */ @@ -52,21 +61,6 @@ struct SilcStackFrameStruct { unsigned int si : 5; /* Stack index */ }; -/* The SilcStack context */ -struct SilcStackStruct { - SilcStackData stack[SILC_STACK_BLOCK_NUM]; /* Allocated stack blocks */ - SilcStackFrame *frames; /* Allocated stack frames */ - SilcStackFrame *frame; /* Current stack frame */ - SilcUInt32 stack_size; /* Default stack size */ - SilcUInt32 alignment; /* Memory alignment */ -#ifdef SILC_DIST_INPLACE - /* Statistics */ - SilcUInt32 snum_malloc; - SilcUInt32 sbytes_malloc; - SilcUInt32 snum_errors; -#endif /* SILC_DIST_INPLACE */ -}; - /* Align the requested amount bytes. The `align' defines the requested alignment. */ #define SILC_STACK_ALIGN(bytes, align) (((bytes) + (align - 1)) & ~(align - 1)) @@ -74,13 +68,17 @@ struct SilcStackStruct { /* Computes the size of stack block si. */ #define SILC_STACK_BLOCK_SIZE(stack, si) \ (((si) == 0) ? stack->stack_size : \ - SILC_STACK_DEFAULT_SIZE * (1L << ((si) - 1)) << 1); + SILC_STACK_DEFAULT_SIZE * (1L << ((si) - 1)) << 1) + +/* Returns a pointer to the data in the given stack block */ +#define SILC_STACK_DATA_EXT(data, si, bsize, alignment) \ + (((unsigned char *)(data)[si]) + \ + SILC_STACK_ALIGN(sizeof(**(data)), alignment) + \ + ((bsize) - (data)[si]->bytes_left)) /* Returns a pointer to the data in the frame */ #define SILC_STACK_DATA(stack, si, bsize) \ - (((unsigned char *)(stack)->stack[si]) + \ - SILC_STACK_ALIGN(sizeof(**(stack)->stack), (stack)->alignment) + \ - ((bsize) - (stack)->stack[si]->bytes_left)) + SILC_STACK_DATA_EXT((stack)->stack->data, si, bsize, (stack)->alignment) #ifdef SILC_DIST_INPLACE /* Statistics updating */ diff --git a/lib/silcutil/tests/Makefile.am b/lib/silcutil/tests/Makefile.am index 4b5513a9..364092bb 100644 --- a/lib/silcutil/tests/Makefile.am +++ b/lib/silcutil/tests/Makefile.am @@ -20,7 +20,8 @@ AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign bin_PROGRAMS = test_silcstrutil test_silcstringprep test_silchashtable \ test_silclist test_silcfsm test_silcasync test_silcschedule \ test_silcnet test_silcstack test_silcmime test_silcfdstream \ - test_silcatomic test_silcmutex test_silctime test_silcthread + test_silcatomic test_silcmutex test_silctime test_silcthread \ + test_silcdll test_silcenv test_silcstrutil_SOURCES = test_silcstrutil.c test_silcstringprep_SOURCES = test_silcstringprep.c @@ -37,6 +38,8 @@ test_silcatomic_SOURCES = test_silcatomic.c test_silcmutex_SOURCES = test_silcmutex.c test_silctime_SOURCES = test_silctime.c test_silcthread_SOURCES = test_silcthread.c +test_silcdll_SOURCES = test_silcdll.c +test_silcenv_SOURCES = test_silcenv.c LIBS = $(SILC_COMMON_LIBS) LDADD = -L.. -L../.. -lsilc diff --git a/lib/silcutil/tests/test_silcstack.c b/lib/silcutil/tests/test_silcstack.c index e4f87064..f3c19091 100644 --- a/lib/silcutil/tests/test_silcstack.c +++ b/lib/silcutil/tests/test_silcstack.c @@ -7,7 +7,7 @@ int main(int argc, char **argv) { SilcBool success = FALSE; - SilcStack stack; + SilcStack stack, child, child2; void *ptr, *ptr2; int i; @@ -19,7 +19,7 @@ int main(int argc, char **argv) } SILC_LOG_DEBUG(("Allocating stack of default size (1024 bytes)")); - stack = silc_stack_alloc(0); + stack = silc_stack_alloc(0, NULL); if (!stack) goto err; silc_stack_stats(stack); @@ -34,7 +34,7 @@ int main(int argc, char **argv) silc_stack_free(stack); SILC_LOG_DEBUG(("Allocating stack of default size (1024 bytes)")); - stack = silc_stack_alloc(0); + stack = silc_stack_alloc(0, NULL); if (!stack) goto err; silc_stack_stats(stack); @@ -93,6 +93,82 @@ int main(int argc, char **argv) SILC_LOG_DEBUG(("Popping")); silc_stack_stats(stack); + SILC_LOG_DEBUG(("Creating child stack")); + child = silc_stack_alloc(8192, stack); + if (!child) + goto err; + SILC_LOG_DEBUG(("Pushing %d times", NUM_ALLS / 2)); + for (i = 0; i < NUM_ALLS / 2; i++) { + if (!silc_stack_push(child, NULL)) + goto err; + ptr2 = silc_smalloc(child, (i + 1) * 7); + if (!ptr2) + goto err; + } + silc_stack_stats(child); + SILC_LOG_DEBUG(("Popping %d times", NUM_ALLS / 2)); + for (i = 0; i < NUM_ALLS / 2; i++) + silc_stack_pop(child); + silc_stack_stats(child); + + SILC_LOG_DEBUG(("Pushing and reallocating %d times", NUM_ALLS / 10)); + ptr2 = NULL; + if (!silc_stack_push(child, NULL)) + goto err; + for (i = 0; i < NUM_ALLS / 10; i++) { + ptr2 = silc_srealloc(child, (i * 7), ptr2, (i + 1) * 7); + if (!ptr2) + goto err; + } + ptr = silc_smalloc(child, 100000); + silc_stack_stats(child); + silc_stack_pop(child); + SILC_LOG_DEBUG(("Popping")); + silc_stack_stats(child); + silc_stack_stats(stack); + silc_stack_free(child); + silc_stack_stats(stack); + + SILC_LOG_DEBUG(("Creating child stack")); + child = silc_stack_alloc(8192, stack); + if (!child) + goto err; + SILC_LOG_DEBUG(("Pushing %d times", NUM_ALLS / 10)); + for (i = 0; i < NUM_ALLS / 10; i++) { + if (!silc_stack_push(child, NULL)) + goto err; + ptr2 = silc_smalloc(child, (i + 1) * 7); + if (!ptr2) + goto err; + } + silc_stack_stats(child); + SILC_LOG_DEBUG(("Popping %d times", NUM_ALLS / 10)); + for (i = 0; i < NUM_ALLS / 10; i++) + silc_stack_pop(child); + silc_stack_stats(child); + + SILC_LOG_DEBUG(("Pushing and reallocating %d times", NUM_ALLS / 10)); + ptr2 = NULL; + if (!silc_stack_push(child, NULL)) + goto err; + for (i = 0; i < NUM_ALLS / 10; i++) { + ptr2 = silc_srealloc(child, (i * 7), ptr2, (i + 1) * 7); + if (!ptr2) + goto err; + } + SILC_LOG_DEBUG(("Allocate child from child")); + child2 = silc_stack_alloc(0, child); + ptr = silc_smalloc(child2, 500000); + silc_stack_stats(child2); + silc_stack_free(child2); + silc_stack_stats(child); + silc_stack_pop(child); + SILC_LOG_DEBUG(("Popping")); + silc_stack_stats(child); + silc_stack_stats(stack); + silc_stack_free(child); + silc_stack_stats(stack); + SILC_LOG_DEBUG(("Current alignment: %d", silc_stack_get_alignment(stack))); SILC_LOG_DEBUG(("Set alignemtn to 16")); silc_stack_set_alignment(stack, 16);