From: Pekka Riikonen Date: Sun, 8 Jul 2007 17:26:58 +0000 (+0000) Subject: Inherit lock from parent when creating SilcStack child. X-Git-Tag: 1.2.beta1~209 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=5f8fefbe150117f9b22a82d6b17a9cb4c8800d2d;p=crypto.git Inherit lock from parent when creating SilcStack child. Check stack blocks from parent if child doesn't have them instead of immediately allocating new one. Added silc_stack_purge. --- diff --git a/lib/silcutil/silcstack.c b/lib/silcutil/silcstack.c index ab5cd62b..d22fba3f 100644 --- a/lib/silcutil/silcstack.c +++ b/lib/silcutil/silcstack.c @@ -78,7 +78,8 @@ static SilcStackDataEntry silc_stack_ref_stack(SilcStack stack, *ret_si = si; *ret_bsize = bsize; - SILC_ST_DEBUG(("Get stack block, si %d, size %lu", si, bsize)); + SILC_ST_DEBUG(("Get stack block, si %d, size %lu, stack %p", + si, bsize, stack)); silc_mutex_lock(stack->lock); @@ -94,6 +95,12 @@ static SilcStackDataEntry silc_stack_ref_stack(SilcStack stack, return e; } + /* If we are child, get block from parent */ + if (stack->parent) { + silc_mutex_unlock(stack->lock); + return silc_stack_ref_stack(stack->parent, size, ret_si, ret_bsize); + } + SILC_ST_DEBUG(("Allocate new stack blocks")); /* Allocate new stack blocks */ @@ -193,6 +200,7 @@ SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent) stack->alignment = SILC_STACK_DEFAULT_ALIGN; stack->oom_handler = parent->oom_handler; stack->oom_context = parent->oom_context; + stack->lock = parent->lock; silc_list_init(stack->stacks, struct SilcStackDataEntryStruct, next); /* Allocate stack frames from the parent */ @@ -244,10 +252,10 @@ SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent) silc_free(stack); return NULL; } - } - /* Allocate lock */ - silc_mutex_alloc(&stack->lock); + /* Allocate lock */ + silc_mutex_alloc(&stack->lock); + } /* Use the allocated stack in first stack frame */ stack->frame = &stack->frames[0]; @@ -273,9 +281,6 @@ void silc_stack_free(SilcStack stack) SILC_LOG_DEBUG(("Free stack %p", stack)); - if (stack->lock) - silc_mutex_free(stack->lock); - if (!stack->parent) { silc_list_start(stack->stacks); while ((e = silc_list_get(stack->stacks))) { @@ -288,6 +293,9 @@ void silc_stack_free(SilcStack stack) silc_free(stack->stack->data[i]); silc_free(stack->stack); + if (stack->lock) + silc_mutex_free(stack->lock); + silc_free(stack); } else { /* Return all stack blocks to the parent */ @@ -530,6 +538,63 @@ SilcUInt32 silc_stack_get_alignment(SilcStack stack) return stack->alignment; } +/* Purge stack */ + +SilcBool silc_stack_purge(SilcStack stack) +{ + SilcStackDataEntry e; + SilcBool ret = FALSE; + int i; + + SILC_LOG_DEBUG(("Purge stack %p", stack)); + + /* Go through the default stack */ + for (i = SILC_STACK_BLOCK_NUM - 1; i > 3; i--) { + if (stack->stack->data[i] && + stack->stack->data[i]->bytes_left == SILC_STACK_BLOCK_SIZE(stack, i)) { + SILC_LOG_DEBUG(("Purge %d bytes", + SILC_STACK_BLOCK_SIZE(stack, i))); + silc_free(stack->stack->data[i]); + stack->stack->data[i] = NULL; + ret = TRUE; + } + } + + silc_mutex_lock(stack->lock); + + /* Remove one child stack */ + if (silc_list_count(stack->stacks) > 2) { + silc_list_start(stack->stacks); + e = silc_list_get(stack->stacks); + + SILC_LOG_DEBUG(("Remove stack blocks %p", e->data)); + silc_list_del(stack->stacks, e); + ret = TRUE; + + for (i = 0; i < SILC_STACK_BLOCK_NUM; i++) + silc_free(e->data[i]); + silc_free(e); + } + + /* Go through the child stacks */ + silc_list_start(stack->stacks); + while ((e = silc_list_get(stack->stacks))) { + for (i = SILC_STACK_BLOCK_NUM - 1; i > 3; i--) { + if (e->data[i]) { + SILC_LOG_DEBUG(("Purge %d bytes", + SILC_STACK_BLOCK_SIZE(stack, i))); + silc_free(e->data[i]); + e->data[i] = NULL; + ret = TRUE; + } + } + } + + silc_mutex_unlock(stack->lock); + + return ret; +} + #ifdef SILC_DIST_INPLACE /* Statistics dumping. */ diff --git a/lib/silcutil/silcstack.h b/lib/silcutil/silcstack.h index c60cd7b7..99d1c4ad 100644 --- a/lib/silcutil/silcstack.h +++ b/lib/silcutil/silcstack.h @@ -365,6 +365,25 @@ void silc_stack_set_alignment(SilcStack stack, SilcUInt32 alignment); ***/ SilcUInt32 silc_stack_get_alignment(SilcStack stack); +/****f* silcutil/SilcStackAPI/silc_stack_purge + * + * SYNOPSIS + * + * SilcBool silc_stack_purge(SilcStack stack); + * + * DESCRIPTION + * + * Purges the `stack' from extra unused memory. This purges only `stack' + * and not its parent if `stack' is a child. This purges only large + * allocations. The 1024, 2048, 4096 and 8192 bytes of allocations remain. + * Call this multiple times to purge even more. Returns FALSE when there + * is no more to purge. This does not purge memory blocks that currently + * have allocations. No memory allocations from the stack are lost, so + * this is always safe to call. + * + ***/ +SilcBool silc_stack_purge(SilcStack stack); + #include "silcstack_i.h" #endif /* SILCSTACK_H */ diff --git a/lib/silcutil/tests/test_silcstack.c b/lib/silcutil/tests/test_silcstack.c index f3c19091..22474625 100644 --- a/lib/silcutil/tests/test_silcstack.c +++ b/lib/silcutil/tests/test_silcstack.c @@ -169,6 +169,10 @@ int main(int argc, char **argv) silc_stack_free(child); silc_stack_stats(stack); + SILC_LOG_DEBUG(("Purge stack")); + silc_stack_purge(stack); + 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);