1/* @title: Bit flag macros */
2#pragma once
3#include <compiler/core.h>
4#include <math/bit.h>
5#include <stdatomic.h>
6#include <stddef.h>
7#include <stdint.h>
8
9#include "bitflag_api_internal.h"
10
11/* Various code around the kernel is a big fan of having bit flags
12 * that are somewhat like the following:
13 *
14 * [ some available bits ] [ some reserved bits ] [ some bits in use ].
15 *
16 * This is all good and well, but the issue is that these bit flags
17 * do not have a unified substrate for actually declaring variables
18 * for the available bits and reserved bits, and end up handrolling
19 * oddities to accomplish this. This is not quite good, so bitflag.h
20 * serves to fix this.
21 *
22 * The idea:
23 *
24 * BITFLAG_RESERVED_DECLARE(type, name,
25 * 5, 6, 8, 9
26 * );
27 *
28 * BITFLAG_AVAILABLE_DECLARE(type, name,
29 * 3, 4, 2, 1, BITFLAG_RANGE(10, 12)
30 * );
31 *
32 * Making arrays that you index into (with safety nets like dedicated macros)
33 * to get the Nth available bit/the Nth reserved bit
34 */
35
36/* Reserved bits */
37#define BITFLAG_RSVD_TYPEOF(name) (typeof(PP_CONCAT(name, _RSVD_MASK)))
38
39#define BITFLAG_RESERVED_DECLARE(type, name, ...) \
40 static_assert(PP_NARG(__VA_ARGS__) > 0); \
41 static const size_t \
42 cc_unused PP_CONCAT(__bitflag_index_rsvd_, name)[] = {__VA_ARGS__}; \
43 static const size_t cc_unused PP_CONCAT(name, _RSVD_COUNT) = \
44 sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)) / \
45 sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)[0]); \
46 static const type cc_unused PP_CONCAT(name, _RSVD_MASK) = \
47 BR_MAKE_MASK(type, __VA_ARGS__)
48
49#define BITFLAG_RSVD_BIT_IDX(name, idx) \
50 (BITFLAG_RSVD_TYPEOF(name)((idx) >= PP_CONCAT(name, _RSVD_COUNT)) \
51 ? 0 * sizeof(struct { \
52 static_assert( \
53 (idx) < \
54 sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)) / \
55 sizeof(PP_CONCAT(__bitflag_index_rsvd_, name)[0]), \
56 "index out of bounds"); \
57 char _b; \
58 }) \
59 : (PP_CONCAT(__bitflag_index_rsvd_, name)[idx]))
60
61#define BITFLAG_RSVD_BIT(name, idx) \
62 ((BITFLAG_RSVD_TYPEOF(name) 1) << BITFLAG_RSVD_BIT_IDX(name, idx))
63
64/* Available bits */
65#define BITFLAG_AVAIL_TYPEOF(name) (typeof(PP_CONCAT(name, _AVAIL_MASK)))
66
67#define BITFLAG_AVAILABLE_DECLARE(type, name, ...) \
68 static_assert(PP_NARG(__VA_ARGS__) > 0); \
69 static const size_t \
70 cc_unused PP_CONCAT(__bitflag_index_avail_, name)[] = {__VA_ARGS__}; \
71 static const size_t cc_unused PP_CONCAT(name, _AVAIL_COUNT) = \
72 sizeof(PP_CONCAT(__bitflag_index_avail_, name)) / \
73 sizeof(PP_CONCAT(__bitflag_index_avail_, name)[0]); \
74 static const type cc_unused PP_CONCAT(name, _AVAIL_MASK) = \
75 BR_MAKE_MASK(type, __VA_ARGS__)
76
77#define BITFLAG_AVAIL_BIT_IDX(name, idx) \
78 (BITFLAG_AVAIL_TYPEOF(name)((idx) >= PP_CONCAT(name, _AVAIL_COUNT)) \
79 ? 0 * sizeof(struct { \
80 static_assert( \
81 (idx) < \
82 sizeof(PP_CONCAT(__bitflag_index_avail_, name)) / \
83 sizeof(PP_CONCAT(__bitflag_index_avail_, name)[0]), \
84 "index out of bounds"); \
85 char _b; \
86 }) \
87 : (PP_CONCAT(__bitflag_index_avail_, name)[idx]))
88
89#define BITFLAG_AVAIL_BIT(name, idx) \
90 ((BITFLAG_AVAIL_TYPEOF(name) 1) << BITFLAG_AVAIL_BIT_IDX(name, idx))
91