rdxtree.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. /*
  2. * Copyright (c) 2011-2018 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Upstream site with license notes :
  18. * http://git.sceen.net/rbraun/librbraun.git/
  19. */
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <stdbool.h>
  24. #include <stddef.h>
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include <kern/init.h>
  28. #include <kern/kmem.h>
  29. #include <kern/macros.h>
  30. #include <kern/rcu.h>
  31. #include <kern/rdxtree.h>
  32. #include <kern/work.h>
  33. // Mask applied on an entry to obtain its address.
  34. #define RDXTREE_ENTRY_ADDR_MASK (~0x3UL)
  35. // Global properties used to shape radix trees.
  36. #define RDXTREE_RADIX 6
  37. #define RDXTREE_RADIX_SIZE (1UL << RDXTREE_RADIX)
  38. #define RDXTREE_RADIX_MASK (RDXTREE_RADIX_SIZE - 1)
  39. #if RDXTREE_RADIX < 6
  40. typedef unsigned long rdxtree_bm_t;
  41. #define rdxtree_ffs __builtin_ffsl
  42. #elif RDXTREE_RADIX == 6
  43. typedef unsigned long long rdxtree_bm_t;
  44. #define rdxtree_ffs __builtin_ffsll
  45. #else
  46. #error "radix too high"
  47. #endif
  48. // Allocation bitmap size in bits.
  49. #define RDXTREE_BM_SIZE (sizeof (rdxtree_bm_t) * CHAR_BIT)
  50. // Empty/full allocation bitmap words.
  51. #define RDXTREE_BM_EMPTY ((rdxtree_bm_t)0)
  52. #define RDXTREE_BM_FULL \
  53. ((~(rdxtree_bm_t)0) >> (RDXTREE_BM_SIZE - RDXTREE_RADIX_SIZE))
  54. /*
  55. * Radix tree node.
  56. *
  57. * The height of a tree is the number of nodes to traverse until stored
  58. * pointers are reached. A height of 0 means the entries of a node (or the
  59. * tree root) directly point to stored pointers.
  60. *
  61. * The index is valid if and only if the parent isn't NULL.
  62. *
  63. * Concerning the allocation bitmap, a bit is set when the node it denotes,
  64. * or one of its children, can be used to allocate an entry. Conversely, a bit
  65. * is clear when the matching node and all of its children have no free entry.
  66. *
  67. * In order to support safe lockless lookups, in particular during a resize,
  68. * each node includes the height of its subtree, which is invariant during
  69. * the entire node lifetime. Since the tree height does vary, it can't be
  70. * used to determine whether the tree root is a node or a stored pointer.
  71. * This implementation assumes that all nodes and stored pointers are at least
  72. * 4-byte aligned, and uses the least significant bit of entries to indicate
  73. * the pointer type. This bit is set for internal nodes, and clear for stored
  74. * pointers so that they can be accessed from slots without conversion.
  75. */
  76. struct rdxtree_node
  77. {
  78. union
  79. {
  80. struct
  81. {
  82. struct rdxtree_node *parent;
  83. uint16_t index;
  84. };
  85. // Deferred destruction when unlinked.
  86. struct work work;
  87. };
  88. uint16_t height;
  89. uint16_t nr_entries;
  90. rdxtree_bm_t alloc_bm;
  91. void *entries[RDXTREE_RADIX_SIZE];
  92. };
  93. static struct kmem_cache rdxtree_node_cache;
  94. static bool
  95. rdxtree_alignment_valid (const void *ptr)
  96. {
  97. return (((uintptr_t)ptr & ~RDXTREE_ENTRY_ADDR_MASK) == 0);
  98. }
  99. static inline void*
  100. rdxtree_entry_addr (void *entry)
  101. {
  102. return ((void *)((uintptr_t)entry & RDXTREE_ENTRY_ADDR_MASK));
  103. }
  104. static inline bool
  105. rdxtree_entry_is_node (const void *entry)
  106. {
  107. return (((uintptr_t)entry & 1) != 0);
  108. }
  109. static inline void*
  110. rdxtree_node_to_entry (struct rdxtree_node *node)
  111. {
  112. return ((void *)((uintptr_t)node | 1));
  113. }
  114. static void
  115. rdxtree_node_ctor (void *buf)
  116. {
  117. struct rdxtree_node *node = buf;
  118. node->nr_entries = 0;
  119. node->alloc_bm = RDXTREE_BM_FULL;
  120. memset (node->entries, 0, sizeof (node->entries));
  121. }
  122. static int
  123. rdxtree_node_create (struct rdxtree_node **nodep,
  124. uint16_t height, uint16_t flags)
  125. {
  126. struct rdxtree_node *node =
  127. kmem_cache_alloc2 (&rdxtree_node_cache,
  128. (flags & RDXTREE_ALLOC_SLEEP) ?
  129. KMEM_ALLOC_SLEEP : 0);
  130. if (! node)
  131. return (ENOMEM);
  132. assert (rdxtree_alignment_valid (node));
  133. node->parent = NULL;
  134. node->height = height;
  135. *nodep = node;
  136. return (0);
  137. }
  138. static void
  139. rdxtree_node_destroy (struct rdxtree_node *node)
  140. {
  141. // See rdxtree_shrink().
  142. if (node->nr_entries)
  143. {
  144. assert (node->entries[0]);
  145. for (uint32_t i = 0; i < node->nr_entries; ++i)
  146. node->entries[i] = NULL;
  147. node->nr_entries = 0;
  148. node->alloc_bm = RDXTREE_BM_FULL;
  149. }
  150. kmem_cache_free (&rdxtree_node_cache, node);
  151. }
  152. static void
  153. rdxtree_node_destroy_deferred (struct work *work)
  154. {
  155. rdxtree_node_destroy (structof (work, struct rdxtree_node, work));
  156. }
  157. static void
  158. rdxtree_node_schedule_destruction (struct rdxtree_node *node)
  159. {
  160. assert (!node->parent);
  161. work_init (&node->work, rdxtree_node_destroy_deferred);
  162. rcu_defer (&node->work);
  163. }
  164. static inline void
  165. rdxtree_node_link (struct rdxtree_node *node, struct rdxtree_node *parent,
  166. uint16_t index)
  167. {
  168. node->parent = parent;
  169. node->index = index;
  170. }
  171. static inline void
  172. rdxtree_node_unlink (struct rdxtree_node *node)
  173. {
  174. assert (node->parent);
  175. node->parent = NULL;
  176. }
  177. static inline bool
  178. rdxtree_node_full (struct rdxtree_node *node)
  179. {
  180. return (node->nr_entries == ARRAY_SIZE (node->entries));
  181. }
  182. static inline bool
  183. rdxtree_node_empty (struct rdxtree_node *node)
  184. {
  185. return (!node->nr_entries);
  186. }
  187. static inline void
  188. rdxtree_node_insert (struct rdxtree_node *node, uint16_t index, void *entry)
  189. {
  190. assert (index < ARRAY_SIZE (node->entries));
  191. assert (!node->entries[index]);
  192. ++node->nr_entries;
  193. rcu_store (&node->entries[index], entry);
  194. }
  195. static inline void
  196. rdxtree_node_insert_node (struct rdxtree_node *node, uint16_t index,
  197. struct rdxtree_node *child)
  198. {
  199. rdxtree_node_insert (node, index, rdxtree_node_to_entry (child));
  200. }
  201. static inline void
  202. rdxtree_node_remove (struct rdxtree_node *node, uint16_t index)
  203. {
  204. assert (index < ARRAY_SIZE (node->entries));
  205. assert (node->entries[index]);
  206. --node->nr_entries;
  207. rcu_store (&node->entries[index], NULL);
  208. }
  209. static inline void*
  210. rdxtree_node_find (struct rdxtree_node *node, uint16_t *indexp)
  211. {
  212. for (uint16_t index = *indexp; index < ARRAY_SIZE (node->entries); ++index)
  213. {
  214. void *ptr = rdxtree_entry_addr (rcu_load (&node->entries[index]));
  215. if (ptr)
  216. {
  217. *indexp = index;
  218. return (ptr);
  219. }
  220. }
  221. return (NULL);
  222. }
  223. static inline void
  224. rdxtree_node_bm_set (struct rdxtree_node *node, uint16_t index)
  225. {
  226. node->alloc_bm |= (rdxtree_bm_t)1 << index;
  227. }
  228. static inline void
  229. rdxtree_node_bm_clear (struct rdxtree_node *node, uint16_t index)
  230. {
  231. node->alloc_bm &= ~ ((rdxtree_bm_t)1 << index);
  232. }
  233. static inline bool
  234. rdxtree_node_bm_is_set (struct rdxtree_node *node, uint16_t index)
  235. {
  236. return (node->alloc_bm & ((rdxtree_bm_t)1 << index));
  237. }
  238. static inline bool
  239. rdxtree_node_bm_empty (struct rdxtree_node *node)
  240. {
  241. return (node->alloc_bm == RDXTREE_BM_EMPTY);
  242. }
  243. static inline uint16_t
  244. rdxtree_node_bm_first (struct rdxtree_node *node)
  245. {
  246. return (rdxtree_ffs (node->alloc_bm) - 1);
  247. }
  248. static inline rdxtree_key_t
  249. rdxtree_max_key (uint16_t height)
  250. {
  251. size_t shift = RDXTREE_RADIX * height;
  252. if (likely (shift < sizeof (rdxtree_key_t) * CHAR_BIT))
  253. return (((rdxtree_key_t)1 << shift) - 1);
  254. else
  255. return (~((rdxtree_key_t)0));
  256. }
  257. static inline bool
  258. rdxtree_key_alloc_enabled (const struct rdxtree *tree)
  259. {
  260. return (tree->flags & RDXTREE_KEY_ALLOC);
  261. }
  262. static void
  263. rdxtree_shrink (struct rdxtree *tree)
  264. {
  265. while (tree->height > 0)
  266. {
  267. struct rdxtree_node *node = rdxtree_entry_addr (tree->root);
  268. if (node->nr_entries != 1)
  269. break;
  270. void *entry = node->entries[0];
  271. if (! entry)
  272. break;
  273. else if (--tree->height > 0)
  274. rdxtree_node_unlink (rdxtree_entry_addr (entry));
  275. rcu_store (&tree->root, entry);
  276. /*
  277. * There is still one valid entry (the first one) in this node. It
  278. * must remain valid as long as read-side references can exist so
  279. * that concurrent lookups can find the rest of the tree. Therefore,
  280. * this entry isn't reset before node destruction.
  281. */
  282. rdxtree_node_schedule_destruction (node);
  283. }
  284. }
  285. static int
  286. rdxtree_grow (struct rdxtree *tree, rdxtree_key_t key)
  287. {
  288. uint16_t new_height = tree->height + 1;
  289. while (key > rdxtree_max_key (new_height))
  290. new_height++;
  291. if (!tree->root)
  292. {
  293. tree->height = new_height;
  294. return (0);
  295. }
  296. struct rdxtree_node *root = rdxtree_entry_addr (tree->root);
  297. do
  298. {
  299. struct rdxtree_node *node;
  300. int error = rdxtree_node_create (&node, tree->height, tree->flags);
  301. if (error)
  302. {
  303. rdxtree_shrink (tree);
  304. return (error);
  305. }
  306. else if (tree->height)
  307. {
  308. rdxtree_node_link (root, node, 0);
  309. if (rdxtree_key_alloc_enabled (tree) &&
  310. rdxtree_node_bm_empty (root))
  311. rdxtree_node_bm_clear (node, 0);
  312. }
  313. else if (rdxtree_key_alloc_enabled (tree))
  314. rdxtree_node_bm_clear (node, 0);
  315. rdxtree_node_insert (node, 0, tree->root);
  316. ++tree->height;
  317. rcu_store (&tree->root, rdxtree_node_to_entry (node));
  318. root = node;
  319. }
  320. while (new_height > tree->height);
  321. return (0);
  322. }
  323. static void
  324. rdxtree_cleanup (struct rdxtree *tree, struct rdxtree_node *node)
  325. {
  326. while (1)
  327. {
  328. if (likely (!rdxtree_node_empty (node)))
  329. {
  330. if (unlikely (!node->parent))
  331. rdxtree_shrink (tree);
  332. break;
  333. }
  334. if (!node->parent)
  335. {
  336. tree->height = 0;
  337. rcu_store (&tree->root, NULL);
  338. rdxtree_node_schedule_destruction (node);
  339. break;
  340. }
  341. struct rdxtree_node *prev = node;
  342. node = node->parent;
  343. rdxtree_node_unlink (prev);
  344. rdxtree_node_remove (node, prev->index);
  345. rdxtree_node_schedule_destruction (prev);
  346. }
  347. }
  348. static void
  349. rdxtree_insert_bm_clear (struct rdxtree_node *node, uint16_t index)
  350. {
  351. while (1)
  352. {
  353. rdxtree_node_bm_clear (node, index);
  354. if (!rdxtree_node_full (node) || !node->parent)
  355. break;
  356. index = node->index;
  357. node = node->parent;
  358. }
  359. }
  360. int
  361. rdxtree_insert_common (struct rdxtree *tree, rdxtree_key_t key,
  362. void *ptr, void ***slotp)
  363. {
  364. assert (ptr);
  365. assert (rdxtree_alignment_valid (ptr));
  366. if (unlikely (key > rdxtree_max_key (tree->height)))
  367. {
  368. int error = rdxtree_grow (tree, key);
  369. if (error)
  370. return (error);
  371. }
  372. uint16_t height = tree->height;
  373. if (unlikely (! height))
  374. {
  375. if (slotp)
  376. *slotp = &tree->root;
  377. if (tree->root)
  378. return (EBUSY);
  379. rcu_store (&tree->root, ptr);
  380. return (0);
  381. }
  382. struct rdxtree_node *node = rdxtree_entry_addr (tree->root),
  383. *prev = NULL;
  384. uint16_t index = 0, shift = (height - 1) * RDXTREE_RADIX;
  385. do
  386. {
  387. if (! node)
  388. {
  389. int error = rdxtree_node_create (&node, height - 1, tree->flags);
  390. if (error)
  391. {
  392. if (! prev)
  393. tree->height = 0;
  394. else
  395. rdxtree_cleanup (tree, prev);
  396. return (error);
  397. }
  398. if (! prev)
  399. rcu_store (&tree->root, rdxtree_node_to_entry (node));
  400. else
  401. {
  402. rdxtree_node_link (node, prev, index);
  403. rdxtree_node_insert_node (prev, index, node);
  404. }
  405. }
  406. prev = node;
  407. index = (uint16_t)(key >> shift) & RDXTREE_RADIX_MASK;
  408. node = rdxtree_entry_addr (prev->entries[index]);
  409. shift -= RDXTREE_RADIX;
  410. --height;
  411. }
  412. while (height > 0);
  413. if (slotp)
  414. *slotp = &prev->entries[index];
  415. if (unlikely (node))
  416. return (EBUSY);
  417. rdxtree_node_insert (prev, index, ptr);
  418. if (rdxtree_key_alloc_enabled (tree))
  419. rdxtree_insert_bm_clear (prev, index);
  420. return (0);
  421. }
  422. int
  423. rdxtree_insert_alloc_common (struct rdxtree *tree, void *ptr,
  424. rdxtree_key_t *keyp, void ***slotp)
  425. {
  426. rdxtree_key_t key;
  427. int error;
  428. assert (rdxtree_key_alloc_enabled (tree));
  429. assert (ptr);
  430. assert (rdxtree_alignment_valid (ptr));
  431. uint16_t height = tree->height;
  432. if (unlikely (! height))
  433. {
  434. if (!tree->root)
  435. {
  436. rcu_store (&tree->root, ptr);
  437. *keyp = 0;
  438. if (slotp != NULL)
  439. *slotp = &tree->root;
  440. return (0);
  441. }
  442. goto grow;
  443. }
  444. struct rdxtree_node *node = rdxtree_entry_addr (tree->root),
  445. *prev = NULL;
  446. uint16_t index = 0, shift = (height - 1) * RDXTREE_RADIX;
  447. key = 0;
  448. do
  449. {
  450. if (! node)
  451. {
  452. error = rdxtree_node_create (&node, height - 1, tree->flags);
  453. if (error)
  454. {
  455. rdxtree_cleanup (tree, prev);
  456. return (error);
  457. }
  458. rdxtree_node_link (node, prev, index);
  459. rdxtree_node_insert_node (prev, index, node);
  460. }
  461. prev = node;
  462. index = rdxtree_node_bm_first (node);
  463. if (index == UINT16_MAX)
  464. goto grow;
  465. key |= (rdxtree_key_t)index << shift;
  466. node = rdxtree_entry_addr (node->entries[index]);
  467. shift -= RDXTREE_RADIX;
  468. --height;
  469. }
  470. while (height > 0);
  471. rdxtree_node_insert (prev, index, ptr);
  472. rdxtree_insert_bm_clear (prev, index);
  473. if (slotp)
  474. *slotp = &prev->entries[index];
  475. goto out;
  476. grow:
  477. key = rdxtree_max_key (height) + 1;
  478. error = rdxtree_insert_common (tree, key, ptr, slotp);
  479. if (error)
  480. return (error);
  481. out:
  482. *keyp = key;
  483. return (0);
  484. }
  485. static void
  486. rdxtree_remove_bm_set (struct rdxtree_node *node, uint16_t index)
  487. {
  488. do
  489. {
  490. rdxtree_node_bm_set (node, index);
  491. if (!node->parent)
  492. break;
  493. index = node->index;
  494. node = node->parent;
  495. }
  496. while (!rdxtree_node_bm_is_set (node, index));
  497. }
  498. void*
  499. rdxtree_remove (struct rdxtree *tree, rdxtree_key_t key)
  500. {
  501. uint16_t height = tree->height;
  502. if (unlikely (key > rdxtree_max_key (height)))
  503. return (NULL);
  504. struct rdxtree_node *prev, *node = rdxtree_entry_addr (tree->root);
  505. if (unlikely (! height))
  506. {
  507. rcu_store (&tree->root, NULL);
  508. return (node);
  509. }
  510. uint16_t index, shift = (height - 1) * RDXTREE_RADIX;
  511. do
  512. {
  513. if (! node)
  514. return (NULL);
  515. prev = node;
  516. index = (uint16_t) (key >> shift) & RDXTREE_RADIX_MASK;
  517. node = rdxtree_entry_addr (node->entries[index]);
  518. shift -= RDXTREE_RADIX;
  519. --height;
  520. }
  521. while (height > 0);
  522. if (! node)
  523. return (NULL);
  524. if (rdxtree_key_alloc_enabled (tree))
  525. rdxtree_remove_bm_set (prev, index);
  526. rdxtree_node_remove (prev, index);
  527. rdxtree_cleanup (tree, prev);
  528. return (node);
  529. }
  530. void*
  531. rdxtree_lookup_common (const struct rdxtree *tree, rdxtree_key_t key,
  532. bool get_slot, void **nodep, int *idxp)
  533. {
  534. struct rdxtree_node *node;
  535. uint16_t height;
  536. void *entry = rcu_load (&tree->root);
  537. if (! entry)
  538. {
  539. node = NULL;
  540. height = 0;
  541. }
  542. else
  543. {
  544. node = rdxtree_entry_addr (entry);
  545. height = rdxtree_entry_is_node (entry) ? node->height + 1 : 0;
  546. }
  547. if (key > rdxtree_max_key (height))
  548. return (NULL);
  549. else if (! height)
  550. return (node && get_slot ? (void *)&tree->root : node);
  551. uint16_t index, shift = (height - 1) * RDXTREE_RADIX;
  552. struct rdxtree_node *prev;
  553. do
  554. {
  555. if (! node)
  556. return (NULL);
  557. prev = node;
  558. index = (uint16_t)(key >> shift) & RDXTREE_RADIX_MASK;
  559. entry = rcu_load (&node->entries[index]);
  560. node = rdxtree_entry_addr (entry);
  561. shift -= RDXTREE_RADIX;
  562. --height;
  563. }
  564. while (height > 0);
  565. *nodep = prev;
  566. *idxp = index;
  567. return (node && get_slot ? (void *)&prev->entries[index] : node);
  568. }
  569. void*
  570. rdxtree_replace_slot (void **slot, void *ptr)
  571. {
  572. assert (ptr);
  573. assert (rdxtree_alignment_valid (ptr));
  574. void *old = *slot;
  575. assert (old);
  576. assert (rdxtree_alignment_valid (old));
  577. rcu_store (slot, ptr);
  578. return (old);
  579. }
  580. void
  581. rdxtree_remove_node_idx (struct rdxtree *tree, void **slot,
  582. void *node, int idx)
  583. {
  584. if (slot == &tree->root)
  585. {
  586. rcu_store (slot, NULL);
  587. return;
  588. }
  589. struct rdxtree_node *prev = node;
  590. if (rdxtree_key_alloc_enabled (tree))
  591. rdxtree_remove_bm_set (prev, idx);
  592. rdxtree_node_remove (prev, idx);
  593. rdxtree_cleanup (tree, prev);
  594. }
  595. static void*
  596. rdxtree_walk_next (struct rdxtree *tree, struct rdxtree_iter *iter)
  597. {
  598. void *entry = rcu_load (&tree->root);
  599. if (! entry)
  600. return (NULL);
  601. else if (!rdxtree_entry_is_node (entry))
  602. {
  603. if (iter->key != (rdxtree_key_t)-1)
  604. return (NULL);
  605. else
  606. {
  607. iter->key = 0;
  608. return (rdxtree_entry_addr (entry));
  609. }
  610. }
  611. rdxtree_key_t key = iter->key + 1;
  612. if (!key && iter->node)
  613. return (NULL);
  614. struct rdxtree_node *root, *node, *prev;
  615. uint16_t height, shift, index, orig_index;
  616. root = rdxtree_entry_addr (entry);
  617. restart:
  618. node = root;
  619. height = root->height + 1;
  620. if (key > rdxtree_max_key (height))
  621. return (NULL);
  622. shift = (height - 1) * RDXTREE_RADIX;
  623. do
  624. {
  625. prev = node;
  626. index = (key >> shift) & RDXTREE_RADIX_MASK;
  627. orig_index = index;
  628. node = rdxtree_node_find (node, &index);
  629. if (! node)
  630. {
  631. shift += RDXTREE_RADIX;
  632. key = ((key >> shift) + 1) << shift;
  633. if (! key)
  634. return (NULL);
  635. goto restart;
  636. }
  637. if (orig_index != index)
  638. key = ((key >> shift) + (index - orig_index)) << shift;
  639. shift -= RDXTREE_RADIX;
  640. --height;
  641. }
  642. while (height > 0);
  643. iter->node = prev;
  644. iter->key = key;
  645. return (node);
  646. }
  647. void*
  648. rdxtree_walk (struct rdxtree *tree, struct rdxtree_iter *iter)
  649. {
  650. if (!iter->node)
  651. return (rdxtree_walk_next (tree, iter));
  652. uint16_t index = (iter->key + 1) & RDXTREE_RADIX_MASK;
  653. if (index)
  654. {
  655. uint16_t orig_index = index;
  656. void *ptr = rdxtree_node_find (iter->node, &index);
  657. if (ptr)
  658. {
  659. iter->key += (index - orig_index) + 1;
  660. return (ptr);
  661. }
  662. }
  663. return (rdxtree_walk_next (tree, iter));
  664. }
  665. void
  666. rdxtree_remove_all (struct rdxtree *tree)
  667. {
  668. if (!tree->height)
  669. {
  670. if (tree->root)
  671. rcu_store (&tree->root, NULL);
  672. return;
  673. }
  674. while (1)
  675. {
  676. struct rdxtree_iter iter;
  677. rdxtree_iter_init (&iter);
  678. rdxtree_walk_next (tree, &iter);
  679. if (!iter.node)
  680. break;
  681. struct rdxtree_node *node = iter.node,
  682. *parent = node->parent;
  683. if (! parent)
  684. rdxtree_init (tree, tree->flags);
  685. else
  686. {
  687. if (rdxtree_key_alloc_enabled (tree))
  688. rdxtree_remove_bm_set (parent, node->index);
  689. rdxtree_node_remove (parent, node->index);
  690. rdxtree_cleanup (tree, parent);
  691. node->parent = NULL;
  692. }
  693. rdxtree_node_schedule_destruction (node);
  694. }
  695. }
  696. static int __init
  697. rdxtree_setup (void)
  698. {
  699. kmem_cache_init (&rdxtree_node_cache, "rdxtree_node",
  700. sizeof (struct rdxtree_node), 0,
  701. rdxtree_node_ctor, KMEM_CACHE_PAGE_ONLY);
  702. return (0);
  703. }
  704. INIT_OP_DEFINE (rdxtree_setup,
  705. INIT_OP_DEP (kmem_bootstrap, true),
  706. INIT_OP_DEP (rcu_bootstrap, true));