Skip to content

Commit 6daa8ea

Browse files
authored
Merge pull request #14 from spaskalev/cpp_interop
cpp interop changes - drop _Bool, use portable popcount and highest_bit_position implementations
2 parents 582ef67 + 8298efd commit 6daa8ea

File tree

2 files changed

+105
-82
lines changed

2 files changed

+105
-82
lines changed

buddy_alloc.h

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#define BUDDY_ALLOC_H
1717

1818
#include <limits.h>
19-
#include <stdalign.h>
2019
#include <stddef.h>
2120
#include <stdint.h>
2221
#include <stdio.h>
@@ -41,10 +40,10 @@ struct buddy *buddy_embed(unsigned char *main, size_t memory_size);
4140
struct buddy *buddy_resize(struct buddy *buddy, size_t new_memory_size);
4241

4342
/* Tests if the allocation can be shrunk in half */
44-
_Bool buddy_can_shrink(struct buddy *buddy);
43+
unsigned int buddy_can_shrink(struct buddy *buddy);
4544

4645
/* Tests if the allocation is completely empty */
47-
_Bool buddy_is_empty(struct buddy *buddy);
46+
unsigned int buddy_is_empty(struct buddy *buddy);
4847

4948
/* Reports the arena size */
5049
size_t buddy_arena_size(struct buddy *buddy);
@@ -105,7 +104,7 @@ static size_t buddy_tree_sizeof(uint8_t order);
105104
static struct buddy_tree *buddy_tree_init(unsigned char *at, uint8_t order);
106105

107106
/* Indicates whether this is a valid position for the tree */
108-
static _Bool buddy_tree_valid(struct buddy_tree *t, buddy_tree_pos pos);
107+
static unsigned int buddy_tree_valid(struct buddy_tree *t, buddy_tree_pos pos);
109108

110109
/* Returns the order of the specified buddy allocation tree */
111110
static uint8_t buddy_tree_order(struct buddy_tree *t);
@@ -146,7 +145,7 @@ static size_t buddy_tree_index(buddy_tree_pos pos);
146145
static struct buddy_tree_interval buddy_tree_interval(struct buddy_tree *t, buddy_tree_pos pos);
147146

148147
/* Checks if one interval contains another */
149-
static _Bool buddy_tree_interval_contains(struct buddy_tree_interval outer,
148+
static unsigned int buddy_tree_interval_contains(struct buddy_tree_interval outer,
150149
struct buddy_tree_interval inner);
151150

152151
/*
@@ -166,10 +165,10 @@ static void buddy_tree_release(struct buddy_tree *t, buddy_tree_pos pos);
166165
static buddy_tree_pos buddy_tree_find_free(struct buddy_tree *t, uint8_t depth);
167166

168167
/* Tests if the incidated position is available for allocation */
169-
static _Bool buddy_tree_is_free(struct buddy_tree *t, buddy_tree_pos pos);
168+
static unsigned int buddy_tree_is_free(struct buddy_tree *t, buddy_tree_pos pos);
170169

171170
/* Tests if the tree can be shrank in half */
172-
static _Bool buddy_tree_can_shrink(struct buddy_tree *t);
171+
static unsigned int buddy_tree_can_shrink(struct buddy_tree *t);
173172

174173
/*
175174
* Debug functions
@@ -179,7 +178,7 @@ static _Bool buddy_tree_can_shrink(struct buddy_tree *t);
179178
static void buddy_tree_debug(FILE *stream, struct buddy_tree *t, buddy_tree_pos pos, size_t start_size);
180179

181180
/* Implementation defined */
182-
static _Bool buddy_tree_check_invariant(struct buddy_tree *t, buddy_tree_pos pos);
181+
static unsigned int buddy_tree_check_invariant(struct buddy_tree *t, buddy_tree_pos pos);
183182

184183
/*
185184
* A char-backed bitset implementation
@@ -197,7 +196,7 @@ static inline void bitset_set(unsigned char *bitset, size_t pos);
197196

198197
static inline void bitset_clear(unsigned char *bitset, size_t pos);
199198

200-
static inline _Bool bitset_test(const unsigned char *bitset, size_t pos);
199+
static inline unsigned int bitset_test(const unsigned char *bitset, size_t pos);
201200

202201
static void bitset_shift_left(unsigned char *bitset, size_t from_pos, size_t to_pos, size_t by);
203202

@@ -214,8 +213,11 @@ static void bitset_debug(FILE *stream, unsigned char *bitset, size_t length);
214213
Bits
215214
*/
216215

216+
/* Returns the number of set bits in the given byte */
217+
static unsigned int popcount_byte(unsigned char b);
218+
217219
/* Returns the index of the highest bit set (1-based) */
218-
static inline size_t highest_bit_position(size_t value);
220+
static size_t highest_bit_position(size_t value);
219221

220222
/* Returns the nearest larger or equal power of two */
221223
static inline size_t ceiling_power_of_two(size_t value);
@@ -235,12 +237,12 @@ struct buddy {
235237
unsigned char *main;
236238
ptrdiff_t main_offset;
237239
};
238-
_Bool relative_mode;
240+
unsigned int relative_mode;
239241
unsigned char buddy_tree[];
240242
};
241243

