1 /* Public domain. */ 2 3 #ifndef _LINUX_XARRAY_H 4 #define _LINUX_XARRAY_H 5 6 #include <linux/gfp.h> 7 8 #include <sys/tree.h> 9 10 #define XA_FLAGS_ALLOC 1 11 #define XA_FLAGS_ALLOC1 2 12 #define XA_FLAGS_LOCK_IRQ 4 13 14 /* 15 * lower bits of pointer are tagged: 16 * 00: pointer 17 * 01: value 18 * 10: internal 19 */ 20 struct xarray_entry { 21 SPLAY_ENTRY(xarray_entry) entry; 22 int id; 23 void *ptr; 24 }; 25 26 struct xarray { 27 gfp_t xa_flags; 28 struct mutex xa_lock; 29 SPLAY_HEAD(xarray_tree, xarray_entry) xa_tree; 30 }; 31 32 void xa_init_flags(struct xarray *, gfp_t); 33 void xa_destroy(struct xarray *); 34 int __xa_alloc(struct xarray *, u32 *, void *, int, gfp_t); 35 void *__xa_load(struct xarray *, unsigned long); 36 void *__xa_store(struct xarray *, unsigned long, void *, gfp_t); 37 void *__xa_erase(struct xarray *, unsigned long); 38 void *xa_get_next(struct xarray *, unsigned long *); 39 40 #define xa_for_each(xa, index, entry) \ 41 for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++) 42 43 #define xa_limit_32b 0 44 45 #define xa_lock_irqsave(_xa, _flags) do { \ 46 _flags = 0; \ 47 mtx_enter(&(_xa)->xa_lock); \ 48 } while (0) 49 50 #define xa_unlock_irqrestore(_xa, _flags) do { \ 51 (void)(_flags); \ 52 mtx_leave(&(_xa)->xa_lock); \ 53 } while (0) 54 55 static inline void * 56 xa_mk_value(unsigned long v) 57 { 58 unsigned long r = (v << 1) | 1; 59 return (void *)r; 60 } 61 62 static inline bool 63 xa_is_value(const void *e) 64 { 65 unsigned long v = (unsigned long)e; 66 return v & 1; 67 } 68 69 static inline unsigned long 70 xa_to_value(const void *e) 71 { 72 unsigned long v = (unsigned long)e; 73 return v >> 1; 74 } 75 76 #define XA_ERROR(x) ((struct xa_node *)(((unsigned long)x << 2) | 2)) 77 78 static inline int 79 xa_err(const void *e) 80 { 81 long v = (long)e; 82 /* not tagged internal, not an errno */ 83 if ((v & 3) != 2) 84 return 0; 85 v >>= 2; 86 if (v >= -ELAST) 87 return v; 88 return 0; 89 } 90 91 static inline bool 92 xa_is_err(const void *e) 93 { 94 return xa_err(e) != 0; 95 } 96 97 static inline int 98 xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp) 99 { 100 int r; 101 mtx_enter(&xa->xa_lock); 102 r = __xa_alloc(xa, id, entry, limit, gfp); 103 mtx_leave(&xa->xa_lock); 104 return r; 105 } 106 107 static inline void * 108 xa_load(struct xarray *xa, unsigned long index) 109 { 110 void *r; 111 r = __xa_load(xa, index); 112 return r; 113 } 114 115 116 static inline void * 117 xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 118 { 119 void *r; 120 mtx_enter(&xa->xa_lock); 121 r = __xa_store(xa, index, entry, gfp); 122 mtx_leave(&xa->xa_lock); 123 return r; 124 } 125 126 static inline void * 127 xa_erase(struct xarray *xa, unsigned long index) 128 { 129 void *r; 130 mtx_enter(&xa->xa_lock); 131 r = __xa_erase(xa, index); 132 mtx_leave(&xa->xa_lock); 133 return r; 134 } 135 136 static inline void * 137 xa_store_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 138 { 139 void *r; 140 mtx_enter(&xa->xa_lock); 141 r = __xa_store(xa, index, entry, gfp); 142 mtx_leave(&xa->xa_lock); 143 return r; 144 } 145 146 static inline void * 147 xa_erase_irq(struct xarray *xa, unsigned long index) 148 { 149 void *r; 150 mtx_enter(&xa->xa_lock); 151 r = __xa_erase(xa, index); 152 mtx_leave(&xa->xa_lock); 153 return r; 154 } 155 156 static inline bool 157 xa_empty(const struct xarray *xa) 158 { 159 return SPLAY_EMPTY(&xa->xa_tree); 160 } 161 162 #endif 163