scheduler: Custom additions to memory cookies
authorHenning Rogge <hrogge@googlemail.com>
Wed, 18 Aug 2010 17:18:18 +0000 (19:18 +0200)
committerHenning Rogge <hrogge@googlemail.com>
Wed, 18 Aug 2010 17:18:18 +0000 (19:18 +0200)
19 files changed:
lib/bmf/src/olsrd_plugin.c
lib/debuginfo/src/olsrd_debuginfo.c
lib/mdns/src/olsrd_plugin.c
lib/obamp/src/olsrd_plugin.c
src/duplicate_set.c
src/hna_set.c
src/interfaces.c
src/lq_plugin.c
src/mid_set.c
src/neighbor_table.c
src/olsr_comport.c
src/olsr_comport_http.c
src/olsr_comport_txt.c
src/olsr_cookie.c
src/olsr_cookie.h
src/plugin_loader.c
src/routing_table.c
src/scheduler.c
src/tc_set.c

index ffe33b5..d29b848 100644 (file)
@@ -48,7 +48,7 @@
 #include "defs.h"               /* uint8_t, olsr_cnf */
 #include "scheduler.h"          /* olsr_start_timer() */
 #include "olsr_cfg.h"           /* olsr_cnf() */
-#include "olsr_cookie.h"        /* olsr_alloc_cookie() */
+#include "olsr_cookie.h"        /* olsr_create_memcookie() */
 #include "olsr_logging.h"
 
 /* BMF includes */
index d979969..8c6b650 100644 (file)
@@ -199,10 +199,10 @@ olsrd_plugin_init(void)
   statistics_timer = olsr_alloc_timerinfo("debuginfo timer", &update_statistics_ptr, true);
   olsr_start_timer(traffic_interval * 1000, 0, NULL, statistics_timer);
 
-  statistics_msg_mem = olsr_alloc_cookie("debuginfo msgstat",
+  statistics_msg_mem = olsr_create_memcookie("debuginfo msgstat",
       sizeof(struct debug_msgtraffic) + sizeof(struct debug_msgtraffic_count) * traffic_slots);
 
-  statistics_pkt_mem = olsr_alloc_cookie("debuginfo pktstat",
+  statistics_pkt_mem = olsr_create_memcookie("debuginfo pktstat",
       sizeof(struct debug_pkttraffic) + sizeof(struct debug_pkttraffic_count) * traffic_slots);
 
   memset(&total_msg_traffic, 0, sizeof(total_msg_traffic));
index 7df04d2..1ab1b21 100644 (file)
@@ -48,7 +48,7 @@
 #include "defs.h"               /* uint8_t, olsr_cnf */
 #include "scheduler.h"          /* olsr_start_timer() */
 #include "olsr_cfg.h"           /* olsr_cnf() */
-#include "olsr_cookie.h"        /* olsr_alloc_cookie() */
+#include "olsr_cookie.h"        /* olsr_create_memcookie() */
 
 /* BMF includes */
 #include "mdns.h"               /* InitBmf(), CloseBmf() */
@@ -97,7 +97,7 @@ olsrd_plugin_init(void)
   //add_ifchgf(&InterfaceChange);
 
   /* create the cookie */
-  //prune_packet_history_timer_cookie = olsr_alloc_cookie("BMF: Prune Packet History", OLSR_COOKIE_TYPE_TIMER);
+  //prune_packet_history_timer_cookie = olsr_create_memcookie("BMF: Prune Packet History", OLSR_COOKIE_TYPE_TIMER);
 
   /* Register the duplicate registration pruning process */
   //olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
index 7da593d..b5d4984 100644 (file)
@@ -52,7 +52,7 @@
 #include "defs.h"               /* uint8_t, olsr_cnf */
 #include "scheduler.h"          /* olsr_start_timer() */
 #include "olsr_cfg.h"           /* olsr_cnf() */
-#include "olsr_cookie.h"        /* olsr_alloc_cookie() */
+#include "olsr_cookie.h"        /* olsr_create_memcookie() */
 
 /* OBAMP includes */
 #include "obamp.h"
index fb96d66..826b505 100644 (file)
@@ -121,7 +121,7 @@ olsr_init_duplicate_set(void)
    */
   duplicate_timer_info = olsr_alloc_timerinfo("Duplicate Set", &olsr_expire_duplicate_entry, false);
 
-  duplicate_mem_cookie = olsr_alloc_cookie("dup_entry", sizeof(struct dup_entry));
+  duplicate_mem_cookie = olsr_create_memcookie("dup_entry", sizeof(struct dup_entry));
 }
 
 
index b75f953..e4ff5c8 100644 (file)
@@ -66,7 +66,7 @@ olsr_init_hna_set(void)
 
   hna_net_timer_info = olsr_alloc_timerinfo("HNA Network", &olsr_expire_hna_net_entry, false);
 
-  hna_net_mem_cookie = olsr_alloc_cookie("hna_net", sizeof(struct hna_net));
+  hna_net_mem_cookie = olsr_create_memcookie("hna_net", sizeof(struct hna_net));
 }
 
 /**
index 38db049..e485443 100644 (file)
@@ -102,9 +102,9 @@ init_interfaces(void)
   /*
    * Get some cookies for getting stats to ease troubleshooting.
    */
