aboutsummaryrefslogtreecommitdiffstats
path: root/epan/wmem
diff options
context:
space:
mode:
authorEvan Huus <eapache@gmail.com>2013-01-23 02:31:04 +0000
committerEvan Huus <eapache@gmail.com>2013-01-23 02:31:04 +0000
commit0cb2a257dee749e8d62c40d1a831efad8a87afce (patch)
tree20470ad876df10cc67709f0c3c676a1a8e0643c5 /epan/wmem
parentec7d4f0cfd42209ef35293a0e4f00d339b7a7745 (diff)
Convert the strict allocator to use a hash table similarly to the simple
allocator, allowing it to implement realloc and free. svn path=/trunk/; revision=47222
Diffstat (limited to 'epan/wmem')
-rw-r--r--epan/wmem/wmem_allocator_strict.c187
1 files changed, 138 insertions, 49 deletions
diff --git a/epan/wmem/wmem_allocator_strict.c b/epan/wmem/wmem_allocator_strict.c
index 5955d41c47..ad87b83314 100644
--- a/epan/wmem/wmem_allocator_strict.c
+++ b/epan/wmem/wmem_allocator_strict.c
@@ -27,6 +27,8 @@
#include <glib.h>
+#include "config.h"
+
#include "wmem_core.h"
#include "wmem_allocator.h"
@@ -44,9 +46,6 @@
#define WMEM_POSTFILL 0x1A
typedef struct _wmem_strict_allocator_block_t {
- /* Simple manual singly-linked list of allocations */
- struct _wmem_strict_allocator_block_t *next;
-
/* Just the length of real_data, not counting the canaries */
gsize data_len;
@@ -56,93 +55,181 @@ typedef struct _wmem_strict_allocator_block_t {
} wmem_strict_allocator_block_t;
typedef struct _wmem_strict_allocator_t {
- wmem_strict_allocator_block_t *block_list;
+ GHashTable *block_table;
} wmem_strict_allocator_t;
-static void *
-wmem_strict_alloc(void *private_data, const size_t size)
+/*
+ * some internal helper functions
+ */
+static void
+wmem_strict_block_check_canaries(wmem_strict_allocator_block_t *block)
+{
+ guint i;
+
+ for (i=0; i<WMEM_CANARY_SIZE; i++) {
+ g_assert(block->leading_canary[i] == WMEM_CANARY_VALUE);
+ g_assert(block->trailing_canary[i] == WMEM_CANARY_VALUE);
+ }
+}
+
+/* wrapper for use with g_hash_table_foreach() */
+static void
+wmem_strict_ghash_check_canaries(gpointer key _U_, gpointer value,
+ gpointer user_data _U_)
+{
+ wmem_strict_block_check_canaries(value);
+}
+
+static void
+wmem_strict_block_free(wmem_strict_allocator_block_t *block)
+{
+ memset(block->real_data, WMEM_POSTFILL, block->data_len);
+
+ g_free(block->leading_canary);
+ g_free(block);
+}
+
+/* wrapper for use with g_hash_table_new_full() */
+static void
+wmem_strict_ghash_block_free(gpointer data)
+{
+ wmem_strict_block_free(data);
+}
+
+static wmem_strict_allocator_block_t *
+wmem_strict_block_new(const size_t size)
{
- wmem_strict_allocator_t *allocator;
wmem_strict_allocator_block_t *block;
- allocator = (wmem_strict_allocator_t*) private_data;
-
block = g_new(wmem_strict_allocator_block_t, 1);
block->data_len = size;
block->leading_canary = g_malloc(block->data_len + (2 * WMEM_CANARY_SIZE));
block->real_data = block->leading_canary + WMEM_CANARY_SIZE;
block->trailing_canary = block->real_data + block->data_len;
- block->next = allocator->block_list;
- allocator->block_list = block;
memset(block->leading_canary, WMEM_CANARY_VALUE, WMEM_CANARY_SIZE);
memset(block->real_data, WMEM_PREFILL, block->data_len);
memset(block->trailing_canary, WMEM_CANARY_VALUE, WMEM_CANARY_SIZE);
+
+ return block;
+}
+
+/*
+ * public API functions
+ */
+static void *
+wmem_strict_alloc(void *private_data, const size_t size)
+{
+ wmem_strict_allocator_t *allocator;
+ wmem_strict_allocator_block_t *block;
+
+ allocator = (wmem_strict_allocator_t*) private_data;
+
+ block = wmem_strict_block_new(size);
+
+ /* we store a pointer to our header, keyed by a pointer to the actual
+ * block we return to the user */
+ g_hash_table_insert(allocator->block_table, block->real_data, block);
return block->real_data;
}
static void
-wmem_strict_real_check_canaries(wmem_strict_allocator_t *allocator)
+wmem_strict_free(void *private_data, void *ptr)
{
- guint i;
+ wmem_strict_allocator_t *allocator;
wmem_strict_allocator_block_t *block;
+
+ allocator = (wmem_strict_allocator_t*) private_data;
+
+ block = g_hash_table_lookup(allocator->block_table, ptr);
+
+ g_assert(block);
+
+ wmem_strict_block_check_canaries(block);
+
+ g_hash_table_remove(allocator->block_table, ptr);
+}
+
+static void *
+wmem_strict_realloc(void *private_data, void *ptr, const size_t size)
+{
+ gsize copy_len;
+ wmem_strict_allocator_t *allocator;
+ wmem_strict_allocator_block_t *block, *newblock;
+
+ allocator = (wmem_strict_allocator_t*) private_data;
- block = allocator->block_list;
+ /* retrieve and check the old block */
+ block = g_hash_table_lookup(allocator->block_table, ptr);
+ g_assert(block);
+ wmem_strict_block_check_canaries(block);
+
+ /* create a new block */
+ newblock = wmem_strict_block_new(size);
- while (block) {
- for (i=0; i<WMEM_CANARY_SIZE; i++) {
- g_assert(block->leading_canary[i] == WMEM_CANARY_VALUE);
- g_assert(block->trailing_canary[i] == WMEM_CANARY_VALUE);
- }
- block = block->next;
+ /* copy from the old block to the new */
+ if (block->data_len > newblock->data_len) {
+ copy_len = newblock->data_len;
+ }
+ else {
+ copy_len = block->data_len;
}
+
+ memcpy(newblock->real_data, block->real_data, copy_len);
+
+ /* update the hash table */
+ g_hash_table_remove(allocator->block_table, ptr);
+ g_hash_table_insert(allocator->block_table, newblock->real_data, newblock);
+
+ return newblock->real_data;
}
void
wmem_strict_check_canaries(wmem_allocator_t *allocator)
{
- /* XXX: Should this be a g_assert() instead? This is more of a general API
- * issue - should allocator-specific functions be safe to call with an
- * allocator of the wrong type or not? And how should they interact with the
- * WIRESHARK_DEBUG_WMEM_OVERRIDE environment variable? */
+ wmem_strict_allocator_t *private_allocator;
+
if (allocator->type != WMEM_ALLOCATOR_STRICT) {
return;
}
+
+ private_allocator = (wmem_strict_allocator_t*) allocator->private_data;
- wmem_strict_real_check_canaries(allocator->private_data);
+ g_hash_table_foreach(private_allocator->block_table,
+ &wmem_strict_ghash_check_canaries, NULL);
}
static void
wmem_strict_free_all(void *private_data)
{
wmem_strict_allocator_t *allocator;
- wmem_strict_allocator_block_t *block, *tmp;
allocator = (wmem_strict_allocator_t*) private_data;
- wmem_strict_real_check_canaries(allocator);
-
- block = allocator->block_list;
-
- while (block) {
- memset(block->real_data, WMEM_POSTFILL, block->data_len);
-
- g_free(block->leading_canary);
+ g_hash_table_foreach(allocator->block_table,
+ &wmem_strict_ghash_check_canaries, NULL);
- tmp = block;
- block = block->next;
- g_free(tmp);
- }
+ g_hash_table_remove_all(allocator->block_table);
+}
- allocator->block_list = NULL;
+static void
+wmem_strict_gc(void *private_data _U_)
+{
+ /* We don't really have anything to garbage-collect, but it might be worth
+ * checking our canaries at this point? */
}
static void
wmem_strict_allocator_destroy(wmem_allocator_t *allocator)
{
- g_free(allocator->private_data);
+ wmem_strict_allocator_t *private_allocator;
+
+ private_allocator = (wmem_strict_allocator_t*) allocator->private_data;
+
+ g_hash_table_destroy(private_allocator->block_table);
+ g_free(private_allocator);
g_free(allocator);
}
@@ -155,17 +242,19 @@ wmem_strict_allocator_new(void)
allocator = g_new(wmem_allocator_t, 1);
strict_allocator = g_new(wmem_strict_allocator_t, 1);
- allocator->alloc = &wmem_strict_alloc;
- allocator->free_all = &wmem_strict_free_all;
- allocator->destroy = &wmem_strict_allocator_destroy;
- allocator->private_data = (void*) strict_allocator;
+ allocator->alloc = &wmem_strict_alloc;
+ allocator->realloc = &wmem_strict_realloc;
+ allocator->free = &wmem_strict_free;
- /* TODO */
- allocator->realloc = NULL;
- allocator->free = NULL;
- allocator->gc = NULL;
+ allocator->free_all = &wmem_strict_free_all;
+ allocator->gc = &wmem_strict_gc;
+ allocator->destroy = &wmem_strict_allocator_destroy;
+
+ allocator->private_data = (void*) strict_allocator;
- strict_allocator->block_list = NULL;
+ strict_allocator->block_table = g_hash_table_new_full(
+ &g_direct_hash, &g_direct_equal,
+ NULL, &wmem_strict_ghash_block_free);
return allocator;
}