Skip to content

Commit b1eefc0

Browse files
Nicolas Pitrenashif
authored andcommitted
lib/os/heap: straighten up our type usage
The size_t usage, especially in struct z_heap_bucket made the heap header almost 2x bigger than it needs to be on 64-bit systems. This prompted me to clean up our type usage to make the code more efficient and easier to understand. From now on: - chunkid_t is for absolute chunk position measured in chunk units - chunksz_t is for chunk sizes measured in chunk units - size_t is for buffer sizes measured in bytes Signed-off-by: Nicolas Pitre <[email protected]>
1 parent e919bb2 commit b1eefc0

File tree

3 files changed

+43
-40
lines changed

3 files changed

+43
-40
lines changed

lib/os/heap-validate.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* running one and corrupting it. YMMV.
1818
*/
1919

20-
static size_t max_chunkid(struct z_heap *h)
20+
static chunkid_t max_chunkid(struct z_heap *h)
2121
{
2222
return h->end_chunk - min_chunk_size(h);
2323
}
@@ -329,7 +329,7 @@ void heap_print_info(struct z_heap *h, bool dump_chunks)
329329
" -----------------------------------------------------------\n");
330330
for (i = 0; i < nb_buckets; i++) {
331331
chunkid_t first = h->buckets[i].next;
332-
size_t largest = 0;
332+
chunksz_t largest = 0;
333333
int count = 0;
334334

335335
if (first) {
@@ -341,7 +341,7 @@ void heap_print_info(struct z_heap *h, bool dump_chunks)
341341
} while (curr != first);
342342
}
343343
if (count) {
344-
printk("%9d %12d %12d %12zd %12zd\n",
344+
printk("%9d %12d %12d %12d %12zd\n",
345345
i, (1 << i) - 1 + min_chunk_size(h), count,
346346
largest, chunksz_to_bytes(h, largest));
347347
}
@@ -360,7 +360,7 @@ void heap_print_info(struct z_heap *h, bool dump_chunks)
360360
free_bytes += chunksz_to_bytes(h, chunk_size(h, c));
361361
}
362362
if (dump_chunks) {
363-
printk("chunk %4zd: [%c] size=%-4zd left=%-4zd right=%zd\n",
363+
printk("chunk %4d: [%c] size=%-4d left=%-4d right=%d\n",
364364
c,
365365
chunk_used(h, c) ? '*'
366366
: solo_free_header(h, c) ? '.'

lib/os/heap.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ static void *chunk_mem(struct z_heap *h, chunkid_t c)
1313
chunk_unit_t *buf = chunk_buf(h);
1414
uint8_t *ret = ((uint8_t *)&buf[c]) + chunk_header_bytes(h);
1515

16-
CHECK(!(((size_t)ret) & (big_heap(h) ? 7 : 3)));
16+
CHECK(!(((uintptr_t)ret) & (big_heap(h) ? 7 : 3)));
1717

1818
return ret;
1919
}
@@ -90,9 +90,9 @@ static void split_chunks(struct z_heap *h, chunkid_t lc, chunkid_t rc)
9090
CHECK(rc > lc);
9191
CHECK(rc - lc < chunk_size(h, lc));
9292

93-
size_t sz0 = chunk_size(h, lc);
94-
size_t lsz = rc - lc;
95-
size_t rsz = sz0 - lsz;
93+
chunksz_t sz0 = chunk_size(h, lc);
94+
chunksz_t lsz = rc - lc;
95+
chunksz_t rsz = sz0 - lsz;
9696

9797
set_chunk_size(h, lc, lsz);
9898
set_chunk_size(h, rc, rsz);
@@ -103,7 +103,7 @@ static void split_chunks(struct z_heap *h, chunkid_t lc, chunkid_t rc)
103103
/* Does not modify free list */
104104
static void merge_chunks(struct z_heap *h, chunkid_t lc, chunkid_t rc)
105105
{
106-
size_t newsz = chunk_size(h, lc) + chunk_size(h, rc);
106+
chunksz_t newsz = chunk_size(h, lc) + chunk_size(h, rc);
107107

108108
set_chunk_size(h, lc, newsz);
109109
set_left_chunk_size(h, right_chunk(h, rc), newsz);
@@ -167,7 +167,7 @@ void sys_heap_free(struct sys_heap *heap, void *mem)
167167
free_chunk(h, c);
168168
}
169169

170-
static chunkid_t alloc_chunk(struct z_heap *h, size_t sz)
170+
static chunkid_t alloc_chunk(struct z_heap *h, chunksz_t sz)
171171
{
172172
int bi = bucket_idx(h, sz);
173173
struct z_heap_bucket *b = &h->buckets[bi];
@@ -205,7 +205,7 @@ static chunkid_t alloc_chunk(struct z_heap *h, size_t sz)
205205
/* Otherwise pick the smallest non-empty bucket guaranteed to
206206
* fit and use that unconditionally.
207207
*/
208-
size_t bmask = h->avail_buckets & ~((1 << (bi + 1)) - 1);
208+
uint32_t bmask = h->avail_buckets & ~((1 << (bi + 1)) - 1);
209209

210210
if (bmask != 0U) {
211211
int minbucket = __builtin_ctz(bmask);
@@ -227,7 +227,7 @@ void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
227227
return NULL;
228228
}
229229

230-
size_t chunk_sz = bytes_to_chunksz(h, bytes);
230+
chunksz_t chunk_sz = bytes_to_chunksz(h, bytes);
231231
chunkid_t c = alloc_chunk(h, chunk_sz);
232232
if (c == 0U) {
233233
return NULL;
@@ -246,7 +246,7 @@ void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
246246
void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
247247
{
248248
struct z_heap *h = heap->heap;
249-
size_t padded_sz, gap, rewind;
249+
size_t gap, rewind;
250250

251251
/*
252252
* Split align and rewind values (if any).
@@ -277,7 +277,7 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
277277
* We over-allocate to account for alignment and then free
278278
* the extra allocations afterwards.
279279
*/
280-
padded_sz = bytes_to_chunksz(h, bytes + align - gap);
280+
chunksz_t padded_sz = bytes_to_chunksz(h, bytes + align - gap);
281281
chunkid_t c0 = alloc_chunk(h, padded_sz);
282282

283283
if (c0 == 0) {
@@ -333,7 +333,7 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
333333
chunkid_t c = mem_to_chunkid(h, ptr);
334334
chunkid_t rc = right_chunk(h, c);
335335
size_t align_gap = (uint8_t *)ptr - (uint8_t *)chunk_mem(h, c);
336-
size_t chunks_need = bytes_to_chunksz(h, bytes + align_gap);
336+
chunksz_t chunks_need = bytes_to_chunksz(h, bytes + align_gap);
337337

338338
if (align && ((uintptr_t)ptr & (align - 1))) {
339339
/* ptr is not sufficiently aligned */
@@ -387,39 +387,39 @@ void sys_heap_init(struct sys_heap *heap, void *mem, size_t bytes)
387387
/* Round the start up, the end down */
388388
uintptr_t addr = ROUND_UP(mem, CHUNK_UNIT);
389389
uintptr_t end = ROUND_DOWN((uint8_t *)mem + bytes, CHUNK_UNIT);
390-
size_t buf_sz = (end - addr) / CHUNK_UNIT;
390+
chunksz_t heap_sz = (end - addr) / CHUNK_UNIT;
391391

392392
CHECK(end > addr);
393-
__ASSERT(buf_sz > chunksz(sizeof(struct z_heap)), "heap size is too small");
393+
__ASSERT(heap_sz > chunksz(sizeof(struct z_heap)), "heap size is too small");
394394

395395
struct z_heap *h = (struct z_heap *)addr;
396396
heap->heap = h;
397-
h->chunk0_hdr_area = 0;
398-
h->end_chunk = buf_sz;
397+
h->end_chunk = heap_sz;
399398
h->avail_buckets = 0;
400399

401-
int nb_buckets = bucket_idx(h, buf_sz) + 1;
402-
size_t chunk0_size = chunksz(sizeof(struct z_heap) +
400+
int nb_buckets = bucket_idx(h, heap_sz) + 1;
401+
chunksz_t chunk0_size = chunksz(sizeof(struct z_heap) +
403402
nb_buckets * sizeof(struct z_heap_bucket));
404403

405-
__ASSERT(chunk0_size + min_chunk_size(h) < buf_sz, "heap size is too small");
404+
__ASSERT(chunk0_size + min_chunk_size(h) < heap_sz, "heap size is too small");
406405

407406
for (int i = 0; i < nb_buckets; i++) {
408407
h->buckets[i].next = 0;
409408
}
410409

411410
/* chunk containing our struct z_heap */
412411
set_chunk_size(h, 0, chunk0_size);
412+
set_left_chunk_size(h, 0, 0);
413413
set_chunk_used(h, 0, true);
414414

415415
/* chunk containing the free heap */
416-
set_chunk_size(h, chunk0_size, buf_sz - chunk0_size);
416+
set_chunk_size(h, chunk0_size, heap_sz - chunk0_size);
417417
set_left_chunk_size(h, chunk0_size, chunk0_size);
418418

419419
/* the end marker chunk */
420-
set_chunk_size(h, buf_sz, 0);
421-
set_left_chunk_size(h, buf_sz, buf_sz - chunk0_size);
422-
set_chunk_used(h, buf_sz, true);
420+
set_chunk_size(h, heap_sz, 0);
421+
set_left_chunk_size(h, heap_sz, heap_sz - chunk0_size);
422+
set_chunk_used(h, heap_sz, true);
423423

424424
free_list_add(h, chunk0_size);
425425
}

lib/os/heap.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,26 +50,29 @@
5050
* the following chunk at the top. This ordering allows for quick buffer
5151
* overflow detection by testing left_chunk(c + chunk_size(c)) == c.
5252
*/
53-
typedef size_t chunkid_t;
5453

5554
enum chunk_fields { LEFT_SIZE, SIZE_AND_USED, FREE_PREV, FREE_NEXT };
5655

5756
#define CHUNK_UNIT 8U
5857

5958
typedef struct { char bytes[CHUNK_UNIT]; } chunk_unit_t;
6059

60+
/* big_heap needs uint32_t, small_heap needs uint16_t */
61+
typedef uint32_t chunkid_t;
62+
typedef uint32_t chunksz_t;
63+
6164
struct z_heap_bucket {
6265
chunkid_t next;
6366
};
6467

6568
struct z_heap {
66-
uint64_t chunk0_hdr_area; /* matches the largest header */
69+
chunkid_t chunk0_hdr[2];
6770
chunkid_t end_chunk;
6871
uint32_t avail_buckets;
6972
struct z_heap_bucket buckets[0];
7073
};
7174

72-
static inline bool big_heap_chunks(size_t chunks)
75+
static inline bool big_heap_chunks(chunksz_t chunks)
7376
{
7477
return sizeof(void *) > 4U || chunks > 0x7fffU;
7578
}
@@ -90,8 +93,8 @@ static inline chunk_unit_t *chunk_buf(struct z_heap *h)
9093
return (chunk_unit_t *)h;
9194
}
9295

93-
static inline size_t chunk_field(struct z_heap *h, chunkid_t c,
94-
enum chunk_fields f)
96+
static inline chunkid_t chunk_field(struct z_heap *h, chunkid_t c,
97+
enum chunk_fields f)
9598
{
9699
chunk_unit_t *buf = chunk_buf(h);
97100
void *cmem = &buf[c];
@@ -125,7 +128,7 @@ static inline bool chunk_used(struct z_heap *h, chunkid_t c)
125128
return chunk_field(h, c, SIZE_AND_USED) & 1U;
126129
}
127130

128-
static inline size_t chunk_size(struct z_heap *h, chunkid_t c)
131+
static inline chunksz_t chunk_size(struct z_heap *h, chunkid_t c)
129132
{
130133
return chunk_field(h, c, SIZE_AND_USED) >> 1;
131134
}
@@ -155,7 +158,7 @@ static inline void set_chunk_used(struct z_heap *h, chunkid_t c, bool used)
155158
* when its size is modified, and potential set_chunk_used() is always
156159
* invoked after set_chunk_size().
157160
*/
158-
static inline void set_chunk_size(struct z_heap *h, chunkid_t c, size_t size)
161+
static inline void set_chunk_size(struct z_heap *h, chunkid_t c, chunksz_t size)
159162
{
160163
chunk_set(h, c, SIZE_AND_USED, size << 1);
161164
}
@@ -193,7 +196,7 @@ static inline chunkid_t right_chunk(struct z_heap *h, chunkid_t c)
193196
}
194197

195198
static inline void set_left_chunk_size(struct z_heap *h, chunkid_t c,
196-
size_t size)
199+
chunksz_t size)
197200
{
198201
chunk_set(h, c, LEFT_SIZE, size);
199202
}
@@ -213,29 +216,29 @@ static inline size_t heap_footer_bytes(size_t size)
213216
return big_heap_bytes(size) ? 8 : 4;
214217
}
215218

216-
static inline size_t chunksz(size_t bytes)
219+
static inline chunksz_t chunksz(size_t bytes)
217220
{
218221
return (bytes + CHUNK_UNIT - 1U) / CHUNK_UNIT;
219222
}
220223

221-
static inline size_t bytes_to_chunksz(struct z_heap *h, size_t bytes)
224+
static inline chunksz_t bytes_to_chunksz(struct z_heap *h, size_t bytes)
222225
{
223226
return chunksz(chunk_header_bytes(h) + bytes);
224227
}
225228

226-
static inline int min_chunk_size(struct z_heap *h)
229+
static inline chunksz_t min_chunk_size(struct z_heap *h)
227230
{
228231
return bytes_to_chunksz(h, 1);
229232
}
230233

231-
static inline size_t chunksz_to_bytes(struct z_heap *h, size_t chunksz)
234+
static inline size_t chunksz_to_bytes(struct z_heap *h, chunksz_t chunksz)
232235
{
233236
return chunksz * CHUNK_UNIT - chunk_header_bytes(h);
234237
}
235238

236-
static inline int bucket_idx(struct z_heap *h, size_t sz)
239+
static inline int bucket_idx(struct z_heap *h, chunksz_t sz)
237240
{
238-
size_t usable_sz = sz - min_chunk_size(h) + 1;
241+
unsigned int usable_sz = sz - min_chunk_size(h) + 1;
239242
return 31 - __builtin_clz(usable_sz);
240243
}
241244

0 commit comments

Comments
 (0)