1 /* $NetBSD: ptree.c,v 1.5 2009/06/07 03:12:40 yamt Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas <matt@3am-software.com>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
34 #if defined(PTCHECK) && !defined(PTDEBUG)
38 #if defined(_KERNEL) || defined(_STANDALONE)
39 #include <sys/param.h>
40 #include <sys/types.h>
41 #include <sys/systm.h>
42 #include <lib/libkern/libkern.h>
43 __KERNEL_RCSID(0, "$NetBSD: ptree.c,v 1.5 2009/06/07 03:12:40 yamt Exp $");
52 #define KASSERT(e) assert(e)
54 #define KASSERT(e) do { } while (/*CONSTCOND*/ 0)
56 __RCSID("$NetBSD: ptree.c,v 1.5 2009/06/07 03:12:40 yamt Exp $");
57 #endif /* _KERNEL || _STANDALONE */
60 #include "namespace.h"
66 #include <sys/ptree.h>
70 * This is an implementation of a radix / PATRICIA tree. As in a traditional
71 * patricia tree, all the data is at the leaves of the tree. An N-value
72 * tree would have N leaves, N-1 branching nodes, and a root pointer. Each
73 * branching node would have left(0) and right(1) pointers that either point
74 * to another branching node or a leaf node. The root pointer would also
75 * point to either the first branching node or a leaf node. Leaf nodes
76 * have no need for pointers.
78 * However, allocation for these branching nodes is problematic since the
79 * allocation could fail. This would cause insertions to fail for reasons
80 * beyond the users control. So to prevent this, in this implementation
81 * each node has two identities: its leaf identity and its branch identity.
82 * Each is separate from the other. Every branch is tagged as to whether
83 * it points to a leaf or a branch. This is not an attribute of the object
84 * but of the pointer to the object. The low bit of the pointer is used as
85 * the tag to determine whether it points to a leaf or branch identity, with
86 * branch identities having the low bit set.
88 * A node's branch identity has one rule: when traversing the tree from the
89 * root to the node's leaf identity, one of the branches traversed will be via
90 * the node's branch identity. Of course, that has an exception: since to
91 * store N leaves, you need N-1 branches. That one node whose branch identity
92 * isn't used is stored as "oddman"-out in the root.
94 * Branching nodes also has a bit offset and a bit length which determines
95 * which branch slot is used. The bit length can be zero resulting in a
96 * one-way branch. This is happens in two special cases: the root and
97 * interior mask nodes.
99 * To support longest match first lookups, when a mask node (one that only
100 * match the first N bits) has children who first N bits match the mask nodes,
101 * that mask node is converted from being a leaf node to being a one-way
102 * branch-node. The mask becomes fixed in position in the tree. The mask
103 * will always be the longest mask match for its descendants (unless they
104 * traverse an even longer match).
107 #define NODETOITEM(pt, ptn) \
108 ((void *)((uintptr_t)(ptn) - (pt)->pt_node_offset))
109 #define NODETOKEY(pt, ptn) \
110 ((void *)((uintptr_t)(ptn) - (pt)->pt_node_offset + pt->pt_key_offset))
111 #define ITEMTONODE(pt, ptn) \
112 ((pt_node_t *)((uintptr_t)(ptn) + (pt)->pt_node_offset))
114 bool ptree_check(const pt_tree_t
*);
116 #define PTREE_CHECK(pt) ptree_check(pt)
118 #define PTREE_CHECK(pt) do { } while (/*CONSTCOND*/ 0)
122 ptree_matchnode(const pt_tree_t
*pt
, const pt_node_t
*target
,
123 const pt_node_t
*ptn
, pt_bitoff_t max_bitoff
,
124 pt_bitoff_t
*bitoff_p
, pt_slot_t
*slots_p
)
126 return (*pt
->pt_ops
->ptto_matchnode
)(NODETOKEY(pt
, target
),
127 (ptn
!= NULL
? NODETOKEY(pt
, ptn
) : NULL
), max_bitoff
,
131 static inline pt_slot_t
132 ptree_testnode(const pt_tree_t
*pt
, const pt_node_t
*target
,
133 const pt_node_t
*ptn
)
135 const pt_bitlen_t bitlen
= PTN_BRANCH_BITLEN(ptn
);
138 return (*pt
->pt_ops
->ptto_testnode
)(NODETOKEY(pt
, target
),
139 PTN_BRANCH_BITOFF(ptn
),
144 ptree_matchkey(const pt_tree_t
*pt
, const void *key
,
145 const pt_node_t
*ptn
, pt_bitoff_t bitoff
, pt_bitlen_t bitlen
)
147 return (*pt
->pt_ops
->ptto_matchkey
)(key
, NODETOKEY(pt
, ptn
),
151 static inline pt_slot_t
152 ptree_testkey(const pt_tree_t
*pt
, const void *key
, const pt_node_t
*ptn
)
154 return (*pt
->pt_ops
->ptto_testkey
)(key
,
155 PTN_BRANCH_BITOFF(ptn
),
156 PTN_BRANCH_BITLEN(ptn
));
160 ptree_set_position(uintptr_t node
, pt_slot_t position
)
163 PTN_SET_LEAF_POSITION(PT_NODE(node
), position
);
165 PTN_SET_BRANCH_POSITION(PT_NODE(node
), position
);
169 ptree_init(pt_tree_t
*pt
, const pt_tree_ops_t
*ops
, size_t node_offset
,
172 memset(pt
, 0, sizeof(*pt
));
173 pt
->pt_node_offset
= node_offset
;
174 pt
->pt_key_offset
= key_offset
;
179 uintptr_t *id_insertp
;
180 pt_node_t
*id_parent
;
182 pt_slot_t id_parent_slot
;
183 pt_bitoff_t id_bitoff
;
187 typedef bool (*pt_insertfunc_t
)(pt_tree_t
*, pt_node_t
*, pt_insertdata_t
*);
190 * Move a branch identify from src to dst. The leaves don't care since
191 * nothing for them has changed.
195 ptree_move_branch(pt_tree_t
* const pt
, pt_node_t
* const dst
,
196 const pt_node_t
* const src
)
198 KASSERT(PTN_BRANCH_BITLEN(src
) == 1);
199 /* set branch bitlen and bitoff in one step. */
200 dst
->ptn_branchdata
= src
->ptn_branchdata
;
201 PTN_SET_BRANCH_POSITION(dst
, PTN_BRANCH_POSITION(src
));
202 PTN_COPY_BRANCH_SLOTS(dst
, src
);
203 return PTN_BRANCH(dst
);
207 static inline uintptr_t *
208 ptree_find_branch(pt_tree_t
* const pt
, uintptr_t branch_node
)
210 pt_node_t
* const branch
= PT_NODE(branch_node
);
213 for (parent
= &pt
->pt_rootnode
;;) {
215 &PTN_BRANCH_SLOT(parent
, ptree_testnode(pt
, branch
, parent
));
216 if (*nodep
== branch_node
)
218 if (PT_LEAF_P(*nodep
))
220 parent
= PT_NODE(*nodep
);
225 ptree_insert_leaf_after_mask(pt_tree_t
* const pt
, pt_node_t
* const target
,
226 pt_insertdata_t
* const id
)
228 const uintptr_t target_node
= PTN_LEAF(target
);
229 const uintptr_t mask_node
= id
->id_node
;
230 pt_node_t
* const mask
= PT_NODE(mask_node
);
231 const pt_bitlen_t mask_len
= PTN_MASK_BITLEN(mask
);
233 KASSERT(PT_LEAF_P(mask_node
));
234 KASSERT(PTN_LEAF_POSITION(mask
) == id
->id_parent_slot
);
235 KASSERT(mask_len
<= id
->id_bitoff
);
236 KASSERT(PTN_ISMASK_P(mask
));
237 KASSERT(!PTN_ISMASK_P(target
) || mask_len
< PTN_MASK_BITLEN(target
));
239 if (mask_node
== PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
)) {
240 KASSERT(id
->id_parent
!= mask
);
242 * Nice, mask was an oddman. So just set the oddman to target.
244 PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
) = target_node
;
247 * We need to find out who's pointing to mask's branch
248 * identity. We know that between root and the leaf identity,
249 * we must traverse the node's branch identity.
251 uintptr_t * const mask_nodep
= ptree_find_branch(pt
, PTN_BRANCH(mask
));
252 KASSERT(mask_nodep
!= NULL
);
253 KASSERT(*mask_nodep
== PTN_BRANCH(mask
));
254 KASSERT(PTN_BRANCH_BITLEN(mask
) == 1);
257 * Alas, mask was used as a branch. Since the mask is becoming
258 * a one-way branch, we need make target take over mask's
259 * branching responsibilities. Only then can we change it.
261 *mask_nodep
= ptree_move_branch(pt
, target
, mask
);
264 * However, it's possible that mask's parent is itself. If
265 * that's true, update the insert point to use target since it
266 * has taken over mask's branching duties.
268 if (id
->id_parent
== mask
)
269 id
->id_insertp
= &PTN_BRANCH_SLOT(target
,
273 PTN_SET_BRANCH_BITLEN(mask
, 0);
274 PTN_SET_BRANCH_BITOFF(mask
, mask_len
);
276 PTN_BRANCH_ROOT_SLOT(mask
) = target_node
;
277 PTN_BRANCH_ODDMAN_SLOT(mask
) = PT_NULL
;
278 PTN_SET_LEAF_POSITION(target
, PT_SLOT_ROOT
);
279 PTN_SET_BRANCH_POSITION(mask
, id
->id_parent_slot
);
282 * Now that everything is done, to make target visible we need to
283 * change mask from a leaf to a branch.
285 *id
->id_insertp
= PTN_BRANCH(mask
);
292 ptree_insert_mask_before_node(pt_tree_t
* const pt
, pt_node_t
* const target
,
293 pt_insertdata_t
* const id
)
295 const uintptr_t node
= id
->id_node
;
296 pt_node_t
* const ptn
= PT_NODE(node
);
297 const pt_slot_t mask_len
= PTN_MASK_BITLEN(target
);
298 const pt_bitlen_t node_mask_len
= PTN_MASK_BITLEN(ptn
);
300 KASSERT(PT_LEAF_P(node
) || id
->id_parent_slot
== PTN_BRANCH_POSITION(ptn
));
301 KASSERT(PT_BRANCH_P(node
) || id
->id_parent_slot
== PTN_LEAF_POSITION(ptn
));
302 KASSERT(PTN_ISMASK_P(target
));
305 * If the node we are placing ourself in front is a mask with the
306 * same mask length as us, return failure.
308 if (PTN_ISMASK_P(ptn
) && node_mask_len
== mask_len
)
311 PTN_SET_BRANCH_BITLEN(target
, 0);
312 PTN_SET_BRANCH_BITOFF(target
, mask_len
);
314 PTN_BRANCH_SLOT(target
, PT_SLOT_ROOT
) = node
;
315 *id
->id_insertp
= PTN_BRANCH(target
);
317 PTN_SET_BRANCH_POSITION(target
, id
->id_parent_slot
);
318 ptree_set_position(node
, PT_SLOT_ROOT
);
323 #endif /* !PTNOMASK */
327 ptree_insert_branch_at_node(pt_tree_t
* const pt
, pt_node_t
* const target
,
328 pt_insertdata_t
* const id
)
330 const uintptr_t target_node
= PTN_LEAF(target
);
331 const uintptr_t node
= id
->id_node
;
332 const pt_slot_t other_slot
= id
->id_slot
^ PT_SLOT_OTHER
;
334 KASSERT(PT_BRANCH_P(node
) || id
->id_parent_slot
== PTN_LEAF_POSITION(PT_NODE(node
)));
335 KASSERT(PT_LEAF_P(node
) || id
->id_parent_slot
== PTN_BRANCH_POSITION(PT_NODE(node
)));
336 KASSERT((node
== pt
->pt_root
) == (id
->id_parent
== &pt
->pt_rootnode
));
338 KASSERT(!PTN_ISMASK_P(target
) || id
->id_bitoff
<= PTN_MASK_BITLEN(target
));
340 KASSERT(node
== pt
->pt_root
|| PTN_BRANCH_BITOFF(id
->id_parent
) + PTN_BRANCH_BITLEN(id
->id_parent
) <= id
->id_bitoff
);
342 PTN_SET_BRANCH_BITOFF(target
, id
->id_bitoff
);
343 PTN_SET_BRANCH_BITLEN(target
, 1);
345 PTN_BRANCH_SLOT(target
, id
->id_slot
) = target_node
;
346 PTN_BRANCH_SLOT(target
, other_slot
) = node
;
347 *id
->id_insertp
= PTN_BRANCH(target
);
349 PTN_SET_LEAF_POSITION(target
, id
->id_slot
);
350 ptree_set_position(node
, other_slot
);
352 PTN_SET_BRANCH_POSITION(target
, id
->id_parent_slot
);
358 ptree_insert_leaf(pt_tree_t
* const pt
, pt_node_t
* const target
,
359 pt_insertdata_t
* const id
)
361 const uintptr_t leaf_node
= id
->id_node
;
362 pt_node_t
* const leaf
= PT_NODE(leaf_node
);
364 const bool inserting_mask
= false;
365 const bool at_mask
= false;
367 const bool inserting_mask
= PTN_ISMASK_P(target
);
368 const bool at_mask
= PTN_ISMASK_P(leaf
);
369 const pt_bitlen_t leaf_masklen
= PTN_MASK_BITLEN(leaf
);
370 const pt_bitlen_t target_masklen
= PTN_MASK_BITLEN(target
);
372 pt_insertfunc_t insertfunc
= ptree_insert_branch_at_node
;
376 * In all likelyhood we are going simply going to insert a branch
377 * where this leaf is which will point to the old and new leaves.
379 KASSERT(PT_LEAF_P(leaf_node
));
380 KASSERT(PTN_LEAF_POSITION(leaf
) == id
->id_parent_slot
);
381 matched
= ptree_matchnode(pt
, target
, leaf
, UINT_MAX
,
382 &id
->id_bitoff
, &id
->id_slot
);
383 if (__predict_false(!inserting_mask
)) {
385 * We aren't inserting a mask nor is the leaf a mask, which
386 * means we are trying to insert a duplicate leaf. Can't do
389 if (!at_mask
&& matched
)
394 * We are at a mask and the leaf we are about to insert
395 * is at or beyond the mask, we need to convert the mask
396 * from a leaf to a one-way branch interior mask.
398 if (at_mask
&& id
->id_bitoff
>= leaf_masklen
)
399 insertfunc
= ptree_insert_leaf_after_mask
;
400 #endif /* PTNOMASK */
405 * We are inserting a mask.
409 * If the leaf isn't a mask, we obviously have to
410 * insert the new mask before non-mask leaf. If the
411 * leaf is a mask, and the new node has a LEQ mask
412 * length it too needs to inserted before leaf (*).
414 * In other cases, we place the new mask as leaf after
415 * leaf mask. Which mask comes first will be a one-way
416 * branch interior mask node which has the other mask
419 * (*) ptree_insert_mask_before_node can detect a
420 * duplicate mask and return failure if needed.
422 if (!at_mask
|| target_masklen
<= leaf_masklen
)
423 insertfunc
= ptree_insert_mask_before_node
;
425 insertfunc
= ptree_insert_leaf_after_mask
;
426 } else if (at_mask
&& id
->id_bitoff
>= leaf_masklen
) {
428 * If the new mask has a bit offset GEQ than the leaf's
429 * mask length, convert the left to a one-way branch
430 * interior mask and make that point to the new [leaf]
433 insertfunc
= ptree_insert_leaf_after_mask
;
436 * The new mask has a bit offset less than the leaf's
437 * mask length or if the leaf isn't a mask at all, the
438 * new mask deserves to be its own leaf so we use the
439 * default insertfunc to do that.
443 #endif /* PTNOMASK */
445 return (*insertfunc
)(pt
, target
, id
);
449 ptree_insert_node_common(pt_tree_t
*pt
, void *item
)
451 pt_node_t
* const target
= ITEMTONODE(pt
, item
);
453 const bool inserting_mask
= PTN_ISMASK_P(target
);
454 const pt_bitlen_t target_masklen
= PTN_MASK_BITLEN(target
);
456 pt_insertfunc_t insertfunc
;
460 * We need a leaf so we can match against. Until we get a leaf
461 * we having nothing to test against.
463 if (__predict_false(PT_NULL_P(pt
->pt_root
))) {
464 PTN_BRANCH_ROOT_SLOT(&pt
->pt_rootnode
) = PTN_LEAF(target
);
465 PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
) = PTN_LEAF(target
);
466 PTN_SET_LEAF_POSITION(target
, PT_SLOT_ROOT
);
472 id
.id_parent
= &pt
->pt_rootnode
;
473 id
.id_parent_slot
= PT_SLOT_ROOT
;
474 id
.id_insertp
= &PTN_BRANCH_ROOT_SLOT(id
.id_parent
);
476 pt_bitoff_t branch_bitoff
;
477 pt_node_t
* const ptn
= PT_NODE(*id
.id_insertp
);
478 id
.id_node
= *id
.id_insertp
;
481 * If we hit a leaf, try to insert target at leaf. We could
482 * have inlined ptree_insert_leaf here but that would have
483 * made this routine much harder to understand. Trust the
484 * compiler to optimize this properly.
486 if (PT_LEAF_P(id
.id_node
)) {
487 KASSERT(PTN_LEAF_POSITION(ptn
) == id
.id_parent_slot
);
488 insertfunc
= ptree_insert_leaf
;
493 * If we aren't a leaf, we must be a branch. Make sure we are
494 * in the slot we think we are.
496 KASSERT(PT_BRANCH_P(id
.id_node
));
497 KASSERT(PTN_BRANCH_POSITION(ptn
) == id
.id_parent_slot
);
500 * Where is this branch?
502 branch_bitoff
= PTN_BRANCH_BITOFF(ptn
);
506 * If this is a one-way mask node, its offset must equal
509 KASSERT(!(PTN_ISMASK_P(ptn
) && PTN_BRANCH_BITLEN(ptn
) == 0) || PTN_MASK_BITLEN(ptn
) == branch_bitoff
);
512 * If we are inserting a mask, and we know that at this point
513 * all bits before the current bit offset match both the target
514 * and the branch. If the target's mask length is LEQ than
515 * this branch's bit offset, then this is where the mask needs
516 * to added to the tree.
518 if (__predict_false(inserting_mask
)
519 && (PTN_ISROOT_P(pt
, id
.id_parent
)
520 || id
.id_bitoff
< target_masklen
)
521 && target_masklen
<= branch_bitoff
) {
523 * We don't know about the bits (if any) between
524 * id.id_bitoff and the target's mask length match
525 * both the target and the branch. If the target's
526 * mask length is greater than the current bit offset
527 * make sure the untested bits match both the target
530 if (target_masklen
== id
.id_bitoff
531 || ptree_matchnode(pt
, target
, ptn
, target_masklen
,
532 &id
.id_bitoff
, &id
.id_slot
)) {
534 * The bits matched, so insert the mask as a
537 insertfunc
= ptree_insert_mask_before_node
;
539 } else if (id
.id_bitoff
< branch_bitoff
) {
541 * They didn't match, so create a normal branch
542 * because this mask needs to a be a new leaf.
544 insertfunc
= ptree_insert_branch_at_node
;
548 #endif /* PTNOMASK */
551 * If we are skipping some bits, verify they match the node.
552 * If they don't match, it means we have a leaf to insert.
553 * Note that if we are advancing bit by bit, we'll skip
554 * doing matchnode and walk the tree bit by bit via testnode.
556 if (id
.id_bitoff
< branch_bitoff
557 && !ptree_matchnode(pt
, target
, ptn
, branch_bitoff
,
558 &id
.id_bitoff
, &id
.id_slot
)) {
559 KASSERT(id
.id_bitoff
< branch_bitoff
);
560 insertfunc
= ptree_insert_branch_at_node
;
565 * At this point, all bits before branch_bitoff are known
566 * to match the target.
568 KASSERT(id
.id_bitoff
>= branch_bitoff
);
571 * Decend the tree one level.
574 id
.id_parent_slot
= ptree_testnode(pt
, target
, id
.id_parent
);
575 id
.id_bitoff
+= PTN_BRANCH_BITLEN(id
.id_parent
);
576 id
.id_insertp
= &PTN_BRANCH_SLOT(id
.id_parent
, id
.id_parent_slot
);
580 * Do the actual insertion.
582 return (*insertfunc
)(pt
, target
, &id
);
586 ptree_insert_node(pt_tree_t
*pt
, void *item
)
588 pt_node_t
* const target
= ITEMTONODE(pt
, item
);
590 memset(target
, 0, sizeof(*target
));
591 return ptree_insert_node_common(pt
, target
);
596 ptree_insert_mask_node(pt_tree_t
*pt
, void *item
, pt_bitlen_t mask_len
)
598 pt_node_t
* const target
= ITEMTONODE(pt
, item
);
599 pt_bitoff_t bitoff
= mask_len
;
602 memset(target
, 0, sizeof(*target
));
603 KASSERT(mask_len
== 0 || (~PT__MASK(PTN_MASK_BITLEN
) & mask_len
) == 0);
605 * Only the first <mask_len> bits can be non-zero.
606 * All other bits must be 0.
608 if (!ptree_matchnode(pt
, target
, NULL
, UINT_MAX
, &bitoff
, &slot
))
610 PTN_SET_MASK_BITLEN(target
, mask_len
);
611 PTN_MARK_MASK(target
);
612 return ptree_insert_node_common(pt
, target
);
614 #endif /* !PTNOMASH */
617 ptree_find_filtered_node(pt_tree_t
*pt
, void *key
, pt_filter_t filter
,
621 pt_node_t
*mask
= NULL
;
623 bool at_mask
= false;
624 pt_node_t
*ptn
, *parent
;
626 pt_slot_t parent_slot
;
628 if (PT_NULL_P(PTN_BRANCH_ROOT_SLOT(&pt
->pt_rootnode
)))
632 parent
= &pt
->pt_rootnode
;
633 parent_slot
= PT_SLOT_ROOT
;
635 const uintptr_t node
= PTN_BRANCH_SLOT(parent
, parent_slot
);
636 const pt_slot_t branch_bitoff
= PTN_BRANCH_BITOFF(PT_NODE(node
));
639 if (PT_LEAF_P(node
)) {
641 at_mask
= PTN_ISMASK_P(ptn
);
646 if (bitoff
< branch_bitoff
) {
647 if (!ptree_matchkey(pt
, key
, ptn
, bitoff
, branch_bitoff
- bitoff
)) {
650 return NODETOITEM(pt
, mask
);
654 bitoff
= branch_bitoff
;
658 if (PTN_ISMASK_P(ptn
) && PTN_BRANCH_BITLEN(ptn
) == 0
660 || (*filter
)(filter_arg
, NODETOITEM(pt
, ptn
),
666 parent_slot
= ptree_testkey(pt
, key
, parent
);
667 bitoff
+= PTN_BRANCH_BITLEN(parent
);
670 KASSERT(PTN_ISROOT_P(pt
, parent
) || PTN_BRANCH_BITOFF(parent
) + PTN_BRANCH_BITLEN(parent
) == bitoff
);
671 if (!filter
|| (*filter
)(filter_arg
, NODETOITEM(pt
, ptn
), at_mask
? PT_FILTER_MASK
: 0)) {
673 if (PTN_ISMASK_P(ptn
)) {
674 const pt_bitlen_t mask_len
= PTN_MASK_BITLEN(ptn
);
675 if (bitoff
== PTN_MASK_BITLEN(ptn
))
676 return NODETOITEM(pt
, ptn
);
677 if (ptree_matchkey(pt
, key
, ptn
, bitoff
, mask_len
- bitoff
))
678 return NODETOITEM(pt
, ptn
);
680 #endif /* !PTNOMASK */
681 if (ptree_matchkey(pt
, key
, ptn
, bitoff
, UINT_MAX
))
682 return NODETOITEM(pt
, ptn
);
687 * By virtue of how the mask was placed in the tree,
688 * all nodes descended from it will match it. But the bits
689 * before the mask still need to be checked and since the
690 * mask was a branch, that was done implicitly.
693 KASSERT(ptree_matchkey(pt
, key
, mask
, 0, PTN_MASK_BITLEN(mask
)));
694 return NODETOITEM(pt
, mask
);
696 #endif /* !PTNOMASK */
705 ptree_iterate(pt_tree_t
*pt
, const void *item
, pt_direction_t direction
)
707 const pt_node_t
* const target
= ITEMTONODE(pt
, item
);
708 uintptr_t node
, next_node
;
710 if (direction
!= PT_ASCENDING
&& direction
!= PT_DESCENDING
)
713 node
= PTN_BRANCH_ROOT_SLOT(&pt
->pt_rootnode
);
718 pt_node_t
* const ptn
= PT_NODE(node
);
719 if (direction
== PT_ASCENDING
720 && PTN_ISMASK_P(ptn
) && PTN_BRANCH_BITLEN(ptn
) == 0)
721 return NODETOITEM(pt
, ptn
);
725 uintptr_t mask_node
= PT_NULL
;
726 #endif /* !PTNOMASK */
728 while (!PT_LEAF_P(node
)) {
729 pt_node_t
* const ptn
= PT_NODE(node
);
732 if (PTN_ISMASK_P(ptn
) && PTN_BRANCH_BITLEN(ptn
) == 0) {
735 if (direction
== PT_DESCENDING
) {
740 #endif /* !PTNOMASK */
741 slot
= ptree_testnode(pt
, target
, ptn
);
742 node
= PTN_BRANCH_SLOT(ptn
, slot
);
743 if (direction
== PT_ASCENDING
) {
744 if (slot
!= (pt_slot_t
)((1 << PTN_BRANCH_BITLEN(ptn
)) - 1))
745 next_node
= PTN_BRANCH_SLOT(ptn
, slot
+ 1);
750 #endif /* !PTNOMASK */
751 next_node
= PTN_BRANCH_SLOT(ptn
, slot
- 1);
755 if (PT_NODE(node
) != target
)
758 if (PT_BRANCH_P(node
)) {
759 pt_node_t
*ptn
= PT_NODE(node
);
760 KASSERT(PTN_ISMASK_P(PT_NODE(node
)) && PTN_BRANCH_BITLEN(PT_NODE(node
)) == 0);
761 if (direction
== PT_ASCENDING
) {
762 next_node
= PTN_BRANCH_ROOT_SLOT(ptn
);
763 ptn
= PT_NODE(next_node
);
767 * When descending, if we countered a mask node then that's
770 if (direction
== PT_DESCENDING
&& !PT_NULL_P(mask_node
)) {
771 KASSERT(PT_NULL_P(next_node
));
772 return NODETOITEM(pt
, PT_NODE(mask_node
));
774 #endif /* !PTNOMASK */
781 while (!PT_LEAF_P(node
)) {
782 pt_node_t
* const ptn
= PT_NODE(node
);
784 if (direction
== PT_ASCENDING
) {
786 if (PT_BRANCH_P(node
)
788 && PTN_BRANCH_BITLEN(ptn
) == 0)
789 return NODETOITEM(pt
, ptn
);
790 #endif /* !PTNOMASK */
793 slot
= (1 << PTN_BRANCH_BITLEN(ptn
)) - 1;
795 node
= PTN_BRANCH_SLOT(ptn
, slot
);
797 return NODETOITEM(pt
, PT_NODE(node
));
801 ptree_remove_node(pt_tree_t
*pt
, void *item
)
803 pt_node_t
* const target
= ITEMTONODE(pt
, item
);
804 const pt_slot_t leaf_slot
= PTN_LEAF_POSITION(target
);
805 const pt_slot_t branch_slot
= PTN_BRANCH_POSITION(target
);
806 pt_node_t
*ptn
, *parent
;
811 pt_slot_t parent_slot
;
816 if (PT_NULL_P(PTN_BRANCH_ROOT_SLOT(&pt
->pt_rootnode
))) {
817 KASSERT(!PT_NULL_P(PTN_BRANCH_ROOT_SLOT(&pt
->pt_rootnode
)));
824 parent
= &pt
->pt_rootnode
;
825 parent_slot
= PT_SLOT_ROOT
;
827 node
= PTN_BRANCH_SLOT(parent
, parent_slot
);
830 at_mask
= PTN_ISMASK_P(ptn
);
837 * If we are at the target, then we are looking at its branch
838 * identity. We need to remember who's pointing at it so we
839 * stop them from doing that.
841 if (__predict_false(ptn
== target
)) {
842 KASSERT(nodep
== NULL
);
845 * Interior mask nodes are trivial to get rid of.
847 if (at_mask
&& PTN_BRANCH_BITLEN(ptn
) == 0) {
848 PTN_BRANCH_SLOT(parent
, parent_slot
) =
849 PTN_BRANCH_ROOT_SLOT(ptn
);
850 KASSERT(PT_NULL_P(PTN_BRANCH_ODDMAN_SLOT(ptn
)));
854 #endif /* !PTNOMASK */
855 nodep
= &PTN_BRANCH_SLOT(parent
, parent_slot
);
856 KASSERT(*nodep
== PTN_BRANCH(target
));
859 * We need also need to know who's pointing at our parent.
860 * After we remove ourselves from our parent, he'll only
861 * have one child and that's unacceptable. So we replace
862 * the pointer to the parent with our abadoned sibling.
864 removep
= &PTN_BRANCH_SLOT(parent
, parent_slot
);
867 * Descend into the tree.
870 parent_slot
= ptree_testnode(pt
, target
, parent
);
871 bitoff
+= PTN_BRANCH_BITLEN(parent
);
875 * We better have found that the leaf we are looking for is target.
878 KASSERT(target
== ptn
);
883 * If we didn't encounter target as branch, then target must be the
887 KASSERT(PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
) == PTN_LEAF(target
));
888 KASSERT(nodep
== NULL
);
889 nodep
= &PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
);
892 KASSERT((removep
== NULL
) == (parent
== &pt
->pt_rootnode
));
895 * We have to special remove the last leaf from the root since
896 * the only time the tree can a PT_NULL node is when it's empty.
898 if (__predict_false(PTN_ISROOT_P(pt
, parent
))) {
899 KASSERT(removep
== NULL
);
900 KASSERT(parent
== &pt
->pt_rootnode
);
901 KASSERT(nodep
== &PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
));
902 KASSERT(*nodep
== PTN_LEAF(target
));
903 PTN_BRANCH_ROOT_SLOT(&pt
->pt_rootnode
) = PT_NULL
;
904 PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
) = PT_NULL
;
908 KASSERT((parent
== target
) == (removep
== nodep
));
909 if (PTN_BRANCH(parent
) == PTN_BRANCH_SLOT(target
, PTN_BRANCH_POSITION(parent
))) {
911 * The pointer to the parent actually lives in the target's
912 * branch identity. We can't just move the target's branch
913 * identity since that would result in the parent pointing
914 * to its own branch identity and that's fobidden.
916 const pt_slot_t slot
= PTN_BRANCH_POSITION(parent
);
917 const pt_slot_t other_slot
= slot
^ PT_SLOT_OTHER
;
918 const pt_bitlen_t parent_bitlen
= PTN_BRANCH_BITLEN(parent
);
920 KASSERT(PTN_BRANCH_BITOFF(target
) < PTN_BRANCH_BITOFF(parent
));
923 * This gets so confusing. The target's branch identity
924 * points to the branch identity of the parent of the target's
927 * TB = { X, PB = { TL, Y } }
928 * or TB = { X, PB = { TL } }
930 * So we can't move the target's branch identity to the parent
931 * because that would corrupt the tree.
933 if (__predict_true(parent_bitlen
> 0)) {
935 * The parent is a two-way branch. We have to have
936 * do to this chang in two steps to keep internally
937 * consistent. First step is to copy our sibling from
938 * our parent to where we are pointing to parent's
939 * branch identiy. This remove all references to his
940 * branch identity from the tree. We then simply make
941 * the parent assume the target's branching duties.
943 * TB = { X, PB = { Y, TL } } --> PB = { X, Y }.
944 * TB = { X, PB = { TL, Y } } --> PB = { X, Y }.
945 * TB = { PB = { Y, TL }, X } --> PB = { Y, X }.
946 * TB = { PB = { TL, Y }, X } --> PB = { Y, X }.
948 PTN_BRANCH_SLOT(target
, slot
) =
949 PTN_BRANCH_SLOT(parent
, parent_slot
^ PT_SLOT_OTHER
);
950 *nodep
= ptree_move_branch(pt
, parent
, target
);
955 * If parent was a one-way branch, it must have been
956 * mask which pointed to a single leaf which we are
957 * removing. This means we have to convert the
958 * parent back to a leaf node. So in the same
959 * position that target pointed to parent, we place
960 * leaf pointer to parent. In the other position,
961 * we just put the other node from target.
963 * TB = { X, PB = { TL } } --> PB = { X, PL }
965 KASSERT(PTN_ISMASK_P(parent
));
966 KASSERT(slot
== ptree_testnode(pt
, parent
, target
));
967 PTN_BRANCH_SLOT(parent
, slot
) = PTN_LEAF(parent
);
968 PTN_BRANCH_SLOT(parent
, other_slot
) =
969 PTN_BRANCH_SLOT(target
, other_slot
);
970 PTN_SET_LEAF_POSITION(parent
,slot
);
971 PTN_SET_BRANCH_BITLEN(parent
, 1);
973 PTN_SET_BRANCH_BITOFF(parent
, PTN_BRANCH_BITOFF(target
));
974 PTN_SET_BRANCH_POSITION(parent
, PTN_BRANCH_POSITION(target
));
976 *nodep
= PTN_BRANCH(parent
);
982 if (__predict_false(PTN_BRANCH_BITLEN(parent
) == 0)) {
984 * Parent was a one-way branch which is changing back to a leaf.
985 * Since parent is no longer a one-way branch, it can take over
986 * target's branching duties.
988 * GB = { PB = { TL } } --> GB = { PL }
989 * TB = { X, Y } --> PB = { X, Y }
991 KASSERT(PTN_ISMASK_P(parent
));
992 KASSERT(parent
!= target
);
993 *removep
= PTN_LEAF(parent
);
995 #endif /* !PTNOMASK */
998 * Now we are the normal removal case. Since after the
999 * target's leaf identity is removed from the its parent,
1000 * that parent will only have one decendent. So we can
1001 * just as easily replace the node that has the parent's
1002 * branch identity with the surviving node. This freeing
1003 * parent from its branching duties which means it can
1004 * take over target's branching duties.
1006 * GB = { PB = { X, TL } } --> GB = { X }
1007 * TB = { V, W } --> PB = { V, W }
1009 const pt_slot_t other_slot
= parent_slot
^ PT_SLOT_OTHER
;
1010 uintptr_t other_node
= PTN_BRANCH_SLOT(parent
, other_slot
);
1011 const pt_slot_t target_slot
= (parent
== target
? branch_slot
: leaf_slot
);
1013 *removep
= other_node
;
1015 ptree_set_position(other_node
, target_slot
);
1018 * If target's branch identity contained its leaf identity, we
1019 * have nothing left to do. We've already moved 'X' so there
1020 * is no longer anything in the target's branch identiy that
1021 * has to be preserved.
1023 if (parent
== target
) {
1025 * GB = { TB = { X, TL } } --> GB = { X }
1026 * TB = { X, TL } --> don't care
1034 * If target wasn't used as a branch, then it must have been the
1035 * oddman-out of the tree (the one node that doesn't have a branch
1036 * identity). This makes parent the new oddman-out.
1038 if (*nodep
== PTN_LEAF(target
)) {
1039 KASSERT(nodep
== &PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
));
1040 PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
) = PTN_LEAF(parent
);
1046 * Finally move the target's branching duties to the parent.
1048 KASSERT(PTN_BRANCH_BITOFF(parent
) > PTN_BRANCH_BITOFF(target
));
1049 *nodep
= ptree_move_branch(pt
, parent
, target
);
1054 static const pt_node_t
*
1055 ptree_check_find_node2(const pt_tree_t
*pt
, const pt_node_t
*parent
,
1058 const pt_bitlen_t slots
= 1 << PTN_BRANCH_BITLEN(parent
);
1061 for (slot
= 0; slot
< slots
; slot
++) {
1062 const uintptr_t node
= PTN_BRANCH_SLOT(parent
, slot
);
1063 if (PTN_BRANCH_SLOT(parent
, slot
) == node
)
1066 for (slot
= 0; slot
< slots
; slot
++) {
1067 const uintptr_t node
= PTN_BRANCH_SLOT(parent
, slot
);
1068 const pt_node_t
*branch
;
1069 if (!PT_BRANCH_P(node
))
1071 branch
= ptree_check_find_node2(pt
, PT_NODE(node
), target
);
1080 ptree_check_leaf(const pt_tree_t
*pt
, const pt_node_t
*parent
,
1081 const pt_node_t
*ptn
)
1083 const pt_bitoff_t leaf_position
= PTN_LEAF_POSITION(ptn
);
1084 const pt_bitlen_t bitlen
= PTN_BRANCH_BITLEN(ptn
);
1085 const pt_bitlen_t mask_len
= PTN_MASK_BITLEN(ptn
);
1086 const uintptr_t leaf_node
= PTN_LEAF(ptn
);
1087 const bool is_parent_root
= (parent
== &pt
->pt_rootnode
);
1088 const bool is_mask
= PTN_ISMASK_P(ptn
);
1091 if (is_parent_root
) {
1092 ok
= ok
&& PTN_BRANCH_ODDMAN_SLOT(parent
) == leaf_node
;
1097 if (is_mask
&& PTN_ISMASK_P(parent
) && PTN_BRANCH_BITLEN(parent
) == 0) {
1098 ok
= ok
&& PTN_MASK_BITLEN(parent
) < mask_len
;
1100 ok
= ok
&& PTN_BRANCH_BITOFF(parent
) < mask_len
;
1103 ok
= ok
&& PTN_BRANCH_SLOT(parent
, leaf_position
) == leaf_node
;
1105 ok
= ok
&& leaf_position
== ptree_testnode(pt
, ptn
, parent
);
1107 if (PTN_BRANCH_ODDMAN_SLOT(&pt
->pt_rootnode
) != leaf_node
) {
1108 ok
= ok
&& bitlen
> 0;
1110 ok
= ok
&& ptn
== ptree_check_find_node2(pt
, ptn
, PTN_LEAF(ptn
));
1117 ptree_check_branch(const pt_tree_t
*pt
, const pt_node_t
*parent
,
1118 const pt_node_t
*ptn
)
1120 const bool is_parent_root
= (parent
== &pt
->pt_rootnode
);
1121 const pt_slot_t branch_slot
= PTN_BRANCH_POSITION(ptn
);
1122 const pt_bitoff_t bitoff
= PTN_BRANCH_BITOFF(ptn
);
1123 const pt_bitoff_t bitlen
= PTN_BRANCH_BITLEN(ptn
);
1124 const pt_bitoff_t parent_bitoff
= PTN_BRANCH_BITOFF(parent
);
1125 const pt_bitoff_t parent_bitlen
= PTN_BRANCH_BITLEN(parent
);
1126 const bool is_parent_mask
= PTN_ISMASK_P(parent
) && parent_bitlen
== 0;
1127 const bool is_mask
= PTN_ISMASK_P(ptn
) && bitlen
== 0;
1128 const pt_bitoff_t parent_mask_len
= PTN_MASK_BITLEN(parent
);
1129 const pt_bitoff_t mask_len
= PTN_MASK_BITLEN(ptn
);
1130 const pt_bitlen_t slots
= 1 << bitlen
;
1134 ok
= ok
&& PTN_BRANCH_SLOT(parent
, branch_slot
) == PTN_BRANCH(ptn
);
1136 ok
= ok
&& branch_slot
== ptree_testnode(pt
, ptn
, parent
);
1140 ok
= ok
&& bitoff
== mask_len
;
1142 if (is_parent_mask
) {
1143 ok
= ok
&& parent_mask_len
< mask_len
;
1145 ok
= ok
&& parent_bitoff
< bitoff
;
1149 if (is_parent_mask
) {
1150 ok
= ok
&& parent_bitoff
<= bitoff
;
1151 } else if (!is_parent_root
) {
1152 ok
= ok
&& parent_bitoff
< bitoff
;
1157 for (slot
= 0; slot
< slots
; slot
++) {
1158 const uintptr_t node
= PTN_BRANCH_SLOT(ptn
, slot
);
1159 pt_bitoff_t tmp_bitoff
= 0;
1161 ok
= ok
&& node
!= PTN_BRANCH(ptn
);
1164 ok
= ok
&& ptree_matchnode(pt
, PT_NODE(node
), ptn
, bitoff
, &tmp_bitoff
, &tmp_slot
);
1166 tmp_slot
= ptree_testnode(pt
, PT_NODE(node
), ptn
);
1167 ok
= ok
&& slot
== tmp_slot
;
1170 if (PT_LEAF_P(node
))
1171 ok
= ok
&& ptree_check_leaf(pt
, ptn
, PT_NODE(node
));
1173 ok
= ok
&& ptree_check_branch(pt
, ptn
, PT_NODE(node
));
1178 #endif /* PTCHECK */
1182 ptree_check(const pt_tree_t
*pt
)
1186 const pt_node_t
* const parent
= &pt
->pt_rootnode
;
1187 const uintptr_t node
= pt
->pt_root
;
1188 const pt_node_t
* const ptn
= PT_NODE(node
);
1190 ok
= ok
&& PTN_BRANCH_BITOFF(parent
) == 0;
1191 ok
= ok
&& !PTN_ISMASK_P(parent
);
1193 if (PT_NULL_P(node
))
1196 if (PT_LEAF_P(node
))
1197 ok
= ok
&& ptree_check_leaf(pt
, parent
, ptn
);
1199 ok
= ok
&& ptree_check_branch(pt
, parent
, ptn
);