-  interface_mem_cookie = olsr_alloc_cookie("Interface", sizeof(struct interface));
+  interface_mem_cookie = olsr_create_memcookie("Interface", sizeof(struct interface));
 
-  interface_lost_mem_cookie = olsr_alloc_cookie("Interface lost", sizeof(struct interface_lost));
+  interface_lost_mem_cookie = olsr_create_memcookie("Interface lost", sizeof(struct interface_lost));
 
   interface_poll_timerinfo = olsr_alloc_timerinfo("Interface Polling", &check_interface_updates, true);
   hello_gen_timerinfo = olsr_alloc_timerinfo("Hello Generation", &generate_hello, true);
index 105cac0..7535eb5 100644 (file)
@@ -69,13 +69,13 @@ init_lq_handler(void)
 
   OLSR_INFO(LOG_LQ_PLUGINS, "Initializing LQ handler %s...\n", active_lq_handler->name);
 
-  tc_edge_mem_cookie = olsr_alloc_cookie("tc_edge", active_lq_handler->size_tc_edge);
+  tc_edge_mem_cookie = olsr_create_memcookie("tc_edge", active_lq_handler->size_tc_edge);
 
   lq_hello_neighbor_mem_cookie =
-      olsr_alloc_cookie("lq_hello_neighbor", active_lq_handler->size_lq_hello_neighbor);
+      olsr_create_memcookie("lq_hello_neighbor", active_lq_handler->size_lq_hello_neighbor);
 
   link_entry_mem_cookie =
-      olsr_alloc_cookie("link_entry", active_lq_handler->size_link_entry);
+      olsr_create_memcookie("link_entry", active_lq_handler->size_link_entry);
 
   if (active_lq_handler->initialize) {
     active_lq_handler->initialize();
index 8f79760..e88b04a 100644 (file)
@@ -80,7 +80,7 @@ olsr_init_mid_set(void)
    */
   mid_validity_timer_info = olsr_alloc_timerinfo("MID validity", &olsr_expire_mid_entries, false);
 
-  mid_address_mem_cookie = olsr_alloc_cookie("MID address", sizeof(struct mid_entry));
+  mid_address_mem_cookie = olsr_create_memcookie("MID address", sizeof(struct mid_entry));
 }
 
 /**
index 2d74726..40802ff 100644 (file)
@@ -78,11 +78,11 @@ olsr_init_neighbor_table(void)
   avl_init(&nbr2_tree, avl_comp_default, false, NULL);
 
   nbr_connector_timer_info = olsr_alloc_timerinfo("Neighbor connector", &olsr_expire_nbr_con, false);
-  nbr_connector_mem_cookie = olsr_alloc_cookie("Neighbor connector", sizeof(struct nbr_con));
+  nbr_connector_mem_cookie = olsr_create_memcookie("Neighbor connector", sizeof(struct nbr_con));
 
-  nbr_mem_cookie = olsr_alloc_cookie("1-Hop Neighbor", sizeof(struct nbr_entry));
+  nbr_mem_cookie = olsr_create_memcookie("1-Hop Neighbor", sizeof(struct nbr_entry));
 
-  nbr2_mem_cookie = olsr_alloc_cookie("2-Hop Neighbor", sizeof(struct nbr2_entry));
+  nbr2_mem_cookie = olsr_create_memcookie("2-Hop Neighbor", sizeof(struct nbr2_entry));
 }
 
 /**
index 56f2248..2e32479 100644 (file)
@@ -93,7 +93,7 @@ static void olsr_com_timeout_handler(void *);
 
 void olsr_com_init(bool failfast) {
   connection_cookie =
-      olsr_alloc_cookie("comport connections", sizeof(struct comport_connection));
+      olsr_create_memcookie("comport connections", sizeof(struct comport_connection));
 
   connection_timeout = olsr_alloc_timerinfo("comport timout",
       &olsr_com_timeout_handler, false);
index 6441882..93ad6a8 100644 (file)
@@ -146,7 +146,7 @@ void
 olsr_com_init_http(void) {
   avl_init(&http_handler_tree, &avl_comp_strcasecmp, false, NULL);
 
-  htmlsite_cookie = olsr_alloc_cookie("comport http sites", sizeof(struct olsr_html_site));
+  htmlsite_cookie = olsr_create_memcookie("comport http sites", sizeof(struct olsr_html_site));
 
   /* activate telnet gateway */
   olsr_com_add_htmlhandler(olsr_com_html2telnet_gate, TELNET_PATH);
