Added reference counting the SilcStack.
authorPekka Riikonen <priikone@silcnet.org>
Wed, 27 Feb 2008 17:21:48 +0000 (19:21 +0200)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 27 Feb 2008 17:21:48 +0000 (19:21 +0200)
The reference counting makes it possible for a parent to be freed
underneath a child stack.  When the child is freed the parent will be
finally freed as well.

TODO
lib/silcutil/silcstack.c

diff --git a/TODO b/TODO
index e907469ae69eee172f41a3210a49bdfafb44902e..f6c2af46f3cbaf065a5d872c254b227ddf297c50 100644 (file)
--- a/TODO
+++ b/TODO
@@ -52,6 +52,8 @@ Runtime library, lib/silcutil/
 
  o Multicast support.
 
+ o Implement silc_get_num_cpu.
+
  o silc_file_readfile and silc_file_writefile should perhaps do the thing
    with mmap, as it's probably a bit faster.
 
index 6a2d5d6b107fa9c56574e44bee507d5962319b9b..576ef6198c4b7645a91069840e2934413dc718a6 100644 (file)
@@ -33,6 +33,7 @@ struct SilcStackStruct {
   void *oom_context;                         /* OOM handler context */
   SilcUInt32 stack_size;                     /* Default stack size */
   SilcUInt32 alignment;                              /* Memory alignment */
+  SilcAtomic32 refcnt;                       /* Reference counter */
 #ifdef SILC_DIST_INPLACE
   /* Statistics */
   SilcUInt32 snum_malloc;
@@ -211,6 +212,12 @@ SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent)
       return NULL;
     }
 
+    /* Reference parent */
+    SILC_LOG_DEBUG(("Reference stack %p, refcnt %d > %d", stack->parent,
+                   silc_atomic_get_int32(&stack->parent->refcnt),
+                   silc_atomic_get_int32(&stack->parent->refcnt) + 1));
+    silc_atomic_add_int32(&stack->parent->refcnt, 1);
+
     /* Set the initial stack */
     stack->stack = e;
   } else {
@@ -257,6 +264,8 @@ SilcStack silc_stack_alloc(SilcUInt32 stack_size, SilcStack parent)
     silc_mutex_alloc(&stack->lock);
   }
 
+  silc_atomic_init32(&stack->refcnt, 1);
+
   /* Use the allocated stack in first stack frame */
   stack->frame = &stack->frames[0];
   stack->frame->prev = NULL;
@@ -279,7 +288,13 @@ void silc_stack_free(SilcStack stack)
   if (!stack)
     return;
 
-  SILC_LOG_DEBUG(("Free stack %p", stack));
+  SILC_LOG_DEBUG(("Free stack %p, refcnt %d > %d", stack,
+                 silc_atomic_get_int32(&stack->refcnt),
+                 silc_atomic_get_int32(&stack->refcnt) - 1));
+
+  /* Unreference */
+  if (silc_atomic_sub_int32(&stack->refcnt, 1) > 0)
+    return;
 
   if (!stack->parent) {
     silc_list_start(stack->stacks);
@@ -296,6 +311,8 @@ void silc_stack_free(SilcStack stack)
     if (stack->lock)
       silc_mutex_free(stack->lock);
 
+    silc_atomic_uninit32(&stack->refcnt);
+
     silc_free(stack);
   } else {
     /* Return all stack blocks to the parent */
@@ -304,6 +321,9 @@ void silc_stack_free(SilcStack stack)
       silc_stack_unref_stack(stack->parent, e);
 
     silc_stack_unref_stack(stack->parent, stack->stack);
+
+    /* Unreference parent */
+    silc_stack_free(stack->parent);
   }
 }