Bit flag macros
include/bitflag.h View source View on GitHubVarious code around the kernel is a big fan of having bit flags that are somewhat like the following:
[ some available bits ] [ some reserved bits ] [ some bits in use ].
This is all good and well, but the issue is that these bit flags do not have a unified substrate for actually declaring variables for the available bits and reserved bits, and end up handrolling oddities to accomplish this. This is not quite good, so bitflag.h serves to fix this.
The idea:
BITFLAG_RESERVED_DECLARE(type, name, 5, 6, 8, 9 );
BITFLAG_AVAILABLE_DECLARE(type, name, 3, 4, 2, 1, BITFLAG_RANGE(10, 12) );
Making arrays that you index into (with safety nets like dedicated macros) to get the Nth available bit/the Nth reserved bit
Macros
Section titled “Macros”Reserved bits
BITFLAG_RSVD_TYPEOF
Section titled “BITFLAG_RSVD_TYPEOF”#define BITFLAG_RSVD_TYPEOF(name) source Expansion
#define BITFLAG_RSVD_TYPEOF(name) (typeof(PP_CONCAT(name, _RSVD_MASK))) BITFLAG_RESERVED_DECLARE
Section titled “BITFLAG_RESERVED_DECLARE”#define BITFLAG_RESERVED_DECLARE(type, name, ...) source Expansion
#define BITFLAG_RESERVED_DECLARE(type, name, ...) \
static_assert(PP_NARG(__VA_ARGS__) > 0); \
static const size_t \
cc_unused PP_CONCAT(__bitflag_index_rsvd_, name)[] = {__VA_ARGS__}; \
static const size_t cc_unused PP_CONCAT(name, _RSVD_COUNT) = \
sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)) / \
sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)[0]); \
static const type cc_unused PP_CONCAT(name, _RSVD_MASK) = \
BR_MAKE_MASK(type, __VA_ARGS__) BITFLAG_RSVD_BIT_IDX
Section titled “BITFLAG_RSVD_BIT_IDX”#define BITFLAG_RSVD_BIT_IDX(name, idx) source Expansion
#define BITFLAG_RSVD_BIT_IDX(name, idx) \
(BITFLAG_RSVD_TYPEOF(name)((idx) >= PP_CONCAT(name, _RSVD_COUNT)) \
? 0 * sizeof(struct { \
static_assert( \
(idx) < \
sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)) / \
sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)[0]), \
"index out of bounds"); \
char _b; \
}) \
: (PP_CONCAT(__bitflag_index_rsvd_, name)[idx])) BITFLAG_RSVD_BIT
Section titled “BITFLAG_RSVD_BIT”#define BITFLAG_RSVD_BIT(name, idx) source Expansion
#define BITFLAG_RSVD_BIT(name, idx) \
((BITFLAG_RSVD_TYPEOF(name) 1) << BITFLAG_RSVD_BIT_IDX(name, idx)) Available bits
BITFLAG_AVAIL_TYPEOF
Section titled “BITFLAG_AVAIL_TYPEOF”#define BITFLAG_AVAIL_TYPEOF(name) source Expansion
#define BITFLAG_AVAIL_TYPEOF(name) (typeof(PP_CONCAT(name, _AVAIL_MASK))) BITFLAG_AVAILABLE_DECLARE
Section titled “BITFLAG_AVAILABLE_DECLARE”#define BITFLAG_AVAILABLE_DECLARE(type, name, ...) source Expansion
#define BITFLAG_AVAILABLE_DECLARE(type, name, ...) \
static_assert(PP_NARG(__VA_ARGS__) > 0); \
static const size_t \
cc_unused PP_CONCAT(__bitflag_index_avail_, name)[] = {__VA_ARGS__}; \
static const size_t cc_unused PP_CONCAT(name, _AVAIL_COUNT) = \
sizeof(PP_CONCAT(__bitflag_index_avail_, name)) / \
sizeof(PP_CONCAT(__bitflag_index_avail_, name)[0]); \
static const type cc_unused PP_CONCAT(name, _AVAIL_MASK) = \
BR_MAKE_MASK(type, __VA_ARGS__) BITFLAG_AVAIL_BIT_IDX
Section titled “BITFLAG_AVAIL_BIT_IDX”#define BITFLAG_AVAIL_BIT_IDX(name, idx) source Expansion
#define BITFLAG_AVAIL_BIT_IDX(name, idx) \
(BITFLAG_AVAIL_TYPEOF(name)((idx) >= PP_CONCAT(name, _AVAIL_COUNT)) \
? 0 * sizeof(struct { \
static_assert( \
(idx) < \
sizeof(PP_CONCAT(__bitflag_index_avail_, name)) / \
sizeof(PP_CONCAT(__bitflag_index_avail_, name)[0]), \
"index out of bounds"); \
char _b; \
}) \
: (PP_CONCAT(__bitflag_index_avail_, name)[idx])) BITFLAG_AVAIL_BIT
Section titled “BITFLAG_AVAIL_BIT”#define BITFLAG_AVAIL_BIT(name, idx) source Expansion
#define BITFLAG_AVAIL_BIT(name, idx) \
((BITFLAG_AVAIL_TYPEOF(name) 1) << BITFLAG_AVAIL_BIT_IDX(name, idx))