242244
struct buddy_embed_check {
243-
_Bool can_fit;
245+
unsigned int can_fit;
244246
size_t offset;
245247
size_t buddy_size;
246248
};
@@ -252,10 +254,10 @@ static void *address_for_position(struct buddy *buddy, buddy_tree_pos pos);
252254
static buddy_tree_pos position_for_address(struct buddy *buddy, const unsigned char *addr);
253255
static unsigned char *buddy_main(struct buddy *buddy);
254256
static struct buddy_tree *buddy_tree(struct buddy *buddy);
255-
static void buddy_toggle_virtual_slots(struct buddy *buddy, _Bool state);
257+
static void buddy_toggle_virtual_slots(struct buddy *buddy, unsigned int state);
256258
static struct buddy *buddy_resize_standard(struct buddy *buddy, size_t new_memory_size);
257259
static struct buddy *buddy_resize_embedded(struct buddy *buddy, size_t new_memory_size);
258-
static _Bool buddy_is_free(struct buddy *buddy, size_t from);
260+
static unsigned int buddy_is_free(struct buddy *buddy, size_t from);
259261
static struct buddy_embed_check buddy_embed_offset(size_t memory_size);
260262
static buddy_tree_pos deepest_position_for_offset(struct buddy *buddy, size_t offset);
261263

@@ -383,14 +385,14 @@ static struct buddy *buddy_resize_embedded(struct buddy *buddy, size_t new_memor
383385
return relocated;
384386
}
385387

