diff options
Diffstat (limited to 'include/linux/idr.h')
-rw-r--r-- | include/linux/idr.h | 172 |
1 files changed, 107 insertions, 65 deletions
diff --git a/include/linux/idr.h b/include/linux/idr.h index de7e190f1af4..a6f38b5c34e4 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h | |||
@@ -17,69 +17,40 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
19 | 19 | ||
20 | #if BITS_PER_LONG == 32 | 20 | /* |
21 | # define IDR_BITS 5 | 21 | * We want shallower trees and thus more bits covered at each layer. 8 |
22 | # define IDR_FULL 0xfffffffful | 22 | * bits gives us large enough first layer for most use cases and maximum |
23 | /* We can only use two of the bits in the top level because there is | 23 | * tree depth of 4. Each idr_layer is slightly larger than 2k on 64bit and |
24 | only one possible bit in the top level (5 bits * 7 levels = 35 | 24 | * 1k on 32bit. |
25 | bits, but you only use 31 bits in the id). */ | 25 | */ |
26 | # define TOP_LEVEL_FULL (IDR_FULL >> 30) | 26 | #define IDR_BITS 8 |
27 | #elif BITS_PER_LONG == 64 | ||
28 | # define IDR_BITS 6 | ||
29 | # define IDR_FULL 0xfffffffffffffffful | ||
30 | /* We can only use two of the bits in the top level because there is | ||
31 | only one possible bit in the top level (6 bits * 6 levels = 36 | ||
32 | bits, but you only use 31 bits in the id). */ | ||
33 | # define TOP_LEVEL_FULL (IDR_FULL >> 62) | ||
34 | #else | ||
35 | # error "BITS_PER_LONG is not 32 or 64" | ||
36 | #endif | ||
37 | |||
38 | #define IDR_SIZE (1 << IDR_BITS) | 27 | #define IDR_SIZE (1 << IDR_BITS) |
39 | #define IDR_MASK ((1 << IDR_BITS)-1) | 28 | #define IDR_MASK ((1 << IDR_BITS)-1) |
40 | 29 | ||
41 | #define MAX_IDR_SHIFT (sizeof(int)*8 - 1) | ||
42 | #define MAX_IDR_BIT (1U << MAX_IDR_SHIFT) | ||
43 | #define MAX_IDR_MASK (MAX_IDR_BIT - 1) | ||
44 | |||
45 | /* Leave the possibility of an incomplete final layer */ | ||
46 | #define MAX_IDR_LEVEL ((MAX_IDR_SHIFT + IDR_BITS - 1) / IDR_BITS) | ||
47 | |||
48 | /* Number of id_layer structs to leave in free list */ | ||
49 | #define MAX_IDR_FREE (MAX_IDR_LEVEL * 2) | ||
50 | |||
51 | struct idr_layer { | 30 | struct idr_layer { |
52 | unsigned long bitmap; /* A zero bit means "space here" */ | 31 | int prefix; /* the ID prefix of this idr_layer */ |
32 | DECLARE_BITMAP(bitmap, IDR_SIZE); /* A zero bit means "space here" */ | ||
53 | struct idr_layer __rcu *ary[1<<IDR_BITS]; | 33 | struct idr_layer __rcu *ary[1<<IDR_BITS]; |
54 | int count; /* When zero, we can release it */ | 34 | int count; /* When zero, we can release it */ |
55 | int layer; /* distance from leaf */ | 35 | int layer; /* distance from leaf */ |
56 | struct rcu_head rcu_head; | 36 | struct rcu_head rcu_head; |
57 | }; | 37 | }; |
58 | 38 | ||
59 | struct idr { | 39 | struct idr { |
60 | struct idr_layer __rcu *top; | 40 | struct idr_layer __rcu *hint; /* the last layer allocated from */ |
61 | struct idr_layer *id_free; | 41 | struct idr_layer __rcu *top; |
62 | int layers; /* only valid without concurrent changes */ | 42 | struct idr_layer *id_free; |
63 | int id_free_cnt; | 43 | int layers; /* only valid w/o concurrent changes */ |
64 | spinlock_t lock; | 44 | int id_free_cnt; |
45 | spinlock_t lock; | ||
65 | }; | 46 | }; |
66 | 47 | ||
67 | #define IDR_INIT(name) \ | 48 | #define IDR_INIT(name) \ |
68 | { \ | 49 | { \ |
69 | .top = NULL, \ | 50 | .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ |
70 | .id_free = NULL, \ | ||
71 | .layers = 0, \ | ||
72 | .id_free_cnt = 0, \ | ||
73 | .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ | ||
74 | } | 51 | } |
75 | #define DEFINE_IDR(name) struct idr name = IDR_INIT(name) | 52 | #define DEFINE_IDR(name) struct idr name = IDR_INIT(name) |
76 | 53 | ||
77 | /* Actions to be taken after a call to _idr_sub_alloc */ | ||
78 | #define IDR_NEED_TO_GROW -2 | ||
79 | #define IDR_NOMORE_SPACE -3 | ||
80 | |||
81 | #define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC) | ||
82 | |||
83 | /** | 54 | /** |
84 | * DOC: idr sync | 55 | * DOC: idr sync |
85 | * idr synchronization (stolen from radix-tree.h) | 56 | * idr synchronization (stolen from radix-tree.h) |
@@ -101,19 +72,90 @@ struct idr { | |||
101 | * This is what we export. | 72 | * This is what we export. |
102 | */ | 73 | */ |
103 | 74 | ||
104 | void *idr_find(struct idr *idp, int id); | 75 | void *idr_find_slowpath(struct idr *idp, int id); |
105 | int idr_pre_get(struct idr *idp, gfp_t gfp_mask); | 76 | int idr_pre_get(struct idr *idp, gfp_t gfp_mask); |
106 | int idr_get_new(struct idr *idp, void *ptr, int *id); | ||
107 | int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id); | 77 | int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id); |
78 | void idr_preload(gfp_t gfp_mask); | ||
79 | int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask); | ||
108 | int idr_for_each(struct idr *idp, | 80 | int idr_for_each(struct idr *idp, |
109 | int (*fn)(int id, void *p, void *data), void *data); | 81 | int (*fn)(int id, void *p, void *data), void *data); |
110 | void *idr_get_next(struct idr *idp, int *nextid); | 82 | void *idr_get_next(struct idr *idp, int *nextid); |
111 | void *idr_replace(struct idr *idp, void *ptr, int id); | 83 | void *idr_replace(struct idr *idp, void *ptr, int id); |
112 | void idr_remove(struct idr *idp, int id); | 84 | void idr_remove(struct idr *idp, int id); |
113 | void idr_remove_all(struct idr *idp); | 85 | void idr_free(struct idr *idp, int id); |
114 | void idr_destroy(struct idr *idp); | 86 | void idr_destroy(struct idr *idp); |
115 | void idr_init(struct idr *idp); | 87 | void idr_init(struct idr *idp); |
116 | 88 | ||
89 | /** | ||
90 | * idr_preload_end - end preload section started with idr_preload() | ||
91 | * | ||
92 | * Each idr_preload() should be matched with an invocation of this | ||
93 | * function. See idr_preload() for details. | ||
94 | */ | ||
95 | static inline void idr_preload_end(void) | ||
96 | { | ||
97 | preempt_enable(); | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * idr_find - return pointer for given id | ||
102 | * @idp: idr handle | ||
103 | * @id: lookup key | ||
104 | * | ||
105 | * Return the pointer given the id it has been registered with. A %NULL | ||
106 | * return indicates that @id is not valid or you passed %NULL in | ||
107 | * idr_get_new(). | ||
108 | * | ||
109 | * This function can be called under rcu_read_lock(), given that the leaf | ||
110 | * pointers lifetimes are correctly managed. | ||
111 | */ | ||
112 | static inline void *idr_find(struct idr *idr, int id) | ||
113 | { | ||
114 | struct idr_layer *hint = rcu_dereference_raw(idr->hint); | ||
115 | |||
116 | if (hint && (id & ~IDR_MASK) == hint->prefix) | ||
117 | return rcu_dereference_raw(hint->ary[id & IDR_MASK]); | ||
118 | |||
119 | return idr_find_slowpath(idr, id); | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * idr_get_new - allocate new idr entry | ||
124 | * @idp: idr handle | ||
125 | * @ptr: pointer you want associated with the id | ||
126 | * @id: pointer to the allocated handle | ||
127 | * | ||
128 | * Simple wrapper around idr_get_new_above() w/ @starting_id of zero. | ||
129 | */ | ||
130 | static inline int idr_get_new(struct idr *idp, void *ptr, int *id) | ||
131 | { | ||
132 | return idr_get_new_above(idp, ptr, 0, id); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * idr_for_each_entry - iterate over an idr's elements of a given type | ||
137 | * @idp: idr handle | ||
138 | * @entry: the type * to use as cursor | ||
139 | * @id: id entry's key | ||
140 | */ | ||
141 | #define idr_for_each_entry(idp, entry, id) \ | ||
142 | for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \ | ||
143 | entry != NULL; \ | ||
144 | ++id, entry = (typeof(entry))idr_get_next((idp), &(id))) | ||
145 | |||
146 | void __idr_remove_all(struct idr *idp); /* don't use */ | ||
147 | |||
148 | /** | ||
149 | * idr_remove_all - remove all ids from the given idr tree | ||
150 | * @idp: idr handle | ||
151 | * | ||
152 | * If you're trying to destroy @idp, calling idr_destroy() is enough. | ||
153 | * This is going away. Don't use. | ||
154 | */ | ||
155 | static inline void __deprecated idr_remove_all(struct idr *idp) | ||
156 | { | ||
157 | __idr_remove_all(idp); | ||
158 | } | ||
117 | 159 | ||
118 | /* | 160 | /* |
119 | * IDA - IDR based id allocator, use when translation from id to | 161 | * IDA - IDR based id allocator, use when translation from id to |
@@ -136,12 +178,11 @@ struct ida { | |||
136 | struct ida_bitmap *free_bitmap; | 178 | struct ida_bitmap *free_bitmap; |
137 | }; | 179 | }; |
138 | 180 | ||
139 | #define IDA_INIT(name) { .idr = IDR_INIT(name), .free_bitmap = NULL, } | 181 | #define IDA_INIT(name) { .idr = IDR_INIT((name).idr), .free_bitmap = NULL, } |
140 | #define DEFINE_IDA(name) struct ida name = IDA_INIT(name) | 182 | #define DEFINE_IDA(name) struct ida name = IDA_INIT(name) |
141 | 183 | ||
142 | int ida_pre_get(struct ida *ida, gfp_t gfp_mask); | 184 | int ida_pre_get(struct ida *ida, gfp_t gfp_mask); |
143 | int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); | 185 | int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); |
144 | int ida_get_new(struct ida *ida, int *p_id); | ||
145 | void ida_remove(struct ida *ida, int id); | 186 | void ida_remove(struct ida *ida, int id); |
146 | void ida_destroy(struct ida *ida); | 187 | void ida_destroy(struct ida *ida); |
147 | void ida_init(struct ida *ida); | 188 | void ida_init(struct ida *ida); |
@@ -150,17 +191,18 @@ int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, | |||
150 | gfp_t gfp_mask); | 191 | gfp_t gfp_mask); |
151 | void ida_simple_remove(struct ida *ida, unsigned int id); | 192 | void ida_simple_remove(struct ida *ida, unsigned int id); |
152 | 193 | ||
153 | void __init idr_init_cache(void); | ||
154 | |||
155 | /** | 194 | /** |
156 | * idr_for_each_entry - iterate over an idr's elements of a given type | 195 | * ida_get_new - allocate new ID |
157 | * @idp: idr handle | 196 | * @ida: idr handle |
158 | * @entry: the type * to use as cursor | 197 | * @p_id: pointer to the allocated handle |
159 | * @id: id entry's key | 198 | * |
199 | * Simple wrapper around ida_get_new_above() w/ @starting_id of zero. | ||
160 | */ | 200 | */ |
161 | #define idr_for_each_entry(idp, entry, id) \ | 201 | static inline int ida_get_new(struct ida *ida, int *p_id) |
162 | for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \ | 202 | { |
163 | entry != NULL; \ | 203 | return ida_get_new_above(ida, 0, p_id); |
164 | ++id, entry = (typeof(entry))idr_get_next((idp), &(id))) | 204 | } |
205 | |||
206 | void __init idr_init_cache(void); | ||
165 | 207 | ||
166 | #endif /* __IDR_H__ */ | 208 | #endif /* __IDR_H__ */ |