add debug support for the memory manager:
authorHannes Gredler <hannes@gredler.at>
Sun, 23 Nov 2008 10:55:55 +0000 (11:55 +0100)
committerHannes Gredler <hannes@gredler.at>
Sun, 23 Nov 2008 10:55:55 +0000 (11:55 +0100)
for memory cookies now two flags can get set.
- NO_MEMLCEAR and
- MEM_POISON.

NO_MEMLCEAR does not memset() memory blocks on the freelist.
  this is used for performance critical applications.
MEM_POISON does memset() a spoiling pattern on the freelist,
  such that corruption can get deteced easier.

src/olsr_cookie.c
src/olsr_cookie.h

index 8cba1fe..c554e40 100644 (file)
@@ -150,6 +150,47 @@ olsr_cookie_set_memory_size(struct olsr_cookie_info *ci, size_t size)
   ci->ci_size = size;
 }
 
+/*
+ * 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_memclear(struct olsr_cookie_info *ci, olsr_bool clear)
+{
+  if (!ci) {
+    return;
+  }
+
+  assert(ci->ci_type == OLSR_COOKIE_TYPE_MEMORY);
+
+  if (clear) {
+    ci->ci_flags |= COOKIE_NO_MEMCLEAR;
+  } else {
+    ci->ci_flags &= ~COOKIE_NO_MEMCLEAR;
+  }
+}
+
+/*
+ * 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_mempoison(struct olsr_cookie_info *ci, olsr_bool poison)
+{
+  if (!ci) {
+    return;
+  }
+
+  assert(ci->ci_type == OLSR_COOKIE_TYPE_MEMORY);
+
+  if (poison) {
+    ci->ci_flags |= COOKIE_MEMPOISON;
+  } else {
+    ci->ci_flags &= ~COOKIE_MEMPOISON;
+  }
+}
+
 /*
  * Basic sanity checking for a passed-in cookie-id.
  */
@@ -212,6 +253,7 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
   struct olsr_cookie_mem_brand *branding;
   struct list_node *free_list_node;
   olsr_bool reuse = OLSR_FALSE;
+  size_t size;
 
   /*
    * Check first if we have reusable memory.
@@ -220,8 +262,10 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
 
     /*
      * No reusable memory block on the free_list.
+     * Allocate a fresh one.
      */
-    ptr = calloc(1, ci->ci_size + sizeof(struct olsr_cookie_mem_brand));
+    size = ci->ci_size + sizeof(struct olsr_cookie_mem_brand);
+    ptr = calloc(1, size);
 
     if (!ptr) {
       const char *const err_msg = strerror(errno);
@@ -229,6 +273,14 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
       olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %s\n", err_msg);
       olsr_exit(ci->ci_name, EXIT_FAILURE);
     }
+
+    /*
+     * Poison the memory for debug purposes ?
+     */
+    if (ci->ci_flags & COOKIE_MEMPOISON) {
+      memset(ptr, COOKIE_MEMPOISON_PATTERN, size);
+    }
+
   } else {
 
     /*
@@ -238,7 +290,22 @@ olsr_cookie_malloc(struct olsr_cookie_info *ci)
     free_list_node = ci->ci_free_list.next;
     list_remove(free_list_node);
     ptr = (void *)free_list_node;
-    memset(ptr, 0, ci->ci_size);
+
+    /*
+     * Reset the memory unless the caller has told us so.
+     */
+    if (!(ci->ci_flags & COOKIE_NO_MEMCLEAR)) {
+
+      /*
+       * Poison the memory for debug purposes ?
+       */
+      if (ci->ci_flags & COOKIE_MEMPOISON) {
+        memset(ptr, COOKIE_MEMPOISON_PATTERN, ci->ci_size);
+      } else {
+        memset(ptr, 0, ci->ci_size);
+      }
+    }
+
     ci->ci_free_list_usage--;
     reuse = OLSR_TRUE;
   }
index dadc88a..cfbdfe7 100644 (file)
@@ -63,12 +63,18 @@ struct olsr_cookie_info {
   char *ci_name;                      /* Name */
   olsr_cookie_type ci_type;           /* Type of cookie */
   size_t ci_size;                     /* Fixed size for block allocations */
+  unsigned int ci_flags;              /* Misc. flags */
   unsigned int ci_usage;              /* Stats, resource usage */
   unsigned int ci_changes;            /* Stats, resource churn */
   struct list_node ci_free_list;       /* List head for recyclable blocks */
   unsigned int ci_free_list_usage;     /* Length of free list */
 };
 
+/* Cookie flags */
+#define COOKIE_NO_MEMCLEAR  ( 1 << 0)  /* Do not clear memory */
+#define COOKIE_MEMPOISON    ( 2 << 0)  /* Poison memory pattern */
+
+#define COOKIE_MEMPOISON_PATTERN  0xa6 /* Pattern to spoil memory */
 #define COOKIE_FREE_LIST_THRESHOLD 10  /* Blocks / Percent  */
 
 /*
@@ -87,6 +93,8 @@ extern void olsr_free_cookie(struct olsr_cookie_info *);
 extern void olsr_delete_all_cookies(void);
 extern char *olsr_cookie_name(olsr_cookie_t);
 extern void olsr_cookie_set_memory_size(struct olsr_cookie_info *, size_t);
+extern void olsr_cookie_set_memclear(struct olsr_cookie_info *, olsr_bool);
+extern void olsr_cookie_set_mempoison(struct olsr_cookie_info *, olsr_bool);
 extern void olsr_cookie_usage_incr(olsr_cookie_t);
 extern void olsr_cookie_usage_decr(olsr_cookie_t);