1 #ifndef _LINUX_GENERIC_RADIX_TREE_H
2 #define _LINUX_GENERIC_RADIX_TREE_H
5 * Generic radix trees/sparse arrays:
7 * A generic radix tree has all nodes of size PAGE_SIZE - both leaves and
11 #include <linux/page.h>
12 #include <linux/bug.h>
13 #include <linux/kernel.h>
14 #include <linux/log2.h>
19 struct genradix_node *root;
24 * NOTE: currently, sizeof(_type) must be a power of two and not larger than
28 #define __GENRADIX_INITIALIZER \
37 * We use a 0 size array to stash the type we're storing without taking any
38 * space at runtime - then the various accessor macros can use typeof() to get
39 * to it for casts/sizeof - we also force the alignment so that storing a type
40 * with a ridiculous alignment doesn't blow up the alignment or size of the
44 #define DECLARE_GENRADIX_TYPE(_name, _type) \
46 struct __genradix tree; \
47 _type type[0] __aligned(1); \
50 #define DECLARE_GENRADIX(_name, _type) \
52 struct __genradix tree; \
53 _type type[0] __aligned(1); \
56 #define DEFINE_GENRADIX(_name, _type) \
57 DECLARE_GENRADIX(_name, _type) = __GENRADIX_INITIALIZER
59 #define genradix_init(_radix) \
61 *(_radix) = (typeof(*_radix)) __GENRADIX_INITIALIZER; \
64 void __genradix_free(struct __genradix *);
66 #define genradix_free(_radix) __genradix_free(&(_radix)->tree)
68 static inline size_t __idx_to_offset(size_t idx, size_t obj_size)
70 BUILD_BUG_ON(obj_size > PAGE_SIZE);
72 if (!is_power_of_2(obj_size)) {
73 size_t objs_per_page = PAGE_SIZE / obj_size;
75 return (idx / objs_per_page) * PAGE_SIZE +
76 (idx % objs_per_page) * obj_size;
78 return idx * obj_size;
82 #define __genradix_cast(_radix) (typeof((_radix)->type[0]) *)
83 #define __genradix_obj_size(_radix) sizeof((_radix)->type[0])
84 #define __genradix_idx_to_offset(_radix, _idx) \
85 __idx_to_offset(_idx, __genradix_obj_size(_radix))
87 void *__genradix_ptr(struct __genradix *, size_t);
89 /* Returns a pointer to element at @_idx */
90 #define genradix_ptr(_radix, _idx) \
91 (__genradix_cast(_radix) \
92 __genradix_ptr(&(_radix)->tree, \
93 __genradix_idx_to_offset(_radix, _idx)))
95 void *__genradix_ptr_alloc(struct __genradix *, size_t, gfp_t);
97 /* Returns a pointer to element at @_idx, allocating it if necessary */
98 #define genradix_ptr_alloc(_radix, _idx, _gfp) \
99 (__genradix_cast(_radix) \
100 __genradix_ptr_alloc(&(_radix)->tree, \
101 __genradix_idx_to_offset(_radix, _idx), \
104 struct genradix_iter {
109 static inline void genradix_iter_init(struct genradix_iter *iter)
115 void *__genradix_iter_peek(struct genradix_iter *, struct __genradix *, size_t);
117 #define genradix_iter_peek(_iter, _radix) \
118 (__genradix_cast(_radix) \
119 __genradix_iter_peek(_iter, &(_radix)->tree, \
120 PAGE_SIZE / __genradix_obj_size(_radix)))
122 static inline void __genradix_iter_advance(struct genradix_iter *iter,
125 iter->offset += obj_size;
127 if (!is_power_of_2(obj_size) &&
128 (iter->offset & (PAGE_SIZE - 1)) + obj_size > PAGE_SIZE)
129 iter->offset = round_up(iter->offset, PAGE_SIZE);
134 #define genradix_iter_advance(_iter, _radix) \
135 __genradix_iter_advance(_iter, __genradix_obj_size(_radix))
137 #endif /* _LINUX_GENERIC_RADIX_TREE_H */