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 lock 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 int __xa_alloc_cyclic(struct xarray *, u32 *, void *, int, u32 *, gfp_t); 36 void *__xa_load(struct xarray *, unsigned long); 37 void *__xa_store(struct xarray *, unsigned long, void *, gfp_t); 38 void *__xa_erase(struct xarray *, unsigned long); 39 void *xa_get_next(struct xarray *, unsigned long *); 40 41#define xa_for_each(xa, index, entry) \ 42 for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++) 43 44#define xa_limit_32b 0 45 46#define xa_lock(_xa) do { \ 47 lockmgr(&(_xa)->xa_lock, LK_EXCLUSIVE); \ 48 } while (0) 49 50#define xa_unlock(_xa) do { \ 51 lockmgr(&(_xa)->xa_lock, LK_RELEASE); \ 52 } while (0) 53 54#define xa_lock_irq(_xa) do { \ 55 lockmgr(&(_xa)->xa_lock, LK_EXCLUSIVE); \ 56 } while (0) 57 58#define xa_unlock_irq(_xa) do { \ 59 lockmgr(&(_xa)->xa_lock, LK_RELEASE); \ 60 } while (0) 61 62#define xa_lock_irqsave(_xa, _flags) do { \ 63 _flags = 0; \ 64 lockmgr(&(_xa)->xa_lock, LK_EXCLUSIVE); \ 65 } while (0) 66 67#define xa_unlock_irqrestore(_xa, _flags) do { \ 68 (void)(_flags); \ 69 lockmgr(&(_xa)->xa_lock, LK_RELEASE); \ 70 } while (0) 71 72 static inline void * 73 xa_mk_value(unsigned long v) 74{ 75 unsigned long r = (v << 1) | 1; 76 return (void *)r; 77} 78 79 static inline bool 80 xa_is_value(const void *e) 81{ 82 unsigned long v = (unsigned long)e; 83 return v & 1; 84} 85 86 static inline unsigned long 87 xa_to_value(const void *e) 88{ 89 unsigned long v = (unsigned long)e; 90 return v >> 1; 91} 92 93#define XA_ERROR(x) ((struct xa_node *)(((unsigned long)x << 2) | 2)) 94 95 static inline int 96 xa_err(const void *e) 97{ 98 long v = (long)e; 99 /* not tagged internal, not an errno */ 100 if ((v & 3) != 2) 101 return 0; 102 v >>= 2; 103 if (v >= -ELAST) 104 return v; 105 return 0; 106} 107 108 static inline bool 109 xa_is_err(const void *e) 110{ 111 return xa_err(e) != 0; 112} 113 114 static inline int 115 xa_alloc(struct xarray *xa, u32 *id, void *entry, int limit, gfp_t gfp) 116{ 117 int r; 118 lockmgr(&xa->xa_lock, LK_EXCLUSIVE); 119 r = __xa_alloc(xa, id, entry, limit, gfp); 120 lockmgr(&xa->xa_lock, LK_RELEASE); 121 return r; 122} 123 124 static inline void * 125 xa_load(struct xarray *xa, unsigned long index) 126{ 127 void *r; 128 r = __xa_load(xa, index); 129 return r; 130} 131 132 133 static inline void * 134 xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 135{ 136 void *r; 137 lockmgr(&xa->xa_lock, LK_EXCLUSIVE); 138 r = __xa_store(xa, index, entry, gfp); 139 lockmgr(&xa->xa_lock, LK_RELEASE); 140 return r; 141} 142 143 static inline void * 144 xa_erase(struct xarray *xa, unsigned long index) 145{ 146 void *r; 147 lockmgr(&xa->xa_lock, LK_EXCLUSIVE); 148 r = __xa_erase(xa, index); 149 lockmgr(&xa->xa_lock, LK_RELEASE); 150 return r; 151} 152 153 static inline void * 154 xa_store_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 155{ 156 void *r; 157 lockmgr(&xa->xa_lock, LK_EXCLUSIVE); 158 r = __xa_store(xa, index, entry, gfp); 159 lockmgr(&xa->xa_lock, LK_RELEASE); 160 return r; 161} 162 163 static inline void * 164 xa_erase_irq(struct xarray *xa, unsigned long index) 165{ 166 void *r; 167 lockmgr(&xa->xa_lock, LK_EXCLUSIVE); 168 r = __xa_erase(xa, index); 169 lockmgr(&xa->xa_lock, LK_RELEASE); 170 return r; 171} 172 173 static inline bool 174 xa_empty(const struct xarray *xa) 175{ 176 return SPLAY_EMPTY(&xa->xa_tree); 177} 178 179 static inline void 180 xa_init(struct xarray *xa) 181{ 182 xa_init_flags(xa, 0); 183} 184 185#endif