summaryrefslogtreecommitdiff
path: root/epan/wmem/wmem_allocator_block.c
diff options
context:
space:
mode:
authorEvan Huus <eapache@gmail.com>2013-03-24 12:53:22 +0000
committerEvan Huus <eapache@gmail.com>2013-03-24 12:53:22 +0000
commitd30dbcbf9e4a8f8621d3dd693e95c2d6b251ec67 (patch)
tree90235ecff2ca4998f79de3e68cc8833169e55b77 /epan/wmem/wmem_allocator_block.c
parentbd61beffaaf7b94d6077e487f227145ab656d642 (diff)
downloadwireshark-d30dbcbf9e4a8f8621d3dd693e95c2d6b251ec67.tar.gz
Fix a few small bugs in the block allocator and add some more assertions to it
that run during normal usage. Simplify, expand and enable the test coverage, since what's there now passes. svn path=/trunk/; revision=48522
Diffstat (limited to 'epan/wmem/wmem_allocator_block.c')
-rw-r--r--epan/wmem/wmem_allocator_block.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/epan/wmem/wmem_allocator_block.c b/epan/wmem/wmem_allocator_block.c
index e4bdae553a..e49503534d 100644
--- a/epan/wmem/wmem_allocator_block.c
+++ b/epan/wmem/wmem_allocator_block.c
@@ -352,13 +352,13 @@ wmem_block_add_to_free_list(wmem_block_allocator_t *allocator,
{
g_assert(!chunk->used);
+ if (WMEM_CHUNK_DATA_LEN(chunk) >= sizeof(wmem_block_free_t)) {
+ /* it's still big enough to store the struct, so check the flag */
+ g_assert(! WMEM_GET_FREE(chunk)->in_free_list);
+ }
+
if (chunk->len < WMEM_RECLAIM_LEN) {
/* it's not big enough to claim */
- if (WMEM_CHUNK_DATA_LEN(chunk) >= sizeof(wmem_block_free_t)) {
- /* it's still big enough to store the struct, so set the flag
- * so we know in future it wasn't added */
- WMEM_GET_FREE(chunk)->in_free_list = FALSE;
- }
return;
}
@@ -390,10 +390,12 @@ wmem_block_merge_free(wmem_block_allocator_t *allocator,
if (tmp && !tmp->used) {
/* Remove it from the free list since we're merging it, then add its
- * length to our length since the two free chunks are now one.
+ * length to our length since the two free chunks are now one. Also
+ * update our last flag, since we may now be last if tmp was.
* Our 'chunk' pointer is still the master header. */
wmem_block_remove_from_free_list(allocator, tmp);
chunk->len += tmp->len;
+ chunk->last = tmp->last;
}
/* check the chunk to our left */
@@ -406,8 +408,10 @@ wmem_block_merge_free(wmem_block_allocator_t *allocator,
wmem_block_remove_from_free_list(allocator, tmp);
/* Add our length to its length since the two free chunks
- * are now one. */
+ * are now one. Also update its last flag, since it may now be the
+ * last chunk in the block. */
tmp->len += chunk->len;
+ tmp->last = chunk->last;
/* The chunk pointer passed in is no longer valid, it's been merged to
* its left, so use the chunk to our left */
@@ -420,6 +424,13 @@ wmem_block_merge_free(wmem_block_allocator_t *allocator,
tmp->prev = chunk->len;
}
+ /* Chunk can be pointing to any of three possible places after the merge,
+ * and we don't know what leftover free_list values they might have, so
+ * reset the in_free_list flag to FALSE if we can to avoid confusion. */
+ if (WMEM_CHUNK_DATA_LEN(chunk) >= sizeof(wmem_block_free_t)) {
+ WMEM_GET_FREE(chunk)->in_free_list = FALSE;
+ }
+
return chunk;
}
@@ -587,7 +598,11 @@ wmem_block_split_used_chunk(wmem_block_allocator_t *allocator,
}
/* merge it to its right if possible (it can't be merged left, obviously) */
- wmem_block_merge_free(allocator, extra);
+ chunk = wmem_block_merge_free(allocator, extra);
+
+ /* assert that chunk == extra; if not then it was merged left which should
+ * be impossible! */
+ g_assert(chunk == extra);
/* add it to the free list */
wmem_block_add_to_free_list(allocator, extra);
@@ -700,7 +715,7 @@ wmem_block_free(void *private_data, void *ptr)
/* merge it with any other free chunks adjacent to it, so that contiguous
* free space doesn't get fragmented */
- wmem_block_merge_free(allocator, chunk);
+ chunk = wmem_block_merge_free(allocator, chunk);
/* Add it to the free list. If it isn't big enough, this is a no-op */
wmem_block_add_to_free_list(allocator, chunk);