From 9b617755d27c47b799449df28595f23c8d5e1842 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 25 Jun 2020 17:18:21 -0400 Subject: [PATCH] lib/os/heap: code cleanup This makes the code cleaner wrt bucket_idx() usage on chunks for which solo_free_header() is true. In such case the bucket_idx() computation is useless, and potentially undefined anyway. In the same vain, move the clearing of the used flag out of free_chunks() as only one of its callers actually needs that. Makes free_chunks singular as there is only one chunk (potentially spanning multiple chunk units) to free. Also some cosmetic changes for better code uniformity. No functional changes. Signed-off-by: Nicolas Pitre --- lib/os/heap.c | 63 ++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/lib/os/heap.c b/lib/os/heap.c index 62e760c597d..3d12a7ff953 100644 --- a/lib/os/heap.c +++ b/lib/os/heap.c @@ -27,13 +27,8 @@ static inline bool solo_free_header(struct z_heap *h, chunkid_t c) && chunk_size(h, c) == 1); } -static void free_list_remove(struct z_heap *h, int bidx, - chunkid_t c) +static void free_list_remove_bidx(struct z_heap *h, chunkid_t c, int bidx) { - if (solo_free_header(h, c)) { - return; - } - struct z_heap_bucket *b = &h->buckets[bidx]; CHECK(!chunk_used(h, c)); @@ -54,27 +49,31 @@ static void free_list_remove(struct z_heap *h, int bidx, } } -static void free_list_add(struct z_heap *h, chunkid_t c) +static void free_list_remove(struct z_heap *h, chunkid_t c) { - if (solo_free_header(h, c)) { - return; + if (!solo_free_header(h, c)) { + int bidx = bucket_idx(h, chunk_size(h, c)); + free_list_remove_bidx(h, c, bidx); } +} - int bi = bucket_idx(h, chunk_size(h, c)); +static void free_list_add_bidx(struct z_heap *h, chunkid_t c, int bidx) +{ + struct z_heap_bucket *b = &h->buckets[bidx]; - if (h->buckets[bi].next == 0) { - CHECK((h->avail_buckets & (1 << bi)) == 0); + if (b->next == 0) { + CHECK((h->avail_buckets & (1 << bidx)) == 0); /* Empty list, first item */ - h->avail_buckets |= (1 << bi); - h->buckets[bi].next = c; + h->avail_buckets |= (1 << bidx); + b->next = c; set_prev_free_chunk(h, c, c); set_next_free_chunk(h, c, c); } else { - CHECK(h->avail_buckets & (1 << bi)); + CHECK(h->avail_buckets & (1 << bidx)); /* Insert before (!) the "next" pointer */ - chunkid_t second = h->buckets[bi].next; + chunkid_t second = b->next; chunkid_t first = prev_free_chunk(h, second); set_prev_free_chunk(h, c, first); @@ -84,6 +83,14 @@ static void free_list_add(struct z_heap *h, chunkid_t c) } } +static void free_list_add(struct z_heap *h, chunkid_t c) +{ + if (!solo_free_header(h, c)) { + int bidx = bucket_idx(h, chunk_size(h, c)); + free_list_add_bidx(h, c, bidx); + } +} + /* Splits a chunk "lc" into a left chunk and a right chunk at "rc". * Leaves both chunks marked "free" */ @@ -116,12 +123,11 @@ static void merge_chunks(struct z_heap *h, chunkid_t lc, chunkid_t rc) */ static chunkid_t split_alloc(struct z_heap *h, int bidx, size_t sz) { - CHECK(h->buckets[bidx].next != 0 - && sz <= chunk_size(h, h->buckets[bidx].next)); - chunkid_t c = h->buckets[bidx].next; - free_list_remove(h, bidx, c); + CHECK(c != 0 && sz <= chunk_size(h, c)); + + free_list_remove_bidx(h, c, bidx); /* Split off remainder if it's usefully large */ if ((chunk_size(h, c) - sz) >= (big_heap(h) ? 2 : 1)) { @@ -133,23 +139,17 @@ static chunkid_t split_alloc(struct z_heap *h, int bidx, size_t sz) return c; } -static void free_chunks(struct z_heap *h, chunkid_t c) +static void free_chunk(struct z_heap *h, chunkid_t c) { - set_chunk_used(h, c, false); - /* Merge with free right chunk? */ if (!chunk_used(h, right_chunk(h, c))) { - int bi = bucket_idx(h, chunk_size(h, right_chunk(h, c))); - - free_list_remove(h, bi, right_chunk(h, c)); + free_list_remove(h, right_chunk(h, c)); merge_chunks(h, c, right_chunk(h, c)); } /* Merge with free left chunk? */ if (!chunk_used(h, left_chunk(h, c))) { - int bi = bucket_idx(h, chunk_size(h, left_chunk(h, c))); - - free_list_remove(h, bi, left_chunk(h, c)); + free_list_remove(h, left_chunk(h, c)); merge_chunks(h, left_chunk(h, c), c); c = left_chunk(h, c); } @@ -187,7 +187,8 @@ void sys_heap_free(struct sys_heap *heap, void *mem) "corrupted heap bounds (buffer overflow?) for memory at %p", mem); - free_chunks(h, c); + set_chunk_used(h, c, false); + free_chunk(h, c); } static chunkid_t alloc_chunks(struct z_heap *h, size_t sz) @@ -297,7 +298,7 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes) if (alloc_sz < chunk_size(h, c)) { split_chunks(h, c, c + alloc_sz); set_chunk_used(h, c, true); - free_chunks(h, c + alloc_sz); + free_chunk(h, c + alloc_sz); } else { set_chunk_used(h, c, true); }