1c349dbc7Sjsg /* Public domain. */ 2c349dbc7Sjsg 3c349dbc7Sjsg #ifndef _LINUX_XARRAY_H 4c349dbc7Sjsg #define _LINUX_XARRAY_H 5c349dbc7Sjsg 6c349dbc7Sjsg #include <linux/gfp.h> 7c349dbc7Sjsg 8c349dbc7Sjsg #include <sys/tree.h> 9c349dbc7Sjsg 1022008fe3Sjsg #define XA_FLAGS_ALLOC (1 << 0) 1122008fe3Sjsg #define XA_FLAGS_ALLOC1 (1 << 1) 1222008fe3Sjsg #define XA_FLAGS_LOCK_IRQ (1 << 2) 13c349dbc7Sjsg 145ca02815Sjsg /* 155ca02815Sjsg * lower bits of pointer are tagged: 165ca02815Sjsg * 00: pointer 175ca02815Sjsg * 01: value 185ca02815Sjsg * 10: internal 195ca02815Sjsg */ 20c349dbc7Sjsg struct xarray_entry { 21c349dbc7Sjsg SPLAY_ENTRY(xarray_entry) entry; 22c349dbc7Sjsg int id; 23c349dbc7Sjsg void *ptr; 24c349dbc7Sjsg }; 25c349dbc7Sjsg 26c349dbc7Sjsg struct xarray { 27c349dbc7Sjsg gfp_t xa_flags; 285ca02815Sjsg struct mutex xa_lock; 29c349dbc7Sjsg SPLAY_HEAD(xarray_tree, xarray_entry) xa_tree; 30c349dbc7Sjsg }; 31c349dbc7Sjsg 32*b73929acSjsg #define DEFINE_XARRAY_ALLOC(name) \ 33*b73929acSjsg struct xarray name = { \ 34*b73929acSjsg .xa_flags = XA_FLAGS_ALLOC, \ 35*b73929acSjsg .xa_lock = MUTEX_INITIALIZER(IPL_NONE), \ 36*b73929acSjsg .xa_tree = SPLAY_INITIALIZER(&name.xa_tree) \ 37*b73929acSjsg } 38*b73929acSjsg 3922008fe3Sjsg struct xarray_range { 4022008fe3Sjsg uint32_t start; 4122008fe3Sjsg uint32_t end; 4222008fe3Sjsg }; 4322008fe3Sjsg 4422008fe3Sjsg #define XA_LIMIT(_start, _end) (struct xarray_range){ _start, _end } 4522008fe3Sjsg #define xa_limit_32b XA_LIMIT(0, UINT_MAX) 4622008fe3Sjsg 47c349dbc7Sjsg void xa_init_flags(struct xarray *, gfp_t); 48c349dbc7Sjsg void xa_destroy(struct xarray *); 4922008fe3Sjsg int __xa_alloc(struct xarray *, u32 *, void *, struct xarray_range, gfp_t); 5022008fe3Sjsg int __xa_alloc_cyclic(struct xarray *, u32 *, void *, struct xarray_range, 5122008fe3Sjsg u32 *, gfp_t); 525ca02815Sjsg void *__xa_load(struct xarray *, unsigned long); 535ca02815Sjsg void *__xa_store(struct xarray *, unsigned long, void *, gfp_t); 545ca02815Sjsg void *__xa_erase(struct xarray *, unsigned long); 55c349dbc7Sjsg void *xa_get_next(struct xarray *, unsigned long *); 56c349dbc7Sjsg 57c349dbc7Sjsg #define xa_for_each(xa, index, entry) \ 58c349dbc7Sjsg for (index = 0; ((entry) = xa_get_next(xa, &(index))) != NULL; index++) 59c349dbc7Sjsg 601bb76ff1Sjsg #define xa_lock(_xa) do { \ 611bb76ff1Sjsg mtx_enter(&(_xa)->xa_lock); \ 621bb76ff1Sjsg } while (0) 631bb76ff1Sjsg 641bb76ff1Sjsg #define xa_unlock(_xa) do { \ 651bb76ff1Sjsg mtx_leave(&(_xa)->xa_lock); \ 661bb76ff1Sjsg } while (0) 671bb76ff1Sjsg 681bb76ff1Sjsg #define xa_lock_irq(_xa) do { \ 691bb76ff1Sjsg mtx_enter(&(_xa)->xa_lock); \ 701bb76ff1Sjsg } while (0) 711bb76ff1Sjsg 721bb76ff1Sjsg #define xa_unlock_irq(_xa) do { \ 731bb76ff1Sjsg mtx_leave(&(_xa)->xa_lock); \ 741bb76ff1Sjsg } while (0) 751bb76ff1Sjsg 765ca02815Sjsg #define xa_lock_irqsave(_xa, _flags) do { \ 775ca02815Sjsg _flags = 0; \ 785ca02815Sjsg mtx_enter(&(_xa)->xa_lock); \ 795ca02815Sjsg } while (0) 805ca02815Sjsg 815ca02815Sjsg #define xa_unlock_irqrestore(_xa, _flags) do { \ 825ca02815Sjsg (void)(_flags); \ 835ca02815Sjsg mtx_leave(&(_xa)->xa_lock); \ 845ca02815Sjsg } while (0) 855ca02815Sjsg 86c349dbc7Sjsg static inline void * 87c349dbc7Sjsg xa_mk_value(unsigned long v) 88c349dbc7Sjsg { 89c349dbc7Sjsg unsigned long r = (v << 1) | 1; 90c349dbc7Sjsg return (void *)r; 91c349dbc7Sjsg } 92c349dbc7Sjsg 93c349dbc7Sjsg static inline bool 94c349dbc7Sjsg xa_is_value(const void *e) 95c349dbc7Sjsg { 96c349dbc7Sjsg unsigned long v = (unsigned long)e; 97c349dbc7Sjsg return v & 1; 98c349dbc7Sjsg } 99c349dbc7Sjsg 100c349dbc7Sjsg static inline unsigned long 101c349dbc7Sjsg xa_to_value(const void *e) 102c349dbc7Sjsg { 103c349dbc7Sjsg unsigned long v = (unsigned long)e; 104c349dbc7Sjsg return v >> 1; 105c349dbc7Sjsg } 106c349dbc7Sjsg 1075ca02815Sjsg #define XA_ERROR(x) ((struct xa_node *)(((unsigned long)x << 2) | 2)) 1085ca02815Sjsg 1095ca02815Sjsg static inline int 1105ca02815Sjsg xa_err(const void *e) 1115ca02815Sjsg { 1125ca02815Sjsg long v = (long)e; 1135ca02815Sjsg /* not tagged internal, not an errno */ 1145ca02815Sjsg if ((v & 3) != 2) 1155ca02815Sjsg return 0; 1165ca02815Sjsg v >>= 2; 1175ca02815Sjsg if (v >= -ELAST) 1185ca02815Sjsg return v; 1195ca02815Sjsg return 0; 1205ca02815Sjsg } 1215ca02815Sjsg 1225ca02815Sjsg static inline bool 1235ca02815Sjsg xa_is_err(const void *e) 1245ca02815Sjsg { 1255ca02815Sjsg return xa_err(e) != 0; 1265ca02815Sjsg } 1275ca02815Sjsg 1285ca02815Sjsg static inline int 12922008fe3Sjsg xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xarray_range xr, 13022008fe3Sjsg gfp_t gfp) 1315ca02815Sjsg { 1325ca02815Sjsg int r; 1335ca02815Sjsg mtx_enter(&xa->xa_lock); 13422008fe3Sjsg r = __xa_alloc(xa, id, entry, xr, gfp); 1355ca02815Sjsg mtx_leave(&xa->xa_lock); 1365ca02815Sjsg return r; 1375ca02815Sjsg } 1385ca02815Sjsg 1395ca02815Sjsg static inline void * 1405ca02815Sjsg xa_load(struct xarray *xa, unsigned long index) 1415ca02815Sjsg { 1425ca02815Sjsg void *r; 1435ca02815Sjsg r = __xa_load(xa, index); 1445ca02815Sjsg return r; 1455ca02815Sjsg } 1465ca02815Sjsg 1475ca02815Sjsg 1485ca02815Sjsg static inline void * 1495ca02815Sjsg xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 1505ca02815Sjsg { 1515ca02815Sjsg void *r; 1525ca02815Sjsg mtx_enter(&xa->xa_lock); 1535ca02815Sjsg r = __xa_store(xa, index, entry, gfp); 1545ca02815Sjsg mtx_leave(&xa->xa_lock); 1555ca02815Sjsg return r; 1565ca02815Sjsg } 1575ca02815Sjsg 1585ca02815Sjsg static inline void * 1595ca02815Sjsg xa_erase(struct xarray *xa, unsigned long index) 1605ca02815Sjsg { 1615ca02815Sjsg void *r; 1625ca02815Sjsg mtx_enter(&xa->xa_lock); 1635ca02815Sjsg r = __xa_erase(xa, index); 1645ca02815Sjsg mtx_leave(&xa->xa_lock); 1655ca02815Sjsg return r; 1665ca02815Sjsg } 1675ca02815Sjsg 1685ca02815Sjsg static inline void * 1695ca02815Sjsg xa_store_irq(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 1705ca02815Sjsg { 1715ca02815Sjsg void *r; 1725ca02815Sjsg mtx_enter(&xa->xa_lock); 1735ca02815Sjsg r = __xa_store(xa, index, entry, gfp); 1745ca02815Sjsg mtx_leave(&xa->xa_lock); 1755ca02815Sjsg return r; 1765ca02815Sjsg } 1775ca02815Sjsg 1785ca02815Sjsg static inline void * 1795ca02815Sjsg xa_erase_irq(struct xarray *xa, unsigned long index) 1805ca02815Sjsg { 1815ca02815Sjsg void *r; 1825ca02815Sjsg mtx_enter(&xa->xa_lock); 1835ca02815Sjsg r = __xa_erase(xa, index); 1845ca02815Sjsg mtx_leave(&xa->xa_lock); 1855ca02815Sjsg return r; 1865ca02815Sjsg } 1875ca02815Sjsg 1885ca02815Sjsg static inline bool 1895ca02815Sjsg xa_empty(const struct xarray *xa) 1905ca02815Sjsg { 1915ca02815Sjsg return SPLAY_EMPTY(&xa->xa_tree); 1925ca02815Sjsg } 1935ca02815Sjsg 194a8551f48Sjsg static inline void 195a8551f48Sjsg xa_init(struct xarray *xa) 196a8551f48Sjsg { 197a8551f48Sjsg xa_init_flags(xa, 0); 198a8551f48Sjsg } 199a8551f48Sjsg 200c349dbc7Sjsg #endif 201