1 #pragma GCC push_options
2 #pragma GCC optimize("O1")
3 
4 #include <common/errno.h>
5 #include <common/spinlock.h>
6 
7 #if ARCH(I386) || ARCH(X86_64)
8 #include <arch/x86_64/math/bitcount.h>
9 #else
10 #error Arch not supported.
11 #endif
12 
13 
14 /**
15  * idr: 基于radix-tree的ID-pointer的数据结构
16  * 主要功能:
17  * 1. 获取一个ID, 并且将该ID与一个指针绑定  - 需要外部加锁
18  * 2. 删除一个已分配的ID                  - 需要外部加锁
19  * 3. 根据ID查找对应的指针                (读操作,看情况加锁)
20  * 4. 根据ID使用新的ptr替换旧的ptr        - 需要外部加锁
21  *
22  * 附加功能:
23  * 1. 给定starting_id, 查询下一个已分配的next_id  (即:next_id>starting_id)
24  * 2. 销毁整个idr
25  *
26  *
27  * .... 待实现
28  */
29 
30 // 默认64位机器
31 #define IDR_BITS 6
32 #define IDR_FULL 0xfffffffffffffffful
33 
34 // size = 64
35 #define IDR_SIZE (1 << IDR_BITS)
36 #define IDR_MASK ((1 << IDR_BITS) - 1)
37 
38 // 能管理的ID范围[0:1<<31]
39 #define MAX_ID_SHIFT (sizeof(int) * 8 - 1)
40 #define MAX_ID_BIT (1U << MAX_ID_SHIFT)
41 #define MAX_ID_MASK (MAX_ID_BIT - 1)
42 
43 // IDR可能最大的层次 以及 IDR预分配空间的最大限制
44 #define MAX_LEVEL ((MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS)
45 #define IDR_FREE_MAX (MAX_LEVEL << 1)
46 
47 // 给定layer, 计算完全64叉树的大小
48 #define TREE_SIZE(layer) ((layer >= 0) ? (1ull << ((layer + 1) * IDR_BITS)) : 1)
49 
50 // 计算最后(最低位)一个1的位置 (注意使用64位的版本)
51 #define __lowbit_id(x) ((x) ? (__ctzll(x)) : -1)
52 
53 // 计算最前(最高位)一个1的位置 (注意使用64位的版本)
54 #define __mostbit_id(x) ((x) ? (63 - __clzll(x)) : -1)
55 
56 // radix-tree 节点定义
57 struct idr_layer
58 {
59     struct idr_layer *ary[IDR_SIZE]; // IDR_SIZE叉树
60     unsigned long bitmap;            // 每一位表示这个子树是否被使用
61     unsigned long full;              // 64个儿子子树, 每一位代表一个子树是否满了
62     int layer;                       // 层数(从底向上)
63 };
64 
65 // idr: 将id与pointer绑定的数据结构
66 struct idr
67 {
68     struct idr_layer *top;
69     struct idr_layer *free_list;
70     int id_free_cnt;
71     spinlock_t lock;
72 }__attribute__((aligned(8)));
73 
74 #define DECLARE_IDR(name)    \
75     struct idr name = {0};   \
76     idr_init(&(name));
77 
78 #define DECLARE_IDR_LAYER(name)  \
79     struct idr_layer name = {0}; \
80     memset(name, 0, sizeof(struct idr_layer));
81 
82 /**
83  * 对外函数声明
84  **/
85 int idr_preload(struct idr *idp, gfp_t gfp_mask);
86 int idr_alloc(struct idr *idp, void *ptr, int *id);
87 void *idr_remove(struct idr *idp, int id);
88 void idr_remove_all(struct idr *idp);
89 void idr_destroy(struct idr *idp);
90 void *idr_find(struct idr *idp, int id);
91 void *idr_find_next(struct idr *idp, int start_id);
92 void *idr_find_next_getid(struct idr *idp, int64_t start_id, int *nextid);
93 int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **oldptr);
94 int idr_replace(struct idr *idp, void *ptr, int id);
95 void idr_init(struct idr *idp);
96 bool idr_empty(struct idr *idp);
97 bool idr_count(struct idr *idp, int id);
98 
99 /**
100  * 对外宏:遍历idr两种方式:
101  *     1. 从第一个元素开始遍历
102  *     2. 从某一个id开始遍历
103  */
104 
105 /**
106  * @brief 第一种遍历方式: 从第一个元素开始遍历
107  * @param idp idr指针
108  * @param id  遍历的id,你不需要初始化这个id,因为它每一次都是从最小已分配的id开始遍历
109  * @param ptr 数据指针(entry),你不需要初始化这个指针
110  */
111 #define for_each_idr_entry(idp, id, ptr) \
112     for (id = -1, ptr = idr_find_next_getid(idp, id, &id); ptr != NULL || !idr_count(idp, id); ptr = idr_find_next_getid(idp, id, &id))
113 
114 /**
115  * @brief 第二种遍历方式: 从某一个id开始遍历
116  * @param idp idr指针
117  * @param id  遍历的id,你需要初始化这个id(请你设置为你要从哪一个id开始遍历,遍历过程将会包括这个id)
118  * @param ptr 数据指针(entry),你不需要初始化这个指针
119  */
120 #define for_each_idr_entry_continue(idp, id, ptr) \
121     for (ptr = idr_find_next_getid(idp, id - 1, &id); ptr != NULL || !idr_count(idp, id); ptr = idr_find_next_getid(idp, id, &id))
122 
123 /**
124  * ida: 基于IDR实现的ID分配器
125  * 主要功能:
126  * 1. 获取一个未分配的ID
127  * 2. 询问一个ID是否被分配
128  * 3. 删除一个已分配ID
129  *
130  * 附加功能:
131  * 1. 暂定
132  */
133 
134 // 一个块的大小 - 即 sizeof(struct ida_bitmap)
135 #define IDA_CHUNK_SIZE 128
136 // ida_bitmap的长度
137 #define IDA_BITMAP_LONGS (IDA_CHUNK_SIZE / sizeof(long) - 1)
138 // 对应linux的IDA_BITMAP_BITS = 960 = 15 * 64
139 #define IDA_FULL (IDA_BITMAP_LONGS * sizeof(long) * 8)
140 #define IDA_BITMAP_BITS IDA_FULL
141 #define IDA_BMP_SIZE (8 * sizeof(long))
142 
143 // 自定义bitmap
144 struct ida_bitmap
145 {
146     unsigned long count;                    // bitmap中已经分配的id数量
147     unsigned long bitmap[IDA_BITMAP_LONGS]; // bitmap本身, 每一个bit代表一个ID
148 };
149 
150 // id-allocater 管理+分配ID的数据结构
151 struct ida
152 {
153     struct idr idr;
154     struct ida_bitmap *free_list; // 预分配的数据块
155 };
156 
157 #define DECLARE_IDA(name)  \
158     struct ida name = {0}; \
159     idr_init(&name.idr);   \
160     name.free_list = (NULL);
161 
162 /**
163  * 对外函数声明
164  */
165 void ida_init(struct ida *ida_p);
166 bool ida_empty(struct ida *ida_p);
167 int ida_preload(struct ida *ida_p, gfp_t gfp_mask);
168 int ida_alloc(struct ida *ida_p, int *p_id);
169 bool ida_count(struct ida *ida_p, int id);
170 void ida_remove(struct ida *ida_p, int id);
171 void ida_destroy(struct ida *ida_p);
172 
173 #pragma GCC pop_options