rdxtree.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /*
  2. * Copyright (c) 2011-2015 Richard Braun.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. *
  26. * Upstream site with license notes :
  27. * http://git.sceen.net/rbraun/librbraun.git/
  28. */
  29. #include <linux/bitops.h>
  30. #include <glue/gnulinux.h>
  31. #include <kern/assert.h>
  32. #include <kern/slab.h>
  33. #include <mach/kern_return.h>
  34. #include <stddef.h>
  35. #include <string.h>
  36. #include "macros.h"
  37. #include "rdxtree.h"
  38. #include "rdxtree_i.h"
  39. /* XXX */
  40. #define CHAR_BIT 8U
  41. #define ERR_SUCCESS KERN_SUCCESS
  42. #define ERR_BUSY KERN_INVALID_ARGUMENT
  43. #define ERR_NOMEM KERN_RESOURCE_SHORTAGE
  44. /*
  45. * Mask applied on an entry to obtain its address.
  46. */
  47. #define RDXTREE_ENTRY_ADDR_MASK (~0x3UL)
  48. /*
  49. * Global properties used to shape radix trees.
  50. */
  51. #define RDXTREE_RADIX 6
  52. #define RDXTREE_RADIX_SIZE (1UL << RDXTREE_RADIX)
  53. #define RDXTREE_RADIX_MASK (RDXTREE_RADIX_SIZE - 1)
  54. #if RDXTREE_RADIX < 6
  55. #error "you shall not pass"
  56. typedef unsigned long rdxtree_bm_t;
  57. #define rdxtree_ffs(x) __gnu_builtin_ffsl(x)
  58. #elif RDXTREE_RADIX == 6 /* RDXTREE_RADIX < 6 */
  59. typedef unsigned long long rdxtree_bm_t;
  60. #define rdxtree_ffs(x) __ffs64(x)
  61. #else /* RDXTREE_RADIX < 6 */
  62. #error "radix too high"
  63. #endif /* RDXTREE_RADIX < 6 */
  64. /*
  65. * Allocation bitmap size in bits.
  66. */
  67. #define RDXTREE_BM_SIZE (sizeof(rdxtree_bm_t) * CHAR_BIT)
  68. /*
  69. * Empty/full allocation bitmap words.
  70. */
  71. #define RDXTREE_BM_EMPTY ((rdxtree_bm_t)0)
  72. #define RDXTREE_BM_FULL \
  73. ((~(rdxtree_bm_t)0) >> (RDXTREE_BM_SIZE - RDXTREE_RADIX_SIZE))
  74. /*
  75. * These macros can be replaced by actual functions in an environment
  76. * that provides lockless synchronization such as RCU.
  77. */
  78. #define llsync_assign_ptr(ptr, value) ((ptr) = (value))
  79. #define llsync_read_ptr(ptr) (ptr)
  80. /*
  81. * Radix tree node.
  82. *
  83. * The height of a tree is the number of nodes to traverse until stored
  84. * pointers are reached. A height of 0 means the entries of a node (or the
  85. * tree root) directly point to stored pointers.
  86. *
  87. * The index is valid if and only if the parent isn't NULL.
  88. *
  89. * Concerning the allocation bitmap, a bit is set when the node it denotes,
  90. * or one of its children, can be used to allocate an entry. Conversely, a bit
  91. * is clear when the matching node and all of its children have no free entry.
  92. *
  93. * In order to support safe lockless lookups, in particular during a resize,
  94. * each node includes the height of its subtree, which is invariant during
  95. * the entire node lifetime. Since the tree height does vary, it can't be
  96. * used to determine whether the tree root is a node or a stored pointer.
  97. * This implementation assumes that all nodes and stored pointers are at least
  98. * 4-byte aligned, and uses the least significant bit of entries to indicate
  99. * the pointer type. This bit is set for internal nodes, and clear for stored
  100. * pointers so that they can be accessed from slots without conversion.
  101. */
  102. struct rdxtree_node {
  103. struct rdxtree_node *parent;
  104. unsigned int index;
  105. unsigned int height;
  106. unsigned int nr_entries;
  107. rdxtree_bm_t alloc_bm;
  108. void *entries[RDXTREE_RADIX_SIZE];
  109. };
  110. /*
  111. * We allocate nodes using the slab allocator.
  112. */
  113. static struct gnu_kmem_cache rdxtree_node_cache;
  114. void
  115. rdxtree_cache_init(void)
  116. {
  117. gnu_kmem_cache_init(&rdxtree_node_cache, "rdxtree_node",
  118. sizeof(struct rdxtree_node), 0, NULL, 0);
  119. }
  120. #ifdef RDXTREE_ENABLE_NODE_CREATION_FAILURES
  121. unsigned int rdxtree_fail_node_creation_threshold;
  122. unsigned int rdxtree_nr_node_creations;
  123. #endif /* RDXTREE_ENABLE_NODE_CREATION_FAILURES */
  124. static inline int
  125. rdxtree_check_alignment(const void *ptr)
  126. {
  127. return ((unsigned long)ptr & ~RDXTREE_ENTRY_ADDR_MASK) == 0;
  128. }
  129. static inline void *
  130. rdxtree_entry_addr(void *entry)
  131. {
  132. return (void *)((unsigned long)entry & RDXTREE_ENTRY_ADDR_MASK);
  133. }
  134. static inline int
  135. rdxtree_entry_is_node(const void *entry)
  136. {
  137. return ((unsigned long)entry & 1) != 0;
  138. }
  139. static inline void *
  140. rdxtree_node_to_entry(struct rdxtree_node *node)
  141. {
  142. return (void *)((unsigned long)node | 1);
  143. }
  144. static int
  145. rdxtree_node_create(struct rdxtree_node **nodep, unsigned int height)
  146. {
  147. struct rdxtree_node *node;
  148. #ifdef RDXTREE_ENABLE_NODE_CREATION_FAILURES
  149. if (rdxtree_fail_node_creation_threshold != 0) {
  150. rdxtree_nr_node_creations++;
  151. if (rdxtree_nr_node_creations == rdxtree_fail_node_creation_threshold)
  152. return ERR_NOMEM;
  153. }
  154. #endif /* RDXTREE_ENABLE_NODE_CREATION_FAILURES */
  155. node = (struct rdxtree_node *) gnu_kmem_cache_alloc(&rdxtree_node_cache);
  156. if (node == NULL)
  157. return ERR_NOMEM;
  158. assert(rdxtree_check_alignment(node));
  159. node->parent = NULL;
  160. node->height = height;
  161. node->nr_entries = 0;
  162. node->alloc_bm = RDXTREE_BM_FULL;
  163. memset(node->entries, 0, sizeof(node->entries));
  164. *nodep = node;
  165. return 0;
  166. }
  167. static void
  168. rdxtree_node_schedule_destruction(struct rdxtree_node *node)
  169. {
  170. /*
  171. * This function is intended to use the appropriate interface to defer
  172. * destruction until all read-side references are dropped in an
  173. * environment that provides lockless synchronization.
  174. *
  175. * Otherwise, it simply "schedules" destruction immediately.
  176. */
  177. gnu_kmem_cache_free(&rdxtree_node_cache, (vm_offset_t) node);
  178. }
  179. static inline void
  180. rdxtree_node_link(struct rdxtree_node *node, struct rdxtree_node *parent,
  181. unsigned int index)
  182. {
  183. node->parent = parent;
  184. node->index = index;
  185. }
  186. static inline void
  187. rdxtree_node_unlink(struct rdxtree_node *node)
  188. {
  189. assert(node->parent != NULL);
  190. node->parent = NULL;
  191. }
  192. static inline int
  193. rdxtree_node_full(struct rdxtree_node *node)
  194. {
  195. return (node->nr_entries == ARRAY_SIZE(node->entries));
  196. }
  197. static inline int
  198. rdxtree_node_empty(struct rdxtree_node *node)
  199. {
  200. return (node->nr_entries == 0);
  201. }
  202. static inline void
  203. rdxtree_node_insert(struct rdxtree_node *node, unsigned int index,
  204. void *entry)
  205. {
  206. assert(index < ARRAY_SIZE(node->entries));
  207. assert(node->entries[index] == NULL);
  208. node->nr_entries++;
  209. llsync_assign_ptr(node->entries[index], entry);
  210. }
  211. static inline void
  212. rdxtree_node_insert_node(struct rdxtree_node *node, unsigned int index,
  213. struct rdxtree_node *child)
  214. {
  215. rdxtree_node_insert(node, index, rdxtree_node_to_entry(child));
  216. }
  217. static inline void
  218. rdxtree_node_remove(struct rdxtree_node *node, unsigned int index)
  219. {
  220. assert(index < ARRAY_SIZE(node->entries));
  221. assert(node->entries[index] != NULL);
  222. node->nr_entries--;
  223. llsync_assign_ptr(node->entries[index], NULL);
  224. }
  225. static inline void *
  226. rdxtree_node_find(struct rdxtree_node *node, unsigned int *indexp)
  227. {
  228. unsigned int index;
  229. void *ptr;
  230. index = *indexp;
  231. while (index < ARRAY_SIZE(node->entries)) {
  232. ptr = rdxtree_entry_addr(llsync_read_ptr(node->entries[index]));
  233. if (ptr != NULL) {
  234. *indexp = index;
  235. return ptr;
  236. }
  237. index++;
  238. }
  239. return NULL;
  240. }
  241. static inline void
  242. rdxtree_node_bm_set(struct rdxtree_node *node, unsigned int index)
  243. {
  244. node->alloc_bm |= (rdxtree_bm_t)1 << index;
  245. }
  246. static inline void
  247. rdxtree_node_bm_clear(struct rdxtree_node *node, unsigned int index)
  248. {
  249. node->alloc_bm &= ~((rdxtree_bm_t)1 << index);
  250. }
  251. static inline int
  252. rdxtree_node_bm_is_set(struct rdxtree_node *node, unsigned int index)
  253. {
  254. return (node->alloc_bm & ((rdxtree_bm_t)1 << index));
  255. }
  256. static inline int
  257. rdxtree_node_bm_empty(struct rdxtree_node *node)
  258. {
  259. return (node->alloc_bm == RDXTREE_BM_EMPTY);
  260. }
  261. static inline unsigned int
  262. rdxtree_node_bm_first(struct rdxtree_node *node)
  263. {
  264. return rdxtree_ffs(node->alloc_bm) - 1;
  265. }
  266. static inline rdxtree_key_t
  267. rdxtree_max_key(unsigned int height)
  268. {
  269. size_t shift;
  270. shift = RDXTREE_RADIX * height;
  271. if (likely(shift < (sizeof(rdxtree_key_t) * CHAR_BIT)))
  272. return ((rdxtree_key_t)1 << shift) - 1;
  273. else
  274. return ~((rdxtree_key_t)0);
  275. }
  276. static void
  277. rdxtree_shrink(struct rdxtree *tree)
  278. {
  279. struct rdxtree_node *node;
  280. void *entry;
  281. while (tree->height > 0) {
  282. node = rdxtree_entry_addr(tree->root);
  283. if (node->nr_entries != 1)
  284. break;
  285. entry = node->entries[0];
  286. if (entry == NULL)
  287. break;
  288. tree->height--;
  289. if (tree->height > 0)
  290. rdxtree_node_unlink(rdxtree_entry_addr(entry));
  291. llsync_assign_ptr(tree->root, entry);
  292. rdxtree_node_schedule_destruction(node);
  293. }
  294. }
  295. static int
  296. rdxtree_grow(struct rdxtree *tree, rdxtree_key_t key)
  297. {
  298. struct rdxtree_node *root, *node;
  299. unsigned int new_height;
  300. int error;
  301. new_height = tree->height + 1;
  302. while (key > rdxtree_max_key(new_height))
  303. new_height++;
  304. if (tree->root == NULL) {
  305. tree->height = new_height;
  306. return ERR_SUCCESS;
  307. }
  308. root = rdxtree_entry_addr(tree->root);
  309. do {
  310. error = rdxtree_node_create(&node, tree->height);
  311. if (error) {
  312. rdxtree_shrink(tree);
  313. return error;
  314. }
  315. if (tree->height == 0)
  316. rdxtree_node_bm_clear(node, 0);
  317. else {
  318. rdxtree_node_link(root, node, 0);
  319. if (rdxtree_node_bm_empty(root))
  320. rdxtree_node_bm_clear(node, 0);
  321. }
  322. rdxtree_node_insert(node, 0, tree->root);
  323. tree->height++;
  324. llsync_assign_ptr(tree->root, rdxtree_node_to_entry(node));
  325. root = node;
  326. } while (new_height > tree->height);
  327. return ERR_SUCCESS;
  328. }
  329. static void
  330. rdxtree_cleanup(struct rdxtree *tree, struct rdxtree_node *node)
  331. {
  332. struct rdxtree_node *prev;
  333. for (;;) {
  334. if (likely(!rdxtree_node_empty(node))) {
  335. if (unlikely(node->parent == NULL))
  336. rdxtree_shrink(tree);
  337. break;
  338. }
  339. if (node->parent == NULL) {
  340. tree->height = 0;
  341. llsync_assign_ptr(tree->root, NULL);
  342. rdxtree_node_schedule_destruction(node);
  343. break;
  344. }
  345. prev = node;
  346. node = node->parent;
  347. rdxtree_node_unlink(prev);
  348. rdxtree_node_remove(node, prev->index);
  349. rdxtree_node_schedule_destruction(prev);
  350. }
  351. }
  352. static void
  353. rdxtree_insert_bm_clear(struct rdxtree_node *node, unsigned int index)
  354. {
  355. for (;;) {
  356. rdxtree_node_bm_clear(node, index);
  357. if (!rdxtree_node_full(node) || (node->parent == NULL))
  358. break;
  359. index = node->index;
  360. node = node->parent;
  361. }
  362. }
  363. int
  364. rdxtree_insert_common(struct rdxtree *tree, rdxtree_key_t key,
  365. void *ptr, void ***slotp)
  366. {
  367. struct rdxtree_node *node, *prev;
  368. unsigned int height, shift, index = index;
  369. int error;
  370. assert(ptr != NULL);
  371. assert(rdxtree_check_alignment(ptr));
  372. if (unlikely(key > rdxtree_max_key(tree->height))) {
  373. error = rdxtree_grow(tree, key);
  374. if (error)
  375. return error;
  376. }
  377. height = tree->height;
  378. if (unlikely(height == 0)) {
  379. if (tree->root != NULL)
  380. return ERR_BUSY;
  381. llsync_assign_ptr(tree->root, ptr);
  382. if (slotp != NULL)
  383. *slotp = &tree->root;
  384. return ERR_SUCCESS;
  385. }
  386. node = rdxtree_entry_addr(tree->root);
  387. shift = (height - 1) * RDXTREE_RADIX;
  388. prev = NULL;
  389. do {
  390. if (node == NULL) {
  391. error = rdxtree_node_create(&node, height - 1);
  392. if (error) {
  393. if (prev == NULL)
  394. tree->height = 0;
  395. else
  396. rdxtree_cleanup(tree, prev);
  397. return error;
  398. }
  399. if (prev == NULL)
  400. llsync_assign_ptr(tree->root, rdxtree_node_to_entry(node));
  401. else {
  402. rdxtree_node_link(node, prev, index);
  403. rdxtree_node_insert_node(prev, index, node);
  404. }
  405. }
  406. prev = node;
  407. index = (unsigned int)(key >> shift) & RDXTREE_RADIX_MASK;
  408. node = rdxtree_entry_addr(prev->entries[index]);
  409. shift -= RDXTREE_RADIX;
  410. height--;
  411. } while (height > 0);
  412. if (unlikely(node != NULL))
  413. return ERR_BUSY;
  414. rdxtree_node_insert(prev, index, ptr);
  415. rdxtree_insert_bm_clear(prev, index);
  416. if (slotp != NULL)
  417. *slotp = &prev->entries[index];
  418. return ERR_SUCCESS;
  419. }
  420. int
  421. rdxtree_insert_alloc_common(struct rdxtree *tree, void *ptr,
  422. rdxtree_key_t *keyp, void ***slotp)
  423. {
  424. struct rdxtree_node *node, *prev;
  425. unsigned int height, shift, index = index;
  426. rdxtree_key_t key;
  427. int error;
  428. assert(ptr != NULL);
  429. assert(rdxtree_check_alignment(ptr));
  430. height = tree->height;
  431. if (unlikely(height == 0)) {
  432. if (tree->root == NULL) {
  433. llsync_assign_ptr(tree->root, ptr);
  434. *keyp = 0;
  435. if (slotp != NULL)
  436. *slotp = &tree->root;
  437. return ERR_SUCCESS;
  438. }
  439. goto grow;
  440. }
  441. node = rdxtree_entry_addr(tree->root);
  442. key = 0;
  443. shift = (height - 1) * RDXTREE_RADIX;
  444. prev = NULL;
  445. do {
  446. if (node == NULL) {
  447. error = rdxtree_node_create(&node, height - 1);
  448. if (error) {
  449. rdxtree_cleanup(tree, prev);
  450. return error;
  451. }
  452. rdxtree_node_link(node, prev, index);
  453. rdxtree_node_insert_node(prev, index, node);
  454. }
  455. prev = node;
  456. index = rdxtree_node_bm_first(node);
  457. if (index == (unsigned int)-1)
  458. goto grow;
  459. key |= (rdxtree_key_t)index << shift;
  460. node = rdxtree_entry_addr(node->entries[index]);
  461. shift -= RDXTREE_RADIX;
  462. height--;
  463. } while (height > 0);
  464. rdxtree_node_insert(prev, index, ptr);
  465. rdxtree_insert_bm_clear(prev, index);
  466. if (slotp != NULL)
  467. *slotp = &prev->entries[index];
  468. goto out;
  469. grow:
  470. key = rdxtree_max_key(height) + 1;
  471. error = rdxtree_insert_common(tree, key, ptr, slotp);
  472. if (error)
  473. return error;
  474. out:
  475. *keyp = key;
  476. return ERR_SUCCESS;
  477. }
  478. static void
  479. rdxtree_remove_bm_set(struct rdxtree_node *node, unsigned int index)
  480. {
  481. do {
  482. rdxtree_node_bm_set(node, index);
  483. if (node->parent == NULL)
  484. break;
  485. index = node->index;
  486. node = node->parent;
  487. } while (!rdxtree_node_bm_is_set(node, index));
  488. }
  489. void *
  490. rdxtree_remove(struct rdxtree *tree, rdxtree_key_t key)
  491. {
  492. struct rdxtree_node *node, *prev;
  493. unsigned int height, shift, index;
  494. height = tree->height;
  495. if (unlikely(key > rdxtree_max_key(height)))
  496. return NULL;
  497. node = rdxtree_entry_addr(tree->root);
  498. if (unlikely(height == 0)) {
  499. llsync_assign_ptr(tree->root, NULL);
  500. return node;
  501. }
  502. shift = (height - 1) * RDXTREE_RADIX;
  503. do {
  504. if (node == NULL)
  505. return NULL;
  506. prev = node;
  507. index = (unsigned int)(key >> shift) & RDXTREE_RADIX_MASK;
  508. node = rdxtree_entry_addr(node->entries[index]);
  509. shift -= RDXTREE_RADIX;
  510. height--;
  511. } while (height > 0);
  512. if (node == NULL)
  513. return NULL;
  514. rdxtree_node_remove(prev, index);
  515. rdxtree_remove_bm_set(prev, index);
  516. rdxtree_cleanup(tree, prev);
  517. return node;
  518. }
  519. void *
  520. rdxtree_lookup_common(const struct rdxtree *tree, rdxtree_key_t key,
  521. int get_slot)
  522. {
  523. struct rdxtree_node *node, *prev;
  524. unsigned int height, shift, index;
  525. void *entry;
  526. entry = llsync_read_ptr(tree->root);
  527. if (entry == NULL) {
  528. node = NULL;
  529. height = 0;
  530. } else {
  531. node = rdxtree_entry_addr(entry);
  532. height = rdxtree_entry_is_node(entry) ? node->height + 1 : 0;
  533. }
  534. if (key > rdxtree_max_key(height))
  535. return NULL;
  536. if (height == 0) {
  537. if (node == NULL)
  538. return NULL;
  539. return get_slot ? (void *)&tree->root : node;
  540. }
  541. shift = (height - 1) * RDXTREE_RADIX;
  542. do {
  543. if (node == NULL)
  544. return NULL;
  545. prev = node;
  546. index = (unsigned int)(key >> shift) & RDXTREE_RADIX_MASK;
  547. entry = llsync_read_ptr(node->entries[index]);
  548. node = rdxtree_entry_addr(entry);
  549. shift -= RDXTREE_RADIX;
  550. height--;
  551. } while (height > 0);
  552. if (node == NULL)
  553. return NULL;
  554. return get_slot ? (void *)&prev->entries[index] : node;
  555. }
  556. void *
  557. rdxtree_replace_slot(void **slot, void *ptr)
  558. {
  559. void *old;
  560. assert(ptr != NULL);
  561. assert(rdxtree_check_alignment(ptr));
  562. old = *slot;
  563. assert(old != NULL);
  564. assert(rdxtree_check_alignment(old));
  565. llsync_assign_ptr(*slot, ptr);
  566. return old;
  567. }
  568. static void *
  569. rdxtree_walk_next(struct rdxtree *tree, struct rdxtree_iter *iter)
  570. {
  571. struct rdxtree_node *root, *node, *prev;
  572. unsigned int height, shift, index, orig_index;
  573. rdxtree_key_t key;
  574. void *entry;
  575. entry = llsync_read_ptr(tree->root);
  576. if (entry == NULL)
  577. return NULL;
  578. if (!rdxtree_entry_is_node(entry)) {
  579. if (iter->key != (rdxtree_key_t)-1)
  580. return NULL;
  581. else {
  582. iter->key = 0;
  583. return rdxtree_entry_addr(entry);
  584. }
  585. }
  586. key = iter->key + 1;
  587. if ((key == 0) && (iter->node != NULL))
  588. return NULL;
  589. root = rdxtree_entry_addr(entry);
  590. restart:
  591. node = root;
  592. height = root->height + 1;
  593. if (key > rdxtree_max_key(height))
  594. return NULL;
  595. shift = (height - 1) * RDXTREE_RADIX;
  596. do {
  597. prev = node;
  598. index = (key >> shift) & RDXTREE_RADIX_MASK;
  599. orig_index = index;
  600. node = rdxtree_node_find(node, &index);
  601. if (node == NULL) {
  602. shift += RDXTREE_RADIX;
  603. key = ((key >> shift) + 1) << shift;
  604. if (key == 0)
  605. return NULL;
  606. goto restart;
  607. }
  608. if (orig_index != index)
  609. key = ((key >> shift) + (index - orig_index)) << shift;
  610. shift -= RDXTREE_RADIX;
  611. height--;
  612. } while (height > 0);
  613. iter->node = prev;
  614. iter->key = key;
  615. return node;
  616. }
  617. void *
  618. rdxtree_walk(struct rdxtree *tree, struct rdxtree_iter *iter)
  619. {
  620. unsigned int index, orig_index;
  621. void *ptr;
  622. if (iter->node == NULL)
  623. return rdxtree_walk_next(tree, iter);
  624. index = (iter->key + 1) & RDXTREE_RADIX_MASK;
  625. if (index != 0) {
  626. orig_index = index;
  627. ptr = rdxtree_node_find(iter->node, &index);
  628. if (ptr != NULL) {
  629. iter->key += (index - orig_index) + 1;
  630. return ptr;
  631. }
  632. }
  633. return rdxtree_walk_next(tree, iter);
  634. }
  635. void
  636. rdxtree_remove_all(struct rdxtree *tree)
  637. {
  638. struct rdxtree_node *node, *parent;
  639. struct rdxtree_iter iter;
  640. if (tree->height == 0) {
  641. if (tree->root != NULL)
  642. llsync_assign_ptr(tree->root, NULL);
  643. return;
  644. }
  645. for (;;) {
  646. rdxtree_iter_init(&iter);
  647. rdxtree_walk_next(tree, &iter);
  648. if (iter.node == NULL)
  649. break;
  650. node = iter.node;
  651. parent = node->parent;
  652. if (parent == NULL)
  653. rdxtree_init(tree);
  654. else {
  655. rdxtree_node_remove(parent, node->index);
  656. rdxtree_remove_bm_set(parent, node->index);
  657. rdxtree_cleanup(tree, parent);
  658. node->parent = NULL;
  659. }
  660. rdxtree_node_schedule_destruction(node);
  661. }
  662. }