386-
_Bool buddy_can_shrink(struct buddy *buddy) {
388+
unsigned int buddy_can_shrink(struct buddy *buddy) {
387389
if (buddy == NULL) {
388390
return 0;
389391
}
390392
return buddy_is_free(buddy, buddy->memory_size / 2);
391393
}
392394

393-
_Bool buddy_is_empty(struct buddy *buddy) {
395+
unsigned int buddy_is_empty(struct buddy *buddy) {
394396
if (buddy == NULL) {
395397
return 1;
396398
}
@@ -482,7 +484,7 @@ void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size) {
482484
}
483485

484486
/* Find the position tracking this address */
485-
buddy_tree_pos origin = position_for_address(buddy, ptr);
487+
buddy_tree_pos origin = position_for_address(buddy, (unsigned char *) ptr);
486488
if (!origin) {
487489
return NULL;
488490
}
@@ -612,7 +614,7 @@ static unsigned char *buddy_main(struct buddy *buddy) {
612614
return buddy->main;
613615
}
614616

615-
static void buddy_toggle_virtual_slots(struct buddy *buddy, _Bool state) {
617+
static void buddy_toggle_virtual_slots(struct buddy *buddy, unsigned int state) {
616618
size_t memory_size = buddy->memory_size;
617619
/* Mask/unmask the virtual space if memory is not a power of two */
618620
size_t effective_memory_size = ceiling_power_of_two(memory_size);
@@ -661,7 +663,7 @@ static void buddy_toggle_virtual_slots(struct buddy *buddy, _Bool state) {
661663
/* Internal function that checks if there are any allocations
662664
after the indicated relative memory index. Used to check if
663665
the arena can be downsized. */
664-
static _Bool buddy_is_free(struct buddy *buddy, size_t from) {
666+
static unsigned int buddy_is_free(struct buddy *buddy, size_t from) {
665667
/* from is already adjusted for alignment */
666668

667669
size_t effective_memory_size = ceiling_power_of_two(buddy->memory_size);
@@ -908,7 +910,7 @@ static void buddy_tree_shrink(struct buddy_tree *t, uint8_t desired_order) {
908910
}
909911
}
910912

911-
static _Bool buddy_tree_valid(struct buddy_tree *t, buddy_tree_pos pos) {
913+
static unsigned int buddy_tree_valid(struct buddy_tree *t, buddy_tree_pos pos) {
912914
return pos && (pos < t->upper_pos_bound);
913915
}
914916

@@ -1020,7 +1022,7 @@ static struct buddy_tree_interval buddy_tree_interval(struct buddy_tree *t, budd
10201022
return result;
10211023
}
10221024

1023-
static _Bool buddy_tree_interval_contains(struct buddy_tree_interval outer,
1025+
static unsigned int buddy_tree_interval_contains(struct buddy_tree_interval outer,
10241026
struct buddy_tree_interval inner) {
10251027
return (inner.from >= outer.from)
10261028
&& (inner.from <= outer.to)
@@ -1139,7 +1141,7 @@ static buddy_tree_pos buddy_tree_find_free(struct buddy_tree *t, uint8_t target_
11391141
}
11401142
}
11411143

1142-
static _Bool buddy_tree_is_free(struct buddy_tree *t, buddy_tree_pos pos) {
1144+
static unsigned int buddy_tree_is_free(struct buddy_tree *t, buddy_tree_pos pos) {
11431145
if (buddy_tree_status(t, pos)) {
11441146
return 0;
11451147
}
@@ -1155,7 +1157,7 @@ static _Bool buddy_tree_is_free(struct buddy_tree *t, buddy_tree_pos pos) {
11551157
return 1;
11561158
}
11571159

1158-
static _Bool buddy_tree_can_shrink(struct buddy_tree *t) {
1160+
static unsigned int buddy_tree_can_shrink(struct buddy_tree *t) {
11591161
if (buddy_tree_status(t, buddy_tree_right_child(buddy_tree_root())) != 0) {
11601162
return 0; /* Refusing to shrink with right subtree still used! */
11611163
}
@@ -1175,7 +1177,7 @@ static void buddy_tree_debug(FILE *stream, struct buddy_tree *t, buddy_tree_pos
11751177
}
11761178

11771179
buddy_tree_pos start = pos;
1178-
_Bool going_up = 0;
1180+
unsigned int going_up = 0;
11791181
while (1) {
11801182
if (going_up) {
11811183
if (pos == start) {
@@ -1215,10 +1217,10 @@ static void buddy_tree_debug(FILE *stream, struct buddy_tree *t, buddy_tree_pos
12151217
fflush(stdout);
12161218
}
12171219

1218-
static _Bool buddy_tree_check_invariant(struct buddy_tree *t, buddy_tree_pos pos) {
1220+
static unsigned int buddy_tree_check_invariant(struct buddy_tree *t, buddy_tree_pos pos) {
12191221
buddy_tree_pos start = pos;
1220-
_Bool going_up = 0;
1221-
_Bool fail = 0;
1222+
unsigned int going_up = 0;
1223+
unsigned int fail = 0;
12221224
while (1) {
12231225
if (going_up) {
12241226
if (pos == start) {
@@ -1239,7 +1241,7 @@ static _Bool buddy_tree_check_invariant(struct buddy_tree *t, buddy_tree_pos pos
12391241
size_t left_child_status = buddy_tree_status(t, buddy_tree_left_child(pos));
12401242
size_t right_child_status = buddy_tree_status(t, buddy_tree_right_child(pos));
12411243

1242-
_Bool violated = 0;
1244+
unsigned int violated = 0;
12431245

12441246
if (left_child_status || right_child_status) {
12451247
size_t min = left_child_status <= right_child_status
@@ -1291,13 +1293,13 @@ static inline void bitset_clear(unsigned char *bitset, size_t pos) {
12911293
bitset[bucket] &= ~bitset_index_mask[index];
12921294
}
12931295

1294-
static inline _Bool bitset_test(const unsigned char *bitset, size_t pos) {
1296+
static inline unsigned int bitset_test(const unsigned char *bitset, size_t pos) {
12951297
size_t bucket = pos / CHAR_BIT;
12961298
size_t index = pos % CHAR_BIT;
12971299
return bitset[bucket] & bitset_index_mask[index];
12981300
}
12991301

1300-
static uint8_t bitset_char_mask[8][8] = {
1302+
static const uint8_t bitset_char_mask[8][8] = {
13011303
{1, 3, 7, 15, 31, 63, 127, 255},
13021304
{0, 2, 6, 14, 30, 62, 126, 254},
13031305
{0, 0, 4, 12, 28, 60, 124, 252},
@@ -1352,13 +1354,13 @@ static size_t bitset_count_range(unsigned char *bitset, size_t from_pos, size_t
13521354
size_t to_index = to_pos % CHAR_BIT;
13531355

13541356
if (from_bucket == to_bucket) {
1355-
return __builtin_popcount(bitset[from_bucket] & bitset_char_mask[from_index][to_index]);
1357+
return popcount_byte(bitset[from_bucket] & bitset_char_mask[from_index][to_index]);
13561358
}
13571359

1358-
size_t result = __builtin_popcount(bitset[from_bucket] & bitset_char_mask[from_index][7])
1359-
+ __builtin_popcount(bitset[to_bucket] & bitset_char_mask[0][to_index]);
1360+
size_t result = popcount_byte(bitset[from_bucket] & bitset_char_mask[from_index][7])
1361+
+ popcount_byte(bitset[to_bucket] & bitset_char_mask[0][to_index]);
13601362
while(++from_bucket != to_bucket) {
1361-
result += __builtin_popcount(bitset[from_bucket]);
1363+
result += popcount_byte(bitset[from_bucket]);
13621364
}
13631365
return result;
13641366
}
@@ -1393,23 +1395,37 @@ static void bitset_shift_right(unsigned char *bitset, size_t from_pos, size_t to
13931395

13941396
static void bitset_debug(FILE *stream, unsigned char *bitset, size_t length) {
13951397
for (size_t i = 0; i < length; i++) {
1396-
fprintf(stream, "%zu: %d\n", i, bitset_test(bitset, i));
1398+
fprintf(stream, "%zu: %d\n", i, bitset_test(bitset, i) && 1);
13971399
}
13981400
}
13991401

14001402
/*
14011403
Bits
14021404
*/
14031405

1404-
/* Returns the higest set bit position for the given value. Do not call with zero. */
1405-
static inline size_t highest_bit_position(size_t value) {
1406-
assert(value);
1407-
return ((sizeof(size_t) * CHAR_BIT) - __builtin_clzl(value));
1406+
static const unsigned char popcount_lookup[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1407+
1408+
static unsigned int popcount_byte(unsigned char b) {
1409+
return popcount_lookup[b & 15] + popcount_lookup[b >> 4];
1410+
}
1411+
1412+
/* Returns the higest set bit position for the given value. Returns zero for zero. */
1413+
static size_t highest_bit_position(size_t value) {
1414+
int result = 0;
1415+
const size_t all_set[] = {4294967295, 65535, 255, 15, 7, 3, 1};
1416+
const size_t count[] = {32, 16, 8, 4, 2, 1, 1};
1417+
for (size_t i = 0; i < 7; i++) {
1418+
if (value >= all_set[i]) {
1419+
value >>= count[i];
1420+
result += count[i];
1421+
}
1422+
}
1423+
return result + value;
14081424
}
14091425

14101426
static inline size_t ceiling_power_of_two(size_t value) {
14111427
value += !value; /* branchless x -> { 1 for 0, x for x } */
1412-
return 1u << ((sizeof(size_t) * CHAR_BIT) - __builtin_clzl(value + value - 1)-1);
1428+
return 1u << (highest_bit_position(value + value - 1)-1);
14131429
}
14141430

14151431
#endif /* BUDDY_ALLOC_IMPLEMENTATION */

0 commit comments

Comments
 (0)