index 1a721c4..38735e7 100644 (file)
@@ -130,7 +130,7 @@ olsr_com_init_txt(void) {
   avl_init(&txt_normal_tree, &avl_comp_strcasecmp, false, NULL);
   avl_init(&txt_help_tree, &avl_comp_strcasecmp, false, NULL);
 
-  txtcommand_cookie = olsr_alloc_cookie("comport txt commands", sizeof(struct olsr_txtcommand));
+  txtcommand_cookie = olsr_create_memcookie("comport txt commands", sizeof(struct olsr_txtcommand));
 
   txt_repeat_timerinfo = olsr_alloc_timerinfo("txt repeat timer", olsr_txt_repeat_timer, true);
 
index 5a7a119..9bf7812 100644 (file)
@@ -44,8 +44,6 @@
 #include "olsr_cookie.h"
 #include "log.h"
 #include "common/list.h"
-#include "valgrind/valgrind.h"
-#include "valgrind/memcheck.h"
 
 #include <assert.h>
 #include <errno.h>
 
 struct avl_tree olsr_cookie_tree;
 
+static inline size_t calc_aligned_size(size_t size) {
+  static const size_t add = sizeof(size_t) * 2 - 1;
+  static const size_t mask = ~(sizeof(size_t)*2 - 1);
+
+  return (size + add) & mask;
+}
+
 void olsr_cookie_init(void) {
+  /* check size of memory prefix */
+  assert (sizeof(struct olsr_memory_prefix)
+      == calc_aligned_size(sizeof(struct olsr_memory_prefix)));
+
   avl_init(&olsr_cookie_tree, &avl_comp_strcasecmp, false, NULL);
 }
 
@@ -61,23 +70,29 @@ void olsr_cookie_init(void) {
  * Allocate a cookie for the next available cookie id.
  */
 struct olsr_cookie_info *
-olsr_alloc_cookie(const char *cookie_name, size_t size)
+olsr_create_memcookie(const char *cookie_name, size_t size)
 {
   struct olsr_cookie_info *ci;
 
   assert (cookie_name);
+  assert (size > 9);
 
-  ci = olsr_malloc(sizeof(struct olsr_cookie_info), "new cookie");
+  ci = olsr_malloc(sizeof(struct olsr_cookie_info), "memory cookie");
 
   /* Now populate the cookie info */
   ci->ci_name = olsr_strdup(cookie_name);
   ci->ci_node.key = ci->ci_name;
   ci->ci_size = size;
+  ci->ci_custom_offset = sizeof(struct olsr_memory_prefix) + calc_aligned_size(size);
   ci->ci_min_free_count = COOKIE_FREE_LIST_THRESHOLD;
 
+  /* no custom data at this point */
+  ci->ci_total_size = ci->ci_custom_offset;
+
   /* Init the free list */
   list_init_head(&ci->ci_free_list);
-  VALGRIND_CREATE_MEMPOOL(ci, 0, 1);
+  list_init_head(&ci->ci_used_list);
+  list_init_head(&ci->ci_custom_list);
 
   avl_insert(&olsr_cookie_tree, &ci->ci_node);
   return ci;
@@ -87,12 +102,10 @@ olsr_alloc_cookie(const char *cookie_name, size_t size)
  * Free a cookie that is no longer being used.
  */
 void
-olsr_free_cookie(struct olsr_cookie_info *ci)
+olsr_cleanup_memcookie(struct olsr_cookie_info *ci)
 {
-  struct list_entity *memory_list;
-
-  /* can only be called if not in use anymore */
-  assert(ci->ci_usage == 0);
+  struct olsr_memory_prefix *memory_entity;
+  struct list_iterator iterator;
 
   /* remove from tree */
   avl_delete(&olsr_cookie_tree, &ci->ci_node);
@@ -105,18 +118,17 @@ olsr_free_cookie(struct olsr_cookie_info *ci)
    * First make all items accessible,
    * such that valgrind does not complain at shutdown.
    */
-  if (!list_is_empty(&ci->ci_free_list)) {
-    for (memory_list = ci->ci_free_list.next; memory_list != &ci->ci_free_list; memory_list = memory_list->next) {
-      VALGRIND_MAKE_MEM_DEFINED(memory_list, ci->ci_size);
-    }
+
+  /* remove all free memory blocks */
+  OLSR_FOR_ALL_FREE_MEM(ci, memory_entity, iterator) {
+    free(memory_entity);
   }
 
-  while (!list_is_empty(&ci->ci_free_list)) {
-    memory_list = ci->ci_free_list.next;
-    list_remove(memory_list);
-    free(memory_list);
+  /* free all used memory blocks */
+  OLSR_FOR_ALL_USED_MEM(ci, memory_entity, iterator) {
+    free(memory_entity->custom);
+    free(memory_entity);
   }
-  VALGRIND_DESTROY_MEMPOOL(ci);
 
   free(ci);
 }
@@ -134,37 +146,10 @@ olsr_cookie_cleanup(void)
    * Walk the full index range and kill 'em all.
    */
   OLSR_FOR_ALL_COOKIES(info, iterator) {
-    if (info->ci_usage > 0) {
-      OLSR_WARN(LOG_COOKIE, "Free cookie %s: %d chunks still in use !\n", info->ci_name, info->ci_usage);
-
-      /* set usage to 0 */
-      info->ci_usage = 0;
-    }
-    olsr_free_cookie(info);
+    olsr_cleanup_memcookie(info);
   }
 }
 
-/*
- * Set if a returned memory block shall be cleared after returning to
- * the free pool. This is only allowed for memory cookies.
- */
-void
-olsr_cookie_set_memory_clear(struct olsr_cookie_info *ci, bool clear)
-{
-  ci->ci_no_memclear = !clear;
-}
-
-/*
- * Set if a returned memory block shall be initialized to an all zero or
- * to a poison memory pattern after returning to the free pool.
- * This is only allowed for memory cookies.
- */
-void
-olsr_cookie_set_memory_poison(struct olsr_cookie_info *ci, bool poison)
-{
-  ci->ci_poison = poison;
-}
-
 /*
  * Set if a returned memory block shall be cleared after returning to
  * the free pool. This is only allowed for memory cookies.
@@ -202,8 +187,10 @@ olsr_cookie_usage_decr(struct olsr_cookie_info *ci)
 void *
 olsr_cookie_malloc(struct olsr_cookie_info *ci)
 {
-  void *ptr;
-  struct list_entity *free_list_node;
+  struct olsr_memory_prefix *mem;
+  struct olsr_cookie_custom *custom;
+  struct list_iterator iterator;
+
 #if !defined REMOVE_LOG_DEBUG
   bool reuse = false;
 #endif
@@ -211,63 +198,21 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
   /*
    * Check first if we have reusable memory.
    */
-  if (!ci->ci_free_list_usage) {
-
+  if (list_is_empty(&ci->ci_free_list)) {
     /*
      * No reusable memory block on the free_list.
      * Allocate a fresh one.
      */
-    ptr = olsr_malloc(ci->ci_size, ci->ci_name);
-
-    /*
-     * Poison the memory for debug purposes ?
-     */
-    if (ci->ci_poison) {
-      memset(ptr, COOKIE_MEMPOISON_PATTERN, ci->ci_size);
-    }
-
+    mem = olsr_malloc(ci->ci_total_size, ci->ci_name);
   } else {
-
     /*
      * There is a memory block on the free list.
      * Carve it out of the list, and clean.
      */
-    free_list_node = ci->ci_free_list.next;
-    ptr = (void *)free_list_node;
-    VALGRIND_MAKE_MEM_DEFINED(ptr, ci->ci_size);
+    mem = list_first_element(&ci->ci_free_list, mem, node);
+    list_remove(&mem->node);
 
-    /*
-     * Before dequeuing the node from the free list,
-     * make the list pointers of the node ahead of
-     * us accessible, such that valgrind does not
-     * log a false positive.
-     */
-    if (free_list_node->next == &ci->ci_free_list) {
-      list_remove(free_list_node);
-    } else {
-
-      /*
-       * Make next item accessible, remove it and make next item inaccessible.
-       */
-      VALGRIND_MAKE_MEM_DEFINED(free_list_node->next, ci->ci_size);
-      list_remove(free_list_node);
-      VALGRIND_MAKE_MEM_NOACCESS(free_list_node->next, ci->ci_size);
-    }
-
-    /*
-     * Reset the memory unless the caller has told us so.
-     */
-    if (!ci->ci_no_memclear) {
-
-      /*
-       * Poison the memory for debug purposes ?
-       */
-      if (ci->ci_poison) {
-        memset(ptr, COOKIE_MEMPOISON_PATTERN, ci->ci_size);
-      } else {
-        memset(ptr, 0, ci->ci_size);
-      }
-    }
+    memset(mem, 0, ci->ci_total_size);
 
     ci->ci_free_list_usage--;
 #if !defined REMOVE_LOG_DEBUG
@@ -275,14 +220,27 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
 #endif
   }
 
+  /* add to used list */
+  list_add_tail(&ci->ci_used_list, &mem->node);
+
+  /* handle custom initialization */
+  if (!list_is_empty(&ci->ci_custom_list)) {
+    mem->custom = ((uint8_t *)mem) + ci->ci_custom_offset;
+
+    /* call up custom init functions */
+    OLSR_FOR_ALL_CUSTOM_MEM(ci, custom, iterator) {
+      if (custom->init) {
+        custom->init(ci, mem->custom + custom->offset);
+      }
+    }
+  }
+
   /* Stats keeping */
   olsr_cookie_usage_incr(ci);
 
   OLSR_DEBUG(LOG_COOKIE, "MEMORY: alloc %s, %p, %lu bytes%s\n",
-             ci->ci_name, ptr, (unsigned long)ci->ci_size, reuse ? ", reuse" : "");
-
-  VALGRIND_MEMPOOL_ALLOC(ci, ptr, ci->ci_size);
-  return ptr;
+             ci->ci_name, mem + 1, (unsigned long)ci->ci_size, reuse ? ", reuse" : "");
+  return mem + 1;
 }
 
 /*
@@ -292,61 +250,153 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
 void
 olsr_cookie_free(struct olsr_cookie_info *ci, void *ptr)
 {
-  struct list_entity *free_list_node;
+  struct olsr_memory_prefix *mem;
+  struct olsr_cookie_custom *custom;
+  struct list_iterator iterator;
 #if !defined REMOVE_LOG_DEBUG
   bool reuse = false;
 #endif
 
+  /* calculate pointer to memory prefix */
+  mem = ptr;
+  mem--;
+
+  /* call up custom cleanup */
+  OLSR_FOR_ALL_CUSTOM_MEM(ci, custom, iterator) {
+    if (custom->cleanup) {
+      custom->cleanup(ci, mem->custom + custom->offset);
+    }
+  }
+
+  /* remove from used_memory list */
+  list_remove(&mem->node);
+
   /*
    * Rather than freeing the memory right away, try to reuse at a later
    * point. Keep at least ten percent of the active used blocks or at least
    * ten blocks on the free list.
    */
-  if ((ci->ci_free_list_usage < ci->ci_min_free_count)
-      || (ci->ci_free_list_usage < ci->ci_usage / COOKIE_FREE_LIST_THRESHOLD)) {
-
-    free_list_node = (struct list_entity *)ptr;
-    list_init_node(free_list_node);
+  if (0 && mem->is_inline && ((ci->ci_free_list_usage < ci->ci_min_free_count)
+      || (ci->ci_free_list_usage < ci->ci_usage / COOKIE_FREE_LIST_THRESHOLD))) {
 
-    /*
-     * Before enqueuing the node to the free list,
-     * make the list pointers of the node ahead of
-     * us accessible, such that valgrind does not
-     * log a false positive.
-     */
-    if (list_is_empty(&ci->ci_free_list)) {
-      list_add_tail(&ci->ci_free_list, free_list_node);
-    } else {
-
-      /*
-       * Make next item accessible, add it and make next item inaccessible.
-       */
-      VALGRIND_MAKE_MEM_DEFINED(ci->ci_free_list.prev, ci->ci_size);
-      list_add_tail(&ci->ci_free_list, free_list_node);
-      VALGRIND_MAKE_MEM_NOACCESS(ci->ci_free_list.prev, ci->ci_size);
-    }
+    list_add_tail(&ci->ci_free_list, &mem->node);
 
     ci->ci_free_list_usage++;
 #if !defined REMOVE_LOG_DEBUG
     reuse = true;
 #endif
-
   } else {
 
-    /*
-     * No interest in reusing memory.
-     */
-    free(ptr);
+    /* No interest in reusing memory. */
+    if (!mem->is_inline) {
+      free (mem->custom);
+    }
+    free(mem);
   }
 
   /* Stats keeping */
   olsr_cookie_usage_decr(ci);
 
   OLSR_DEBUG(LOG_COOKIE, "MEMORY: free %s, %p, %lu bytes%s\n",
-             ci->ci_name, ptr, (unsigned long)ci->ci_size, reuse ? ", reuse" : "");
+             ci->ci_name, ptr, (unsigned long)ci->ci_total_size, reuse ? ", reuse" : "");
+}
+
+struct olsr_cookie_custom *
+olsr_alloc_cookie_custom(struct olsr_cookie_info *ci, size_t size, const char *name,
+    void (*init)(struct olsr_cookie_info *, void *),
+    void (*cleanup)(struct olsr_cookie_info *, void *)) {
+  struct olsr_cookie_custom *custom;
+  struct olsr_memory_prefix *mem;
+  struct list_iterator iterator;
+  size_t old_total_size, new_total_size;
+
+  custom = olsr_malloc(sizeof(struct olsr_cookie_custom), name);
+  custom->name = strdup(name);
+  custom->size = calc_aligned_size(size);
+  custom->init = init;
+  custom->cleanup = cleanup;
+
+  /* recalculate custom data block size */
+  old_total_size = ci->ci_total_size - ci->ci_custom_offset;
+  new_total_size = old_total_size + custom->size;
+
+  custom->offset = old_total_size;
+  ci->ci_total_size += custom->size;
+
+  /* reallocate custom data blocks on used memory blocks*/
+  OLSR_FOR_ALL_USED_MEM(ci, mem, iterator) {
+    uint8_t *custom_ptr;
+
+    custom_ptr = olsr_malloc(new_total_size, ci->ci_name);
+
+    /* copy old data */
+    if (old_total_size > 0) {
+      memcpy(custom_ptr, mem->custom, old_total_size);
+    }
+    mem->is_inline = false;
+
+    /* call up necessary initialization */
+    init(ci, custom_ptr + old_total_size);
+  }
+
+  /* remove all free data blocks, they have the wrong size */
+  OLSR_FOR_ALL_FREE_MEM(ci, mem, iterator) {
+    list_remove(&mem->node);
+    free(mem);
+  }
+  ci->ci_free_list_usage = 0;
+
+  /* add the custom data object to the list */
+  list_add_tail(&ci->ci_custom_list, &custom->node);
+  return custom;
+}
+
+void
+olsr_free_cookie_custom(struct olsr_cookie_info *ci, struct olsr_cookie_custom *custom) {
+  struct olsr_memory_prefix *mem;
+  struct olsr_cookie_custom *c_ptr;
+  struct list_iterator iterator;
+  size_t prefix_block, suffix_block;
+  bool match;
+
+  prefix_block = 0;
+  suffix_block = 0;
+  match = false;
+
+  OLSR_FOR_ALL_CUSTOM_MEM(ci, c_ptr, iterator) {
+    if (c_ptr == custom) {
+      match = true;
+      continue;
+    }
+
+    if (match) {
+      suffix_block += c_ptr->size;
+      c_ptr->offset -= custom->size;
+    }
+    else {
+      prefix_block += c_ptr->size;
+    }
+  }
+
+  /* move the custom memory back into a continous block */
+  if (suffix_block > 0) {
+    OLSR_FOR_ALL_USED_MEM(ci, mem, iterator) {
+      memmove(mem->custom + prefix_block, mem->custom + prefix_block + custom->size, suffix_block);
+    }
+  }
+  ci->ci_total_size -= custom->size;
+
+  /* remove all free data blocks, they have the wrong size */
+  OLSR_FOR_ALL_FREE_MEM(ci, mem, iterator) {
+    list_remove(&mem->node);
+    free(mem);
+  }
+  ci->ci_free_list_usage = 0;
 
-  VALGRIND_MEMPOOL_FREE(ci, ptr);
-  VALGRIND_MAKE_MEM_NOACCESS(ptr, ci->ci_size);
+  /* remove the custom data object from the list */
+  list_remove(&custom->node);
+  free (custom->name);
+  free (custom);
 }
 
 /*
index 6d0d24b..6685323 100644 (file)
@@ -63,9 +63,11 @@ struct olsr_cookie_info {
   /* Size of memory blocks */
   size_t ci_size;
 
-  /* flags */
-  bool ci_poison;
-  bool ci_no_memclear;
+  /* size including prefix and custom data */
+  size_t ci_total_size;
+
+  /* offset from the inline custom data block */
+  size_t ci_custom_offset;
 
   /*
    * minimum number of chunks the allocator will keep
@@ -79,6 +81,12 @@ struct olsr_cookie_info {
   /* Stats, resource churn */
   uint32_t ci_changes;
 
+  /* list of custom additions of this memory cookie */
+  struct list_entity ci_custom_list;
+
+  /* List head for used memory blocks */
+  struct list_entity ci_used_list;
+
   /* List head for recyclable blocks */
   struct list_entity ci_free_list;
 
@@ -86,25 +94,76 @@ struct olsr_cookie_info {
   uint32_t ci_free_list_usage;
 };
 
+/* Custom addition to existing cookie */
+struct olsr_cookie_custom {
+  struct list_entity node;
+
+  char *name;
+
+  size_t size;
+  size_t offset;
+
+  void (*init)(struct olsr_cookie_info *, void *);
+  void (*cleanup)(struct olsr_cookie_info *, void *);
+};
+
+/* should have a length of 2*memory_alignment */
+struct olsr_memory_prefix {
+  struct list_entity node;
+  uint8_t *custom;
+  uint8_t is_inline;
+  uint8_t padding[sizeof(size_t) - sizeof(uint8_t)];
+};
+
 #define OLSR_FOR_ALL_COOKIES(ci, iterator) avl_for_each_element_safe(&olsr_cookie_tree, ci, ci_node, iterator.loop, iterator.safe)
+#define OLSR_FOR_ALL_USED_MEM(ci, mem, iterator) list_for_each_element_safe(&ci->ci_used_list, mem, node, iterator.loop, iterator.safe)
+#define OLSR_FOR_ALL_FREE_MEM(ci, mem, iterator) list_for_each_element_safe(&ci->ci_free_list, mem, node, iterator.loop, iterator.safe)
+#define OLSR_FOR_ALL_CUSTOM_MEM(ci, custom, iterator) list_for_each_element_safe(&ci->ci_custom_list, custom, node, iterator.loop, iterator.safe)
 
-#define COOKIE_MEMPOISON_PATTERN  0xa6  /* Pattern to spoil memory */
 #define COOKIE_FREE_LIST_THRESHOLD 10   /* Blocks / Percent  */
 
 /* Externals. */
 void olsr_cookie_init(void);
 void olsr_cookie_cleanup(void);
 
-struct olsr_cookie_info *EXPORT(olsr_alloc_cookie) (const char *, size_t size);
-void EXPORT(olsr_free_cookie)(struct olsr_cookie_info *);
+struct olsr_cookie_info *EXPORT(olsr_create_memcookie) (const char *, size_t size);
+void EXPORT(olsr_cleanup_memcookie)(struct olsr_cookie_info *);
 
-void EXPORT(olsr_cookie_set_memory_clear) (struct olsr_cookie_info *, bool);
-void EXPORT(olsr_cookie_set_memory_poison) (struct olsr_cookie_info *, bool);
 void EXPORT(olsr_cookie_set_min_free)(struct olsr_cookie_info *, uint32_t);
 
 void *EXPORT(olsr_cookie_malloc) (struct olsr_cookie_info *);
 void EXPORT(olsr_cookie_free) (struct olsr_cookie_info *, void *);
 
+struct olsr_cookie_custom *EXPORT(olsr_alloc_cookie_custom)(
+    struct olsr_cookie_info *ci, size_t size, const char *name,
+    void (*init)(struct olsr_cookie_info *, void *),
+    void (*cleanup)(struct olsr_cookie_info *, void *));
+
+void EXPORT(olsr_free_cookie_custom)(
+    struct olsr_cookie_info *ci, struct olsr_cookie_custom *custom);
+
+/* inline function to access memory of custom data */
+static inline void *EXPORT(olsr_cookie_get_custom)(
+    struct olsr_cookie_info *ci,
+    struct olsr_cookie_custom *custom,
+    void *ptr) {
+  struct olsr_memory_prefix *mem;
+  uint8_t *c_ptr;
+
+  /* get to the prefix memory structure */
+  mem = ptr;
+  mem--;
+
+  if (mem->custom) {
+    c_ptr = mem->custom;
+  }
+  else {
+    c_ptr = (uint8_t *)mem;
+    c_ptr += ci->ci_custom_offset;
+  }
+  return c_ptr + custom->offset;
+}
+
 #endif /* _OLSR_COOKIE_H */
 
 /*
index 93796a1..beeb4ba 100644 (file)
@@ -94,7 +94,7 @@ struct olsr_plugin *olsr_get_plugin(const char *libname) {
 
 void
 olsr_init_pluginsystem(void) {
-  plugin_mem_cookie = olsr_alloc_cookie("Plugin handle", sizeof(struct olsr_plugin));
+  plugin_mem_cookie = olsr_create_memcookie("Plugin handle", sizeof(struct olsr_plugin));
 
   /* could already be initialized */
   if (!plugin_tree_initialized) {
index 1eece28..a2a7dee 100644 (file)
@@ -92,8 +92,8 @@ olsr_init_routing_table(void)
   /*
    * Get some cookies for memory stats and memory recycling.
    */
-  rt_mem_cookie = olsr_alloc_cookie("rt_entry", sizeof(struct rt_entry));
-  rtp_mem_cookie = olsr_alloc_cookie("rt_path", sizeof(struct rt_path));
+  rt_mem_cookie = olsr_create_memcookie("rt_entry", sizeof(struct rt_entry));
+  rtp_mem_cookie = olsr_create_memcookie("rt_path", sizeof(struct rt_path));
 }
 
 /**
index 823bb73..b1bcbbd 100644 (file)
@@ -66,7 +66,7 @@ static uint32_t timer_last_run;        /* remember the last timeslot walk */
 /* Memory cookie for the timer manager */
 struct avl_tree timerinfo_tree;
 static struct olsr_cookie_info *timer_mem_cookie = NULL;
-static struct olsr_cookie_info *timerinfo_coookie = NULL;
+static struct olsr_cookie_info *timerinfo_cookie = NULL;
 
 /* Head of all OLSR used sockets */
 static struct list_entity socket_head;
@@ -167,7 +167,7 @@ struct olsr_timer_info *
 olsr_alloc_timerinfo(const char *name, timer_cb_func callback, bool periodic) {
   struct olsr_timer_info *ti;
 
-  ti = olsr_cookie_malloc(timerinfo_coookie);
+  ti = olsr_cookie_malloc(timerinfo_cookie);
   ti->name = strdup(name);
   ti->node.key = ti->name;
   ti->callback = callback;
@@ -177,7 +177,6 @@ olsr_alloc_timerinfo(const char *name, timer_cb_func callback, bool periodic) {
   return ti;
 }
 
-
 /**
  * Add a socket and handler to the socketset
  * beeing used in the main select(2) loop
@@ -568,11 +567,10 @@ olsr_init_timers(void)
   timer_last_run = now_times;
 
   /* Allocate a cookie for the block based memory manager. */
-  timer_mem_cookie = olsr_alloc_cookie("timer_entry", sizeof(struct timer_entry));
-  olsr_cookie_set_memory_clear(timer_mem_cookie, false);
+  timer_mem_cookie = olsr_create_memcookie("timer_entry", sizeof(struct timer_entry));
 
   avl_init(&timerinfo_tree, avl_comp_strcasecmp, false, NULL);
-  timerinfo_coookie = olsr_alloc_cookie("timerinfo", sizeof(struct olsr_timer_info));
+  timerinfo_cookie = olsr_create_memcookie("timerinfo", sizeof(struct olsr_timer_info));
 }
 
 /**
@@ -687,6 +685,9 @@ walk_timers(uint32_t * last_run)
 void
 olsr_flush_timers(void)
 {
+  struct olsr_timer_info *ti;
+  struct list_iterator iterator;
+
   struct list_entity *timer_head_node;
   unsigned int wheel_slot = 0;
 
@@ -701,6 +702,16 @@ olsr_flush_timers(void)
       olsr_stop_timer(timer);
     }
   }
+
+  /* free all timerinfos */
+  OLSR_FOR_ALL_TIMERS(ti, iterator) {
+    avl_delete(&timerinfo_tree, &ti->node);
+    free(ti->name);
+    olsr_cookie_free(timerinfo_cookie, ti);
+  }
+
+  /* release memory cookie for timers */
+  olsr_cleanup_memcookie(timerinfo_cookie);
 }
 
 /**
index f3b5d22..ced75d3 100644 (file)
@@ -142,7 +142,7 @@ olsr_init_tc(void)
   tc_edge_gc_timer_info = olsr_alloc_timerinfo("TC edge GC", olsr_expire_tc_edge_gc, false);
   tc_validity_timer_info = olsr_alloc_timerinfo("TC validity", &olsr_expire_tc_entry, false);
 
-  tc_mem_cookie = olsr_alloc_cookie("tc_entry", sizeof(struct tc_entry));
+  tc_mem_cookie = olsr_create_memcookie("tc_entry", sizeof(struct tc_entry));
 }
 
 /**