1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#ifndef _LINUX_RHASHTABLE_H
19#define _LINUX_RHASHTABLE_H
20
21#include <linux/compiler.h>
22#include <linux/list_nulls.h>
23#include <linux/workqueue.h>
24#include <linux/mutex.h>
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#define RHT_BASE_BITS 4
42#define RHT_HASH_BITS 27
43#define RHT_BASE_SHIFT RHT_HASH_BITS
44
45struct rhash_head {
46 struct rhash_head __rcu *next;
47};
48
49
50
51
52
53
54
55
56struct bucket_table {
57 size_t size;
58 unsigned int locks_mask;
59 spinlock_t *locks;
60
61 struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp;
62};
63
64typedef u32 (*rht_hashfn_t)(const void *data, u32 len, u32 seed);
65typedef u32 (*rht_obj_hashfn_t)(const void *data, u32 seed);
66
67struct rhashtable;
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83struct rhashtable_params {
84 size_t nelem_hint;
85 size_t key_len;
86 size_t key_offset;
87 size_t head_offset;
88 u32 hash_rnd;
89 size_t max_shift;
90 size_t min_shift;
91 u32 nulls_base;
92 size_t locks_mul;
93 rht_hashfn_t hashfn;
94 rht_obj_hashfn_t obj_hashfn;
95};
96
97
98
99
100
101
102
103
104
105
106
107
108
109struct rhashtable {
110 struct bucket_table __rcu *tbl;
111 struct bucket_table __rcu *future_tbl;
112 atomic_t nelems;
113 atomic_t shift;
114 struct rhashtable_params p;
115 struct work_struct run_work;
116 struct mutex mutex;
117 struct list_head walkers;
118 bool being_destroyed;
119};
120
121
122
123
124
125
126struct rhashtable_walker {
127 struct list_head list;
128 bool resize;
129};
130
131
132
133
134
135
136
137
138
139struct rhashtable_iter {
140 struct rhashtable *ht;
141 struct rhash_head *p;
142 struct rhashtable_walker *walker;
143 unsigned int slot;
144 unsigned int skip;
145};
146
147static inline unsigned long rht_marker(const struct rhashtable *ht, u32 hash)
148{
149 return NULLS_MARKER(ht->p.nulls_base + hash);
150}
151
152#define INIT_RHT_NULLS_HEAD(ptr, ht, hash) \
153 ((ptr) = (typeof(ptr)) rht_marker(ht, hash))
154
155static inline bool rht_is_a_nulls(const struct rhash_head *ptr)
156{
157 return ((unsigned long) ptr & 1);
158}
159
160static inline unsigned long rht_get_nulls_value(const struct rhash_head *ptr)
161{
162 return ((unsigned long) ptr) >> 1;
163}
164
165#ifdef CONFIG_PROVE_LOCKING
166int lockdep_rht_mutex_is_held(struct rhashtable *ht);
167int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash);
168#else
169static inline int lockdep_rht_mutex_is_held(struct rhashtable *ht)
170{
171 return 1;
172}
173
174static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl,
175 u32 hash)
176{
177 return 1;
178}
179#endif
180
181int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params);
182
183void rhashtable_insert(struct rhashtable *ht, struct rhash_head *node);
184bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *node);
185
186int rhashtable_expand(struct rhashtable *ht);
187int rhashtable_shrink(struct rhashtable *ht);
188
189void *rhashtable_lookup(struct rhashtable *ht, const void *key);
190void *rhashtable_lookup_compare(struct rhashtable *ht, const void *key,
191 bool (*compare)(void *, void *), void *arg);
192
193bool rhashtable_lookup_insert(struct rhashtable *ht, struct rhash_head *obj);
194bool rhashtable_lookup_compare_insert(struct rhashtable *ht,
195 struct rhash_head *obj,
196 bool (*compare)(void *, void *),
197 void *arg);
198
199int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter);
200void rhashtable_walk_exit(struct rhashtable_iter *iter);
201int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU);
202void *rhashtable_walk_next(struct rhashtable_iter *iter);
203void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
204
205void rhashtable_destroy(struct rhashtable *ht);
206
207#define rht_dereference(p, ht) \
208 rcu_dereference_protected(p, lockdep_rht_mutex_is_held(ht))
209
210#define rht_dereference_rcu(p, ht) \
211 rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht))
212
213#define rht_dereference_bucket(p, tbl, hash) \
214 rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash))
215
216#define rht_dereference_bucket_rcu(p, tbl, hash) \
217 rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash))
218
219#define rht_entry(tpos, pos, member) \
220 ({ tpos = container_of(pos, typeof(*tpos), member); 1; })
221
222
223
224
225
226
227
228
229#define rht_for_each_continue(pos, head, tbl, hash) \
230 for (pos = rht_dereference_bucket(head, tbl, hash); \
231 !rht_is_a_nulls(pos); \
232 pos = rht_dereference_bucket((pos)->next, tbl, hash))
233
234
235
236
237
238
239
240#define rht_for_each(pos, tbl, hash) \
241 rht_for_each_continue(pos, (tbl)->buckets[hash], tbl, hash)
242
243
244
245
246
247
248
249
250
251
252#define rht_for_each_entry_continue(tpos, pos, head, tbl, hash, member) \
253 for (pos = rht_dereference_bucket(head, tbl, hash); \
254 (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \
255 pos = rht_dereference_bucket((pos)->next, tbl, hash))
256
257
258
259
260
261
262
263
264
265#define rht_for_each_entry(tpos, pos, tbl, hash, member) \
266 rht_for_each_entry_continue(tpos, pos, (tbl)->buckets[hash], \
267 tbl, hash, member)
268
269
270
271
272
273
274
275
276
277
278
279
280
281#define rht_for_each_entry_safe(tpos, pos, next, tbl, hash, member) \
282 for (pos = rht_dereference_bucket((tbl)->buckets[hash], tbl, hash), \
283 next = !rht_is_a_nulls(pos) ? \
284 rht_dereference_bucket(pos->next, tbl, hash) : NULL; \
285 (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \
286 pos = next, \
287 next = !rht_is_a_nulls(pos) ? \
288 rht_dereference_bucket(pos->next, tbl, hash) : NULL)
289
290
291
292
293
294
295
296
297
298
299
300
301#define rht_for_each_rcu_continue(pos, head, tbl, hash) \
302 for (({barrier(); }), \
303 pos = rht_dereference_bucket_rcu(head, tbl, hash); \
304 !rht_is_a_nulls(pos); \
305 pos = rcu_dereference_raw(pos->next))
306
307
308
309
310
311
312
313
314
315
316
317#define rht_for_each_rcu(pos, tbl, hash) \
318 rht_for_each_rcu_continue(pos, (tbl)->buckets[hash], tbl, hash)
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333#define rht_for_each_entry_rcu_continue(tpos, pos, head, tbl, hash, member) \
334 for (({barrier(); }), \
335 pos = rht_dereference_bucket_rcu(head, tbl, hash); \
336 (!rht_is_a_nulls(pos)) && rht_entry(tpos, pos, member); \
337 pos = rht_dereference_bucket_rcu(pos->next, tbl, hash))
338
339
340
341
342
343
344
345
346
347
348
349
350
351#define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member) \
352 rht_for_each_entry_rcu_continue(tpos, pos, (tbl)->buckets[hash],\
353 tbl, hash, member)
354
355#endif
356