1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99#ifndef TEST
100#include <linux/slab.h>
101#include <linux/init.h>
102#include <linux/module.h>
103#endif
104#include <linux/string.h>
105#include <linux/idr.h>
106
107
108static kmem_cache_t *idr_layer_cache;
109
110
111
112static inline struct idr_layer *alloc_layer(struct idr *idp)
113{
114 struct idr_layer *p;
115
116 spin_lock(&idp->lock);
117 if (!(p = idp->id_free))
118 BUG();
119 idp->id_free = p->ary[0];
120 idp->id_free_cnt--;
121 p->ary[0] = 0;
122 spin_unlock(&idp->lock);
123 return(p);
124}
125
126static inline void free_layer(struct idr *idp, struct idr_layer *p)
127{
128
129
130
131 spin_lock(&idp->lock);
132 p->ary[0] = idp->id_free;
133 idp->id_free = p;
134 idp->id_free_cnt++;
135 spin_unlock(&idp->lock);
136}
137
138int idr_pre_get(struct idr *idp)
139{
140 while (idp->id_free_cnt < idp->layers + 1) {
141 struct idr_layer *new;
142 new = kmem_cache_alloc(idr_layer_cache, GFP_KERNEL);
143 if(new == NULL)
144 return (0);
145 free_layer(idp, new);
146 }
147 return 1;
148}
149EXPORT_SYMBOL(idr_pre_get);
150
151static inline int sub_alloc(struct idr *idp, int shift, void *ptr)
152{
153 int n, v = 0;
154 struct idr_layer *p;
155 struct idr_layer **pa[MAX_LEVEL];
156 struct idr_layer ***paa = &pa[0];
157
158 *paa = NULL;
159 *++paa = &idp->top;
160
161
162
163
164
165
166
167 while (1){
168 p = **paa;
169 n = ffz(p->bitmap);
170 if (shift){
171
172
173
174
175 if (!p->ary[n]){
176
177
178
179
180
181 if ((n << shift) >= MAX_ID_BIT)
182 return -1;
183 p->ary[n] = alloc_layer(idp);
184 p->count++;
185 }
186 *++paa = &p->ary[n];
187 v += (n << shift);
188 shift -= IDR_BITS;
189 } else {
190
191
192
193
194 p->ary[n] = (struct idr_layer *)ptr;
195 __set_bit(n, &p->bitmap);
196 v += n;
197 p->count++;
198
199
200
201
202
203 while (*(paa-1) && (**paa)->bitmap == IDR_FULL){
204 n = *paa - &(**(paa-1))->ary[0];
205 __set_bit(n, &(**--paa)->bitmap);
206 }
207 return(v);
208 }
209 }
210}
211
212int idr_get_new(struct idr *idp, void *ptr)
213{
214 int v;
215
216 if (idp->id_free_cnt < idp->layers + 1)
217 return (-1);
218
219
220
221 if (unlikely(!idp->top || idp->top->bitmap == IDR_FULL)){
222
223
224
225
226 struct idr_layer *new = alloc_layer(idp);
227 new->ary[0] = idp->top;
228 if ( idp->top)
229 ++new->count;
230 idp->top = new;
231 if ( idp->layers++ )
232 __set_bit(0, &new->bitmap);
233 }
234 v = sub_alloc(idp, (idp->layers - 1) * IDR_BITS, ptr);
235 if ( likely(v >= 0 )){
236 idp->count++;
237 v += (idp->count << MAX_ID_SHIFT);
238 if ( unlikely( v == -1 ))
239 v += (1L << MAX_ID_SHIFT);
240 }
241 return(v);
242}
243EXPORT_SYMBOL(idr_get_new);
244
245
246static inline void sub_remove(struct idr *idp, int shift, int id)
247{
248 struct idr_layer *p = idp->top;
249 struct idr_layer **pa[MAX_LEVEL];
250 struct idr_layer ***paa = &pa[0];
251
252 *paa = NULL;
253 *++paa = &idp->top;
254
255 while ((shift > 0) && p) {
256 int n = (id >> shift) & IDR_MASK;
257 __clear_bit(n, &p->bitmap);
258 *++paa = &p->ary[n];
259 p = p->ary[n];
260 shift -= IDR_BITS;
261 }
262 if (likely(p != NULL)){
263 int n = id & IDR_MASK;
264 __clear_bit(n, &p->bitmap);
265 p->ary[n] = NULL;
266 while(*paa && ! --((**paa)->count)){
267 free_layer(idp, **paa);
268 **paa-- = NULL;
269 }
270 if ( ! *paa )
271 idp->layers = 0;
272 }
273}
274void idr_remove(struct idr *idp, int id)
275{
276 struct idr_layer *p;
277
278 sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
279 if ( idp->top && idp->top->count == 1 &&
280 (idp->layers > 1) &&
281 idp->top->ary[0]){
282
283 p = idp->top->ary[0];
284 idp->top->bitmap = idp->top->count = 0;
285 free_layer(idp, idp->top);
286 idp->top = p;
287 --idp->layers;
288 }
289 while (idp->id_free_cnt >= IDR_FREE_MAX) {
290
291 p = alloc_layer(idp);
292 kmem_cache_free(idr_layer_cache, p);
293 return;
294 }
295}
296EXPORT_SYMBOL(idr_remove);
297
298void *idr_find(struct idr *idp, int id)
299{
300 int n;
301 struct idr_layer *p;
302
303 n = idp->layers * IDR_BITS;
304 p = idp->top;
305#if 0
306
307
308
309
310 if ( unlikely( (id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)))
311 return NULL;
312#endif
313 while (n > 0 && p) {
314 n -= IDR_BITS;
315 p = p->ary[(id >> n) & IDR_MASK];
316 }
317 return((void *)p);
318}
319EXPORT_SYMBOL(idr_find);
320
321static void idr_cache_ctor(void * idr_layer,
322 kmem_cache_t *idr_layer_cache, unsigned long flags)
323{
324 memset(idr_layer, 0, sizeof(struct idr_layer));
325}
326
327static int init_id_cache(void)
328{
329 if (!idr_layer_cache)
330 idr_layer_cache = kmem_cache_create("idr_layer_cache",
331 sizeof(struct idr_layer), 0, 0, idr_cache_ctor, 0);
332 return 0;
333}
334
335void idr_init(struct idr *idp)
336{
337 init_id_cache();
338 memset(idp, 0, sizeof(struct idr));
339 spin_lock_init(&idp->lock);
340}
341EXPORT_SYMBOL(idr_init);
342
343