lib/os/heap: rename struct z_heap.len to struct z_heap.end_chunk
The end marker chunk was represented by the len field of struct z_heap. It is now renamed to end_chunk to make it more obvious what it is. And while at it... Given that it is used in size_too_big() to cap the allocation size already, we no longer need to test the bucket index against the biggest index possible derived from end_chunk in alloc_chunk(). The corresponding bucket_idx() call is relatively expensive on some architectures so avoiding it (turning it into a CHECK() instead) is a good thing. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
e8910f629d
commit
a54e101a1e
|
@ -19,7 +19,7 @@
|
|||
|
||||
static size_t max_chunkid(struct z_heap *h)
|
||||
{
|
||||
return h->len - min_chunk_size(h);
|
||||
return h->end_chunk - min_chunk_size(h);
|
||||
}
|
||||
|
||||
#define VALIDATE(cond) do { if (!(cond)) { return false; } } while (0)
|
||||
|
@ -28,14 +28,14 @@ static bool in_bounds(struct z_heap *h, chunkid_t c)
|
|||
{
|
||||
VALIDATE(c >= right_chunk(h, 0));
|
||||
VALIDATE(c <= max_chunkid(h));
|
||||
VALIDATE(chunk_size(h, c) < h->len);
|
||||
VALIDATE(chunk_size(h, c) < h->end_chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool valid_chunk(struct z_heap *h, chunkid_t c)
|
||||
{
|
||||
VALIDATE(chunk_size(h, c) > 0);
|
||||
VALIDATE(c + chunk_size(h, c) <= h->len);
|
||||
VALIDATE(c + chunk_size(h, c) <= h->end_chunk);
|
||||
VALIDATE(in_bounds(h, c));
|
||||
VALIDATE(right_chunk(h, left_chunk(h, c)) == c);
|
||||
VALIDATE(left_chunk(h, right_chunk(h, c)) == c);
|
||||
|
@ -85,7 +85,7 @@ bool sys_heap_validate(struct sys_heap *heap)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (c != h->len) {
|
||||
if (c != h->end_chunk) {
|
||||
return false; /* Should have exactly consumed the buffer */
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ bool sys_heap_validate(struct sys_heap *heap)
|
|||
* should be correct, and all chunk entries should point into
|
||||
* valid unused chunks. Mark those chunks USED, temporarily.
|
||||
*/
|
||||
for (int b = 0; b <= bucket_idx(h, h->len); b++) {
|
||||
for (int b = 0; b <= bucket_idx(h, h->end_chunk); b++) {
|
||||
chunkid_t c0 = h->buckets[b].next;
|
||||
uint32_t n = 0;
|
||||
|
||||
|
@ -137,7 +137,7 @@ bool sys_heap_validate(struct sys_heap *heap)
|
|||
|
||||
set_chunk_used(h, c, solo_free_header(h, c));
|
||||
}
|
||||
if (c != h->len) {
|
||||
if (c != h->end_chunk) {
|
||||
return false; /* Should have exactly consumed the buffer */
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ bool sys_heap_validate(struct sys_heap *heap)
|
|||
* pass caught all the blocks and that they now show UNUSED.
|
||||
* Mark them USED.
|
||||
*/
|
||||
for (int b = 0; b <= bucket_idx(h, h->len); b++) {
|
||||
for (int b = 0; b <= bucket_idx(h, h->end_chunk); b++) {
|
||||
chunkid_t c0 = h->buckets[b].next;
|
||||
int n = 0;
|
||||
|
||||
|
@ -318,11 +318,11 @@ void sys_heap_stress(void *(*alloc)(void *arg, size_t bytes),
|
|||
*/
|
||||
void heap_print_info(struct z_heap *h, bool dump_chunks)
|
||||
{
|
||||
int i, nb_buckets = bucket_idx(h, h->len) + 1;
|
||||
int i, nb_buckets = bucket_idx(h, h->end_chunk) + 1;
|
||||
size_t free_bytes, allocated_bytes, total, overhead;
|
||||
|
||||
printk("Heap at %p contains %d units in %d buckets\n\n",
|
||||
chunk_buf(h), h->len, nb_buckets);
|
||||
chunk_buf(h), h->end_chunk, nb_buckets);
|
||||
|
||||
printk(" bucket# min units total largest largest\n"
|
||||
" threshold chunks (units) (bytes)\n"
|
||||
|
@ -352,7 +352,7 @@ void heap_print_info(struct z_heap *h, bool dump_chunks)
|
|||
}
|
||||
free_bytes = allocated_bytes = 0;
|
||||
for (chunkid_t c = 0; ; c = right_chunk(h, c)) {
|
||||
if (c == 0 || c == h->len) {
|
||||
if (c == 0 || c == h->end_chunk) {
|
||||
/* those are always allocated for internal purposes */
|
||||
} else if (chunk_used(h, c)) {
|
||||
allocated_bytes += chunk_size(h, c) * CHUNK_UNIT
|
||||
|
@ -371,16 +371,13 @@ void heap_print_info(struct z_heap *h, bool dump_chunks)
|
|||
left_chunk(h, c),
|
||||
right_chunk(h, c));
|
||||
}
|
||||
if (c == h->len) {
|
||||
if (c == h->end_chunk) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The final chunk at h->len is just a header serving as a end
|
||||
* marker. It is part of the overhead.
|
||||
*/
|
||||
total = h->len * CHUNK_UNIT + chunk_header_bytes(h);
|
||||
/* The end marker chunk has a header. It is part of the overhead. */
|
||||
total = h->end_chunk * CHUNK_UNIT + chunk_header_bytes(h);
|
||||
overhead = total - free_bytes - allocated_bytes;
|
||||
printk("\n%zd free bytes, %zd allocated bytes, overhead = %zd bytes (%zd.%zd%%)\n",
|
||||
free_bytes, allocated_bytes, overhead,
|
||||
|
|
|
@ -172,9 +172,7 @@ static chunkid_t alloc_chunk(struct z_heap *h, size_t sz)
|
|||
int bi = bucket_idx(h, sz);
|
||||
struct z_heap_bucket *b = &h->buckets[bi];
|
||||
|
||||
if (bi > bucket_idx(h, h->len)) {
|
||||
return 0;
|
||||
}
|
||||
CHECK(bi <= bucket_idx(h, h->end_chunk));
|
||||
|
||||
/* First try a bounded count of items from the minimal bucket
|
||||
* size. These may not fit, trying (e.g.) three means that
|
||||
|
@ -383,7 +381,7 @@ void sys_heap_init(struct sys_heap *heap, void *mem, size_t bytes)
|
|||
/* Must fit in a 31 bit count of HUNK_UNIT */
|
||||
__ASSERT(bytes / CHUNK_UNIT <= 0x7fffffffU, "heap size is too big");
|
||||
|
||||
/* Reserve the final marker chunk's header */
|
||||
/* Reserve the end marker chunk's header */
|
||||
__ASSERT(bytes > heap_footer_bytes(bytes), "heap size is too small");
|
||||
bytes -= heap_footer_bytes(bytes);
|
||||
|
||||
|
@ -398,7 +396,7 @@ void sys_heap_init(struct sys_heap *heap, void *mem, size_t bytes)
|
|||
struct z_heap *h = (struct z_heap *)addr;
|
||||
heap->heap = h;
|
||||
h->chunk0_hdr_area = 0;
|
||||
h->len = buf_sz;
|
||||
h->end_chunk = buf_sz;
|
||||
h->avail_buckets = 0;
|
||||
|
||||
int nb_buckets = bucket_idx(h, buf_sz) + 1;
|
||||
|
|
|
@ -64,7 +64,7 @@ struct z_heap_bucket {
|
|||
|
||||
struct z_heap {
|
||||
uint64_t chunk0_hdr_area; /* matches the largest header */
|
||||
uint32_t len;
|
||||
chunkid_t end_chunk;
|
||||
uint32_t avail_buckets;
|
||||
struct z_heap_bucket buckets[0];
|
||||
};
|
||||
|
@ -81,7 +81,7 @@ static inline bool big_heap_bytes(size_t bytes)
|
|||
|
||||
static inline bool big_heap(struct z_heap *h)
|
||||
{
|
||||
return big_heap_chunks(h->len);
|
||||
return big_heap_chunks(h->end_chunk);
|
||||
}
|
||||
|
||||
static inline chunk_unit_t *chunk_buf(struct z_heap *h)
|
||||
|
@ -106,7 +106,7 @@ static inline size_t chunk_field(struct z_heap *h, chunkid_t c,
|
|||
static inline void chunk_set(struct z_heap *h, chunkid_t c,
|
||||
enum chunk_fields f, chunkid_t val)
|
||||
{
|
||||
CHECK(c <= h->len);
|
||||
CHECK(c <= h->end_chunk);
|
||||
|
||||
chunk_unit_t *buf = chunk_buf(h);
|
||||
void *cmem = &buf[c];
|
||||
|
@ -239,9 +239,8 @@ static inline bool size_too_big(struct z_heap *h, size_t bytes)
|
|||
/*
|
||||
* Quick check to bail out early if size is too big.
|
||||
* Also guards against potential arithmetic overflows elsewhere.
|
||||
* There is a minimum of one chunk always in use by the heap header.
|
||||
*/
|
||||
return (bytes / CHUNK_UNIT) >= h->len;
|
||||
return (bytes / CHUNK_UNIT) >= h->end_chunk;
|
||||
}
|
||||
|
||||
/* For debugging */
|
||||
|
|
Loading…
Reference in a new issue