File Coverage

src/mds_arena.c
Criterion Covered Total %
statement 76 76 100.0
branch 22 26 84.6
condition n/a
subroutine n/a
pod n/a
total 98 102 96.0


line stmt bran cond sub pod time code
1             #include "mds_arena.h"
2             #include
3             #include
4              
5 2228           static mds_arena_page* page_new(size_t cap) {
6 2228           mds_arena_page* p = (mds_arena_page*)malloc(sizeof(mds_arena_page) + cap);
7 2228 50         if (!p) return NULL;
8 2228           p->next = NULL;
9 2228           p->used = 0;
10 2228           p->cap = cap;
11 2228           return p;
12             }
13              
14 2226           void mds_arena_init(mds_arena* a) {
15 2226           a->head = NULL;
16 2226           a->big = NULL;
17 2226           a->total_alloc = 0;
18 2226           a->page_count = 0;
19 2226           a->big_count = 0;
20 2226           a->big_bytes = 0;
21 2226           }
22              
23 11761           void* mds_arena_alloc(mds_arena* a, size_t n) {
24             /* round up to alignment */
25 11761           size_t aligned = (n + (MDS_ARENA_ALIGN - 1)) & ~(size_t)(MDS_ARENA_ALIGN - 1);
26             void* out;
27 11761           a->total_alloc += aligned;
28              
29 11761 100         if (aligned > MDS_ARENA_BIG) {
30             /* oversize: dedicated page, prepended to `big` list */
31 2           mds_arena_page* p = page_new(aligned + MDS_ARENA_ALIGN);
32             uintptr_t base;
33             size_t pad;
34 2 50         if (!p) return NULL;
35             /* align the start of `data` */
36 2           base = (uintptr_t)p->data;
37 2           pad = (MDS_ARENA_ALIGN - (base & (MDS_ARENA_ALIGN - 1))) & (MDS_ARENA_ALIGN - 1);
38 2           p->used = pad + aligned;
39 2           p->next = a->big;
40 2           a->big = p;
41 2           a->big_count++;
42 2           a->big_bytes += aligned;
43 2           return p->data + pad;
44             }
45              
46 11759 100         if (!a->head || a->head->used + aligned > a->head->cap) {
    100          
47 2226           mds_arena_page* p = page_new(MDS_ARENA_PAGE);
48             uintptr_t base;
49             size_t pad;
50 2226 50         if (!p) return NULL;
51             /* prime `used` so the first returned pointer is aligned */
52 2226           base = (uintptr_t)p->data;
53 2226           pad = (MDS_ARENA_ALIGN - (base & (MDS_ARENA_ALIGN - 1))) & (MDS_ARENA_ALIGN - 1);
54 2226           p->used = pad;
55 2226           p->next = a->head;
56 2226           a->head = p;
57 2226           a->page_count++;
58             }
59 11759           out = a->head->data + a->head->used;
60 11759           a->head->used += aligned;
61 11759           return out;
62             }
63              
64 222           void mds_arena_reset(mds_arena* a) {
65             mds_arena_page* b;
66             /* free everything except the head page (kept warm); reset head usage */
67 222 50         if (a->head) {
68 222           mds_arena_page* p = a->head->next;
69             uintptr_t base;
70             size_t pad;
71 225 100         while (p) { mds_arena_page* n = p->next; free(p); p = n; }
72 222           a->head->next = NULL;
73             /* re-prime to alignment padding so next alloc returns aligned ptr */
74 222           base = (uintptr_t)a->head->data;
75 222           pad = (MDS_ARENA_ALIGN - (base & (MDS_ARENA_ALIGN - 1))) & (MDS_ARENA_ALIGN - 1);
76 222           a->head->used = pad;
77             }
78 222           b = a->big;
79 223 100         while (b) { mds_arena_page* n = b->next; free(b); b = n; }
80 222           a->big = NULL;
81 222           a->total_alloc = 0;
82             /* keep `page_count` reflecting the warm page that remains. */
83 222           a->page_count = a->head ? 1 : 0;
84 222           a->big_count = 0;
85 222           a->big_bytes = 0;
86 222           }
87              
88 2226           void mds_arena_free(mds_arena* a) {
89 2226           mds_arena_page* p = a->head;
90 4449 100         while (p) { mds_arena_page* n = p->next; free(p); p = n; }
91 2226           p = a->big;
92 2227 100         while (p) { mds_arena_page* n = p->next; free(p); p = n; }
93 2226           a->head = a->big = NULL;
94 2226           a->total_alloc = 0;
95 2226           a->page_count = 0;
96 2226           a->big_count = 0;
97 2226           a->big_bytes = 0;
98 2226           }
99              
100 2443           void mds_arena_snapshot(const mds_arena* a, mds_arena_profile* out) {
101 2443           out->total_alloc = a->total_alloc;
102 2443           out->page_count = a->page_count;
103 2443           out->big_count = a->big_count;
104 2443           out->big_bytes = a->big_bytes;
105 2443 100         out->head_used_last = a->head ? a->head->used : 0;
106 2443 100         out->head_cap_last = a->head ? a->head->cap : 0;
107 2443           }