16
16
#define BUDDY_ALLOC_H
17
17
18
18
#include <limits.h>
19
- #include <stdalign.h>
20
19
#include <stddef.h>
21
20
#include <stdint.h>
22
21
#include <stdio.h>
@@ -41,10 +40,10 @@ struct buddy *buddy_embed(unsigned char *main, size_t memory_size);
41
40
struct buddy * buddy_resize (struct buddy * buddy , size_t new_memory_size );
42
41
43
42
/* 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 );
45
44
46
45
/* Tests if the allocation is completely empty */
47
- _Bool buddy_is_empty (struct buddy * buddy );
46
+ unsigned int buddy_is_empty (struct buddy * buddy );
48
47
49
48
/* Reports the arena size */
50
49
size_t buddy_arena_size (struct buddy * buddy );
@@ -105,7 +104,7 @@ static size_t buddy_tree_sizeof(uint8_t order);
105
104
static struct buddy_tree * buddy_tree_init (unsigned char * at , uint8_t order );
106
105
107
106
/* 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 );
109
108
110
109
/* Returns the order of the specified buddy allocation tree */
111
110
static uint8_t buddy_tree_order (struct buddy_tree * t );
@@ -146,7 +145,7 @@ static size_t buddy_tree_index(buddy_tree_pos pos);
146
145
static struct buddy_tree_interval buddy_tree_interval (struct buddy_tree * t , buddy_tree_pos pos );
147
146
148
147
/* 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 ,
150
149
struct buddy_tree_interval inner );
151
150
152
151
/*
@@ -166,10 +165,10 @@ static void buddy_tree_release(struct buddy_tree *t, buddy_tree_pos pos);
166
165
static buddy_tree_pos buddy_tree_find_free (struct buddy_tree * t , uint8_t depth );
167
166
168
167
/* 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 );
170
169
171
170
/* 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 );
173
172
174
173
/*
175
174
* Debug functions
@@ -179,7 +178,7 @@ static _Bool buddy_tree_can_shrink(struct buddy_tree *t);
179
178
static void buddy_tree_debug (FILE * stream , struct buddy_tree * t , buddy_tree_pos pos , size_t start_size );
180
179
181
180
/* 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 );
183
182
184
183
/*
185
184
* A char-backed bitset implementation
@@ -197,7 +196,7 @@ static inline void bitset_set(unsigned char *bitset, size_t pos);
197
196
198
197
static inline void bitset_clear (unsigned char * bitset , size_t pos );
199
198
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 );
201
200
202
201
static void bitset_shift_left (unsigned char * bitset , size_t from_pos , size_t to_pos , size_t by );
203
202
@@ -214,8 +213,11 @@ static void bitset_debug(FILE *stream, unsigned char *bitset, size_t length);
214
213
Bits
215
214
*/
216
215
216
+ /* Returns the number of set bits in the given byte */
217
+ static unsigned int popcount_byte (unsigned char b );
218
+
217
219
/* 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 );
219
221
220
222
/* Returns the nearest larger or equal power of two */
221
223
static inline size_t ceiling_power_of_two (size_t value );
@@ -235,12 +237,12 @@ struct buddy {
235
237
unsigned char * main ;
236
238
ptrdiff_t main_offset ;
237
239
};
238
- _Bool relative_mode ;
240
+ unsigned int relative_mode ;
239
241
unsigned char buddy_tree [];
240
242
};
241
243
242
244
struct buddy_embed_check {
243
- _Bool can_fit ;
245
+ unsigned int can_fit ;
244
246
size_t offset ;
245
247
size_t buddy_size ;
246
248
};
@@ -252,10 +254,10 @@ static void *address_for_position(struct buddy *buddy, buddy_tree_pos pos);
252
254
static buddy_tree_pos position_for_address (struct buddy * buddy , const unsigned char * addr );
253
255
static unsigned char * buddy_main (struct buddy * buddy );
254
256
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 );
256
258
static struct buddy * buddy_resize_standard (struct buddy * buddy , size_t new_memory_size );
257
259
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 );
259
261
static struct buddy_embed_check buddy_embed_offset (size_t memory_size );
260
262
static buddy_tree_pos deepest_position_for_offset (struct buddy * buddy , size_t offset );
261
263
@@ -383,14 +385,14 @@ static struct buddy *buddy_resize_embedded(struct buddy *buddy, size_t new_memor
383
385
return relocated ;
384
386
}
385
387
386
- _Bool buddy_can_shrink (struct buddy * buddy ) {
388
+ unsigned int buddy_can_shrink (struct buddy * buddy ) {
387
389
if (buddy == NULL ) {
388
390
return 0 ;
389
391
}
390
392
return buddy_is_free (buddy , buddy -> memory_size / 2 );
391
393
}
392
394
393
- _Bool buddy_is_empty (struct buddy * buddy ) {
395
+ unsigned int buddy_is_empty (struct buddy * buddy ) {
394
396
if (buddy == NULL ) {
395
397
return 1 ;
396
398
}
@@ -482,7 +484,7 @@ void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size) {
482
484
}
483
485
484
486
/* 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 );
486
488
if (!origin ) {
487
489
return NULL ;
488
490
}
@@ -612,7 +614,7 @@ static unsigned char *buddy_main(struct buddy *buddy) {
612
614
return buddy -> main ;
613
615
}
614
616
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 ) {
616
618
size_t memory_size = buddy -> memory_size ;
617
619
/* Mask/unmask the virtual space if memory is not a power of two */
618
620
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) {
661
663
/* Internal function that checks if there are any allocations
662
664
after the indicated relative memory index. Used to check if
663
665
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 ) {
665
667
/* from is already adjusted for alignment */
666
668
667
669
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) {
908
910
}
909
911
}
910
912
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 ) {
912
914
return pos && (pos < t -> upper_pos_bound );
913
915
}
914
916
@@ -1020,7 +1022,7 @@ static struct buddy_tree_interval buddy_tree_interval(struct buddy_tree *t, budd
1020
1022
return result ;
1021
1023
}
1022
1024
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 ,
1024
1026
struct buddy_tree_interval inner ) {
1025
1027
return (inner .from >= outer .from )
1026
1028
&& (inner .from <= outer .to )
@@ -1139,7 +1141,7 @@ static buddy_tree_pos buddy_tree_find_free(struct buddy_tree *t, uint8_t target_
1139
1141
}
1140
1142
}
1141
1143
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 ) {
1143
1145
if (buddy_tree_status (t , pos )) {
1144
1146
return 0 ;
1145
1147
}
@@ -1155,7 +1157,7 @@ static _Bool buddy_tree_is_free(struct buddy_tree *t, buddy_tree_pos pos) {
1155
1157
return 1 ;
1156
1158
}
1157
1159
1158
- static _Bool buddy_tree_can_shrink (struct buddy_tree * t ) {
1160
+ static unsigned int buddy_tree_can_shrink (struct buddy_tree * t ) {
1159
1161
if (buddy_tree_status (t , buddy_tree_right_child (buddy_tree_root ())) != 0 ) {
1160
1162
return 0 ; /* Refusing to shrink with right subtree still used! */
1161
1163
}
@@ -1175,7 +1177,7 @@ static void buddy_tree_debug(FILE *stream, struct buddy_tree *t, buddy_tree_pos
1175
1177
}
1176
1178
1177
1179
buddy_tree_pos start = pos ;
1178
- _Bool going_up = 0 ;
1180
+ unsigned int going_up = 0 ;
1179
1181
while (1 ) {
1180
1182
if (going_up ) {
1181
1183
if (pos == start ) {
@@ -1215,10 +1217,10 @@ static void buddy_tree_debug(FILE *stream, struct buddy_tree *t, buddy_tree_pos
1215
1217
fflush (stdout );
1216
1218
}
1217
1219
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 ) {
1219
1221
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 ;
1222
1224
while (1 ) {
1223
1225
if (going_up ) {
1224
1226
if (pos == start ) {
@@ -1239,7 +1241,7 @@ static _Bool buddy_tree_check_invariant(struct buddy_tree *t, buddy_tree_pos pos
1239
1241
size_t left_child_status = buddy_tree_status (t , buddy_tree_left_child (pos ));
1240
1242
size_t right_child_status = buddy_tree_status (t , buddy_tree_right_child (pos ));
1241
1243
1242
- _Bool violated = 0 ;
1244
+ unsigned int violated = 0 ;
1243
1245
1244
1246
if (left_child_status || right_child_status ) {
1245
1247
size_t min = left_child_status <= right_child_status
@@ -1291,13 +1293,13 @@ static inline void bitset_clear(unsigned char *bitset, size_t pos) {
1291
1293
bitset [bucket ] &= ~bitset_index_mask [index ];
1292
1294
}
1293
1295
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 ) {
1295
1297
size_t bucket = pos / CHAR_BIT ;
1296
1298
size_t index = pos % CHAR_BIT ;
1297
1299
return bitset [bucket ] & bitset_index_mask [index ];
1298
1300
}
1299
1301
1300
- static uint8_t bitset_char_mask [8 ][8 ] = {
1302
+ static const uint8_t bitset_char_mask [8 ][8 ] = {
1301
1303
{1 , 3 , 7 , 15 , 31 , 63 , 127 , 255 },
1302
1304
{0 , 2 , 6 , 14 , 30 , 62 , 126 , 254 },
1303
1305
{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
1352
1354
size_t to_index = to_pos % CHAR_BIT ;
1353
1355
1354
1356
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 ]);
1356
1358
}
1357
1359
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 ]);
1360
1362
while (++ from_bucket != to_bucket ) {
1361
- result += __builtin_popcount (bitset [from_bucket ]);
1363
+ result += popcount_byte (bitset [from_bucket ]);
1362
1364
}
1363
1365
return result ;
1364
1366
}
@@ -1393,23 +1395,37 @@ static void bitset_shift_right(unsigned char *bitset, size_t from_pos, size_t to
1393
1395
1394
1396
static void bitset_debug (FILE * stream , unsigned char * bitset , size_t length ) {
1395
1397
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 );
1397
1399
}
1398
1400
}
1399
1401
1400
1402
/*
1401
1403
Bits
1402
1404
*/
1403
1405
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 ;
1408
1424
}
1409
1425
1410
1426
static inline size_t ceiling_power_of_two (size_t value ) {
1411
1427
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 );
1413
1429
}
1414
1430
1415
1431
#endif /* BUDDY_ALLOC_IMPLEMENTATION */
0 commit comments