Home | History | Annotate | Line # | Download | only in gen
ptree.c revision 1.10.32.2
      1  1.10.32.1   martin /*	$NetBSD: ptree.c,v 1.10.32.2 2020/04/21 19:37:49 martin Exp $	*/
      2        1.1     matt 
      3        1.1     matt /*-
      4        1.1     matt  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5        1.1     matt  * All rights reserved.
      6        1.1     matt  *
      7        1.1     matt  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1     matt  * by Matt Thomas <matt (at) 3am-software.com>.
      9        1.1     matt  *
     10        1.1     matt  * Redistribution and use in source and binary forms, with or without
     11        1.1     matt  * modification, are permitted provided that the following conditions
     12        1.1     matt  * are met:
     13        1.1     matt  * 1. Redistributions of source code must retain the above copyright
     14        1.1     matt  *    notice, this list of conditions and the following disclaimer.
     15        1.1     matt  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1     matt  *    notice, this list of conditions and the following disclaimer in the
     17        1.1     matt  *    documentation and/or other materials provided with the distribution.
     18        1.1     matt  *
     19        1.1     matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20        1.1     matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21        1.1     matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22        1.1     matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23        1.1     matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24        1.1     matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25        1.1     matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26        1.1     matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27        1.1     matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28        1.1     matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29        1.1     matt  * POSSIBILITY OF SUCH DAMAGE.
     30        1.1     matt  */
     31        1.1     matt 
     32        1.1     matt #define _PT_PRIVATE
     33        1.1     matt 
     34        1.1     matt #if defined(PTCHECK) && !defined(PTDEBUG)
     35        1.1     matt #define PTDEBUG
     36        1.1     matt #endif
     37        1.1     matt 
     38        1.1     matt #if defined(_KERNEL) || defined(_STANDALONE)
     39        1.1     matt #include <sys/param.h>
     40        1.1     matt #include <sys/types.h>
     41        1.1     matt #include <sys/systm.h>
     42        1.3  jnemeth #include <lib/libkern/libkern.h>
     43  1.10.32.1   martin __KERNEL_RCSID(0, "$NetBSD: ptree.c,v 1.10.32.2 2020/04/21 19:37:49 martin Exp $");
     44        1.1     matt #else
     45        1.1     matt #include <stddef.h>
     46        1.1     matt #include <stdint.h>
     47        1.1     matt #include <limits.h>
     48        1.1     matt #include <stdbool.h>
     49        1.1     matt #include <string.h>
     50        1.1     matt #ifdef PTDEBUG
     51        1.1     matt #include <assert.h>
     52        1.1     matt #define	KASSERT(e)	assert(e)
     53        1.1     matt #else
     54        1.1     matt #define	KASSERT(e)	do { } while (/*CONSTCOND*/ 0)
     55        1.1     matt #endif
     56  1.10.32.1   martin __RCSID("$NetBSD: ptree.c,v 1.10.32.2 2020/04/21 19:37:49 martin Exp $");
     57        1.1     matt #endif /* _KERNEL || _STANDALONE */
     58        1.1     matt 
     59        1.1     matt #ifdef _LIBC
     60        1.1     matt #include "namespace.h"
     61        1.1     matt #endif
     62        1.1     matt 
     63        1.1     matt #ifdef PTTEST
     64        1.1     matt #include "ptree.h"
     65        1.1     matt #else
     66        1.1     matt #include <sys/ptree.h>
     67        1.1     matt #endif
     68        1.1     matt 
     69        1.1     matt /*
     70        1.9    rmind  * This is an implementation of a radix / PATRICIA tree.  As in a traditional
     71        1.1     matt  * patricia tree, all the data is at the leaves of the tree.  An N-value
     72        1.1     matt  * tree would have N leaves, N-1 branching nodes, and a root pointer.  Each
     73        1.1     matt  * branching node would have left(0) and right(1) pointers that either point
     74        1.1     matt  * to another branching node or a leaf node.  The root pointer would also
     75        1.1     matt  * point to either the first branching node or a leaf node.  Leaf nodes
     76        1.1     matt  * have no need for pointers.
     77        1.1     matt  *
     78        1.1     matt  * However, allocation for these branching nodes is problematic since the
     79        1.9    rmind  * allocation could fail.  This would cause insertions to fail for reasons
     80        1.9    rmind  * beyond the user's control.  So to prevent this, in this implementation
     81        1.1     matt  * each node has two identities: its leaf identity and its branch identity.
     82        1.1     matt  * Each is separate from the other.  Every branch is tagged as to whether
     83        1.1     matt  * it points to a leaf or a branch.  This is not an attribute of the object
     84        1.1     matt  * but of the pointer to the object.  The low bit of the pointer is used as
     85        1.5     yamt  * the tag to determine whether it points to a leaf or branch identity, with
     86        1.1     matt  * branch identities having the low bit set.
     87        1.9    rmind  *
     88        1.1     matt  * A node's branch identity has one rule: when traversing the tree from the
     89        1.1     matt  * root to the node's leaf identity, one of the branches traversed will be via
     90        1.1     matt  * the node's branch identity.  Of course, that has an exception: since to
     91        1.1     matt  * store N leaves, you need N-1 branches.  That one node whose branch identity
     92        1.1     matt  * isn't used is stored as "oddman"-out in the root.
     93        1.1     matt  *
     94        1.1     matt  * Branching nodes also has a bit offset and a bit length which determines
     95        1.1     matt  * which branch slot is used.  The bit length can be zero resulting in a
     96        1.9    rmind  * one-way branch.  This happens in two special cases: the root and
     97        1.1     matt  * interior mask nodes.
     98        1.1     matt  *
     99        1.1     matt  * To support longest match first lookups, when a mask node (one that only
    100        1.1     matt  * match the first N bits) has children who first N bits match the mask nodes,
    101        1.1     matt  * that mask node is converted from being a leaf node to being a one-way
    102        1.1     matt  * branch-node.  The mask becomes fixed in position in the tree.  The mask
    103        1.5     yamt  * will always be the longest mask match for its descendants (unless they
    104        1.1     matt  * traverse an even longer match).
    105        1.1     matt  */
    106        1.1     matt 
    107        1.1     matt #define	NODETOITEM(pt, ptn)	\
    108        1.1     matt 	((void *)((uintptr_t)(ptn) - (pt)->pt_node_offset))
    109        1.1     matt #define	NODETOKEY(pt, ptn)	\
    110        1.1     matt 	((void *)((uintptr_t)(ptn) - (pt)->pt_node_offset + pt->pt_key_offset))
    111        1.1     matt #define	ITEMTONODE(pt, ptn)	\
    112        1.1     matt 	((pt_node_t *)((uintptr_t)(ptn) + (pt)->pt_node_offset))
    113        1.1     matt 
    114        1.1     matt bool ptree_check(const pt_tree_t *);
    115        1.1     matt #if PTCHECK > 1
    116        1.1     matt #define	PTREE_CHECK(pt)		ptree_check(pt)
    117        1.1     matt #else
    118        1.2     matt #define	PTREE_CHECK(pt)		do { } while (/*CONSTCOND*/ 0)
    119        1.1     matt #endif
    120        1.1     matt 
    121        1.1     matt static inline bool
    122        1.1     matt ptree_matchnode(const pt_tree_t *pt, const pt_node_t *target,
    123        1.1     matt 	const pt_node_t *ptn, pt_bitoff_t max_bitoff,
    124        1.1     matt 	pt_bitoff_t *bitoff_p, pt_slot_t *slots_p)
    125        1.1     matt {
    126        1.1     matt 	return (*pt->pt_ops->ptto_matchnode)(NODETOKEY(pt, target),
    127        1.6    rmind 	    (ptn != NULL ? NODETOKEY(pt, ptn) : NULL),
    128        1.6    rmind 	    max_bitoff, bitoff_p, slots_p, pt->pt_context);
    129        1.1     matt }
    130        1.1     matt 
    131        1.1     matt static inline pt_slot_t
    132        1.1     matt ptree_testnode(const pt_tree_t *pt, const pt_node_t *target,
    133        1.1     matt 	const pt_node_t *ptn)
    134        1.1     matt {
    135        1.1     matt 	const pt_bitlen_t bitlen = PTN_BRANCH_BITLEN(ptn);
    136        1.1     matt 	if (bitlen == 0)
    137        1.7     matt 		return PT_SLOT_ROOT;	/* mask or root, doesn't matter */
    138        1.1     matt 	return (*pt->pt_ops->ptto_testnode)(NODETOKEY(pt, target),
    139        1.6    rmind 	    PTN_BRANCH_BITOFF(ptn), bitlen, pt->pt_context);
    140        1.1     matt }
    141        1.1     matt 
    142        1.1     matt static inline bool
    143        1.1     matt ptree_matchkey(const pt_tree_t *pt, const void *key,
    144        1.1     matt 	const pt_node_t *ptn, pt_bitoff_t bitoff, pt_bitlen_t bitlen)
    145        1.1     matt {
    146        1.1     matt 	return (*pt->pt_ops->ptto_matchkey)(key, NODETOKEY(pt, ptn),
    147        1.6    rmind 	    bitoff, bitlen, pt->pt_context);
    148        1.1     matt }
    149        1.1     matt 
    150        1.1     matt static inline pt_slot_t
    151        1.1     matt ptree_testkey(const pt_tree_t *pt, const void *key, const pt_node_t *ptn)
    152        1.1     matt {
    153        1.7     matt 	const pt_bitlen_t bitlen = PTN_BRANCH_BITLEN(ptn);
    154        1.7     matt 	if (bitlen == 0)
    155        1.7     matt 		return PT_SLOT_ROOT;	/* mask or root, doesn't matter */
    156        1.6    rmind 	return (*pt->pt_ops->ptto_testkey)(key, PTN_BRANCH_BITOFF(ptn),
    157        1.6    rmind 	    PTN_BRANCH_BITLEN(ptn), pt->pt_context);
    158        1.1     matt }
    159        1.1     matt 
    160        1.1     matt static inline void
    161        1.1     matt ptree_set_position(uintptr_t node, pt_slot_t position)
    162        1.1     matt {
    163        1.1     matt 	if (PT_LEAF_P(node))
    164        1.1     matt 		PTN_SET_LEAF_POSITION(PT_NODE(node), position);
    165        1.1     matt 	else
    166        1.1     matt 		PTN_SET_BRANCH_POSITION(PT_NODE(node), position);
    167        1.1     matt }
    168        1.1     matt 
    169        1.1     matt void
    170        1.6    rmind ptree_init(pt_tree_t *pt, const pt_tree_ops_t *ops, void *context,
    171        1.6    rmind 	size_t node_offset, size_t key_offset)
    172        1.1     matt {
    173        1.1     matt 	memset(pt, 0, sizeof(*pt));
    174        1.1     matt 	pt->pt_node_offset = node_offset;
    175        1.1     matt 	pt->pt_key_offset = key_offset;
    176        1.6    rmind 	pt->pt_context = context;
    177        1.1     matt 	pt->pt_ops = ops;
    178        1.1     matt }
    179        1.1     matt 
    180        1.1     matt typedef struct {
    181        1.1     matt 	uintptr_t *id_insertp;
    182        1.1     matt 	pt_node_t *id_parent;
    183        1.1     matt 	uintptr_t id_node;
    184        1.1     matt 	pt_slot_t id_parent_slot;
    185        1.1     matt 	pt_bitoff_t id_bitoff;
    186        1.1     matt 	pt_slot_t id_slot;
    187        1.1     matt } pt_insertdata_t;
    188        1.1     matt 
    189        1.1     matt typedef bool (*pt_insertfunc_t)(pt_tree_t *, pt_node_t *, pt_insertdata_t *);
    190        1.1     matt 
    191        1.1     matt /*
    192        1.1     matt  * Move a branch identify from src to dst.  The leaves don't care since
    193        1.1     matt  * nothing for them has changed.
    194        1.1     matt  */
    195        1.2     matt /*ARGSUSED*/
    196        1.1     matt static uintptr_t
    197        1.1     matt ptree_move_branch(pt_tree_t * const pt, pt_node_t * const dst,
    198        1.1     matt 	const pt_node_t * const src)
    199        1.1     matt {
    200        1.1     matt 	KASSERT(PTN_BRANCH_BITLEN(src) == 1);
    201        1.1     matt 	/* set branch bitlen and bitoff in one step.  */
    202        1.1     matt 	dst->ptn_branchdata = src->ptn_branchdata;
    203        1.1     matt 	PTN_SET_BRANCH_POSITION(dst, PTN_BRANCH_POSITION(src));
    204        1.1     matt 	PTN_COPY_BRANCH_SLOTS(dst, src);
    205        1.1     matt 	return PTN_BRANCH(dst);
    206        1.1     matt }
    207        1.1     matt 
    208        1.1     matt #ifndef PTNOMASK
    209        1.1     matt static inline uintptr_t *
    210        1.1     matt ptree_find_branch(pt_tree_t * const pt, uintptr_t branch_node)
    211        1.1     matt {
    212        1.1     matt 	pt_node_t * const branch = PT_NODE(branch_node);
    213        1.1     matt 	pt_node_t *parent;
    214        1.1     matt 
    215        1.1     matt 	for (parent = &pt->pt_rootnode;;) {
    216        1.1     matt 		uintptr_t *nodep =
    217        1.1     matt 		    &PTN_BRANCH_SLOT(parent, ptree_testnode(pt, branch, parent));
    218        1.1     matt 		if (*nodep == branch_node)
    219        1.1     matt 			return nodep;
    220        1.1     matt 		if (PT_LEAF_P(*nodep))
    221        1.1     matt 			return NULL;
    222        1.1     matt 		parent = PT_NODE(*nodep);
    223        1.1     matt 	}
    224        1.1     matt }
    225        1.1     matt 
    226        1.1     matt static bool
    227        1.1     matt ptree_insert_leaf_after_mask(pt_tree_t * const pt, pt_node_t * const target,
    228        1.1     matt 	pt_insertdata_t * const id)
    229        1.1     matt {
    230        1.1     matt 	const uintptr_t target_node = PTN_LEAF(target);
    231        1.1     matt 	const uintptr_t mask_node = id->id_node;
    232        1.1     matt 	pt_node_t * const mask = PT_NODE(mask_node);
    233        1.1     matt 	const pt_bitlen_t mask_len = PTN_MASK_BITLEN(mask);
    234        1.1     matt 
    235        1.1     matt 	KASSERT(PT_LEAF_P(mask_node));
    236        1.1     matt 	KASSERT(PTN_LEAF_POSITION(mask) == id->id_parent_slot);
    237        1.1     matt 	KASSERT(mask_len <= id->id_bitoff);
    238        1.1     matt 	KASSERT(PTN_ISMASK_P(mask));
    239        1.1     matt 	KASSERT(!PTN_ISMASK_P(target) || mask_len < PTN_MASK_BITLEN(target));
    240        1.1     matt 
    241        1.1     matt 	if (mask_node == PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode)) {
    242        1.1     matt 		KASSERT(id->id_parent != mask);
    243        1.1     matt 		/*
    244        1.1     matt 		 * Nice, mask was an oddman.  So just set the oddman to target.
    245        1.1     matt 		 */
    246        1.1     matt 		PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode) = target_node;
    247        1.1     matt 	} else {
    248        1.1     matt 		/*
    249        1.1     matt 		 * We need to find out who's pointing to mask's branch
    250        1.1     matt 		 * identity.  We know that between root and the leaf identity,
    251        1.1     matt 		 * we must traverse the node's branch identity.
    252        1.1     matt 		 */
    253        1.1     matt 		uintptr_t * const mask_nodep = ptree_find_branch(pt, PTN_BRANCH(mask));
    254        1.1     matt 		KASSERT(mask_nodep != NULL);
    255        1.1     matt 		KASSERT(*mask_nodep == PTN_BRANCH(mask));
    256        1.1     matt 		KASSERT(PTN_BRANCH_BITLEN(mask) == 1);
    257        1.1     matt 
    258        1.1     matt 		/*
    259        1.1     matt 		 * Alas, mask was used as a branch.  Since the mask is becoming
    260        1.1     matt 		 * a one-way branch, we need make target take over mask's
    261        1.1     matt 		 * branching responsibilities.  Only then can we change it.
    262        1.1     matt 		 */
    263        1.1     matt 		*mask_nodep = ptree_move_branch(pt, target, mask);
    264        1.1     matt 
    265        1.1     matt 		/*
    266        1.1     matt 		 * However, it's possible that mask's parent is itself.  If
    267        1.1     matt 		 * that's true, update the insert point to use target since it
    268        1.1     matt 		 * has taken over mask's branching duties.
    269        1.1     matt 		 */
    270        1.1     matt 		if (id->id_parent == mask)
    271        1.1     matt 			id->id_insertp = &PTN_BRANCH_SLOT(target,
    272        1.1     matt 			    id->id_parent_slot);
    273        1.1     matt 	}
    274        1.1     matt 
    275        1.1     matt 	PTN_SET_BRANCH_BITLEN(mask, 0);
    276        1.1     matt 	PTN_SET_BRANCH_BITOFF(mask, mask_len);
    277        1.1     matt 
    278        1.1     matt 	PTN_BRANCH_ROOT_SLOT(mask) = target_node;
    279        1.1     matt 	PTN_BRANCH_ODDMAN_SLOT(mask) = PT_NULL;
    280        1.1     matt 	PTN_SET_LEAF_POSITION(target, PT_SLOT_ROOT);
    281        1.1     matt 	PTN_SET_BRANCH_POSITION(mask, id->id_parent_slot);
    282        1.1     matt 
    283        1.1     matt 	/*
    284        1.1     matt 	 * Now that everything is done, to make target visible we need to
    285        1.1     matt 	 * change mask from a leaf to a branch.
    286        1.1     matt 	 */
    287        1.1     matt 	*id->id_insertp = PTN_BRANCH(mask);
    288        1.1     matt 	PTREE_CHECK(pt);
    289        1.1     matt 	return true;
    290        1.1     matt }
    291        1.1     matt 
    292        1.2     matt /*ARGSUSED*/
    293        1.1     matt static bool
    294        1.1     matt ptree_insert_mask_before_node(pt_tree_t * const pt, pt_node_t * const target,
    295        1.1     matt 	pt_insertdata_t * const id)
    296        1.1     matt {
    297        1.1     matt 	const uintptr_t node = id->id_node;
    298        1.1     matt 	pt_node_t * const ptn = PT_NODE(node);
    299        1.1     matt 	const pt_slot_t mask_len = PTN_MASK_BITLEN(target);
    300        1.1     matt 	const pt_bitlen_t node_mask_len = PTN_MASK_BITLEN(ptn);
    301        1.1     matt 
    302        1.1     matt 	KASSERT(PT_LEAF_P(node) || id->id_parent_slot == PTN_BRANCH_POSITION(ptn));
    303        1.1     matt 	KASSERT(PT_BRANCH_P(node) || id->id_parent_slot == PTN_LEAF_POSITION(ptn));
    304        1.1     matt 	KASSERT(PTN_ISMASK_P(target));
    305        1.1     matt 
    306        1.1     matt 	/*
    307        1.1     matt 	 * If the node we are placing ourself in front is a mask with the
    308        1.1     matt 	 * same mask length as us, return failure.
    309        1.1     matt 	 */
    310        1.1     matt 	if (PTN_ISMASK_P(ptn) && node_mask_len == mask_len)
    311        1.1     matt 		return false;
    312        1.1     matt 
    313        1.1     matt 	PTN_SET_BRANCH_BITLEN(target, 0);
    314        1.1     matt 	PTN_SET_BRANCH_BITOFF(target, mask_len);
    315        1.1     matt 
    316        1.1     matt 	PTN_BRANCH_SLOT(target, PT_SLOT_ROOT) = node;
    317        1.1     matt 	*id->id_insertp = PTN_BRANCH(target);
    318        1.1     matt 
    319        1.1     matt 	PTN_SET_BRANCH_POSITION(target, id->id_parent_slot);
    320        1.1     matt 	ptree_set_position(node, PT_SLOT_ROOT);
    321        1.1     matt 
    322        1.1     matt 	PTREE_CHECK(pt);
    323        1.1     matt 	return true;
    324        1.1     matt }
    325        1.1     matt #endif /* !PTNOMASK */
    326        1.1     matt 
    327        1.2     matt /*ARGSUSED*/
    328        1.1     matt static bool
    329        1.1     matt ptree_insert_branch_at_node(pt_tree_t * const pt, pt_node_t * const target,
    330        1.1     matt 	pt_insertdata_t * const id)
    331        1.1     matt {
    332        1.1     matt 	const uintptr_t target_node = PTN_LEAF(target);
    333        1.1     matt 	const uintptr_t node = id->id_node;
    334        1.1     matt 	const pt_slot_t other_slot = id->id_slot ^ PT_SLOT_OTHER;
    335        1.1     matt 
    336        1.1     matt 	KASSERT(PT_BRANCH_P(node) || id->id_parent_slot == PTN_LEAF_POSITION(PT_NODE(node)));
    337        1.1     matt 	KASSERT(PT_LEAF_P(node) || id->id_parent_slot == PTN_BRANCH_POSITION(PT_NODE(node)));
    338        1.1     matt 	KASSERT((node == pt->pt_root) == (id->id_parent == &pt->pt_rootnode));
    339        1.1     matt #ifndef PTNOMASK
    340        1.1     matt 	KASSERT(!PTN_ISMASK_P(target) || id->id_bitoff <= PTN_MASK_BITLEN(target));
    341        1.1     matt #endif
    342        1.1     matt 	KASSERT(node == pt->pt_root || PTN_BRANCH_BITOFF(id->id_parent) + PTN_BRANCH_BITLEN(id->id_parent) <= id->id_bitoff);
    343        1.1     matt 
    344        1.1     matt 	PTN_SET_BRANCH_BITOFF(target, id->id_bitoff);
    345        1.1     matt 	PTN_SET_BRANCH_BITLEN(target, 1);
    346        1.1     matt 
    347        1.1     matt 	PTN_BRANCH_SLOT(target, id->id_slot) = target_node;
    348        1.1     matt 	PTN_BRANCH_SLOT(target, other_slot) = node;
    349        1.1     matt 	*id->id_insertp = PTN_BRANCH(target);
    350        1.1     matt 
    351        1.1     matt 	PTN_SET_LEAF_POSITION(target, id->id_slot);
    352        1.1     matt 	ptree_set_position(node, other_slot);
    353        1.1     matt 
    354        1.1     matt 	PTN_SET_BRANCH_POSITION(target, id->id_parent_slot);
    355        1.1     matt 	PTREE_CHECK(pt);
    356        1.1     matt 	return true;
    357        1.1     matt }
    358        1.1     matt 
    359        1.1     matt static bool
    360        1.1     matt ptree_insert_leaf(pt_tree_t * const pt, pt_node_t * const target,
    361        1.1     matt 	pt_insertdata_t * const id)
    362        1.1     matt {
    363        1.1     matt 	const uintptr_t leaf_node = id->id_node;
    364        1.1     matt 	pt_node_t * const leaf = PT_NODE(leaf_node);
    365        1.1     matt #ifdef PTNOMASK
    366        1.1     matt 	const bool inserting_mask = false;
    367        1.1     matt 	const bool at_mask = false;
    368        1.1     matt #else
    369        1.1     matt 	const bool inserting_mask = PTN_ISMASK_P(target);
    370        1.1     matt 	const bool at_mask = PTN_ISMASK_P(leaf);
    371        1.1     matt 	const pt_bitlen_t leaf_masklen = PTN_MASK_BITLEN(leaf);
    372        1.1     matt 	const pt_bitlen_t target_masklen = PTN_MASK_BITLEN(target);
    373        1.1     matt #endif
    374        1.1     matt 	pt_insertfunc_t insertfunc = ptree_insert_branch_at_node;
    375        1.1     matt 	bool matched;
    376        1.1     matt 
    377        1.1     matt 	/*
    378        1.1     matt 	 * In all likelyhood we are going simply going to insert a branch
    379        1.1     matt 	 * where this leaf is which will point to the old and new leaves.
    380        1.1     matt 	 */
    381        1.1     matt 	KASSERT(PT_LEAF_P(leaf_node));
    382        1.1     matt 	KASSERT(PTN_LEAF_POSITION(leaf) == id->id_parent_slot);
    383        1.1     matt 	matched = ptree_matchnode(pt, target, leaf, UINT_MAX,
    384        1.1     matt 	    &id->id_bitoff, &id->id_slot);
    385        1.1     matt 	if (__predict_false(!inserting_mask)) {
    386        1.1     matt 		/*
    387        1.1     matt 		 * We aren't inserting a mask nor is the leaf a mask, which
    388        1.1     matt 		 * means we are trying to insert a duplicate leaf.  Can't do
    389        1.1     matt 		 * that.
    390        1.1     matt 		 */
    391        1.1     matt 		if (!at_mask && matched)
    392        1.1     matt 			return false;
    393        1.1     matt 
    394        1.1     matt #ifndef PTNOMASK
    395        1.1     matt 		/*
    396        1.1     matt 		 * We are at a mask and the leaf we are about to insert
    397        1.1     matt 		 * is at or beyond the mask, we need to convert the mask
    398        1.1     matt 		 * from a leaf to a one-way branch interior mask.
    399        1.1     matt 		 */
    400        1.1     matt 		if (at_mask && id->id_bitoff >= leaf_masklen)
    401        1.1     matt 			insertfunc = ptree_insert_leaf_after_mask;
    402        1.1     matt #endif /* PTNOMASK */
    403        1.1     matt 	}
    404        1.1     matt #ifndef PTNOMASK
    405        1.1     matt 	else {
    406        1.1     matt 		/*
    407        1.1     matt 		 * We are inserting a mask.
    408        1.1     matt 		 */
    409        1.1     matt 		if (matched) {
    410        1.1     matt 			/*
    411        1.1     matt 			 * If the leaf isn't a mask, we obviously have to
    412        1.1     matt 			 * insert the new mask before non-mask leaf.  If the
    413        1.1     matt 			 * leaf is a mask, and the new node has a LEQ mask
    414        1.1     matt 			 * length it too needs to inserted before leaf (*).
    415        1.1     matt 			 *
    416        1.1     matt 			 * In other cases, we place the new mask as leaf after
    417        1.1     matt 			 * leaf mask.  Which mask comes first will be a one-way
    418        1.1     matt 			 * branch interior mask node which has the other mask
    419        1.1     matt 			 * node as a child.
    420        1.1     matt 			 *
    421        1.1     matt 			 * (*) ptree_insert_mask_before_node can detect a
    422        1.1     matt 			 * duplicate mask and return failure if needed.
    423        1.1     matt 			 */
    424        1.1     matt 			if (!at_mask || target_masklen <= leaf_masklen)
    425        1.1     matt 				insertfunc = ptree_insert_mask_before_node;
    426        1.1     matt 			else
    427        1.1     matt 				insertfunc = ptree_insert_leaf_after_mask;
    428        1.1     matt 		} else if (at_mask && id->id_bitoff >= leaf_masklen) {
    429        1.1     matt 			/*
    430        1.1     matt 			 * If the new mask has a bit offset GEQ than the leaf's
    431        1.1     matt 			 * mask length, convert the left to a one-way branch
    432        1.1     matt 			 * interior mask and make that point to the new [leaf]
    433        1.1     matt 			 * mask.
    434        1.1     matt 			 */
    435        1.1     matt 			insertfunc = ptree_insert_leaf_after_mask;
    436        1.1     matt 		} else {
    437        1.1     matt 			/*
    438        1.1     matt 			 * The new mask has a bit offset less than the leaf's
    439        1.1     matt 			 * mask length or if the leaf isn't a mask at all, the
    440        1.1     matt 			 * new mask deserves to be its own leaf so we use the
    441        1.1     matt 			 * default insertfunc to do that.
    442        1.1     matt 			 */
    443        1.1     matt 		}
    444        1.1     matt 	}
    445        1.1     matt #endif /* PTNOMASK */
    446        1.1     matt 
    447        1.1     matt 	return (*insertfunc)(pt, target, id);
    448        1.1     matt }
    449        1.1     matt 
    450        1.1     matt static bool
    451        1.1     matt ptree_insert_node_common(pt_tree_t *pt, void *item)
    452        1.1     matt {
    453        1.1     matt 	pt_node_t * const target = ITEMTONODE(pt, item);
    454        1.1     matt #ifndef PTNOMASK
    455        1.1     matt 	const bool inserting_mask = PTN_ISMASK_P(target);
    456        1.1     matt 	const pt_bitlen_t target_masklen = PTN_MASK_BITLEN(target);
    457        1.1     matt #endif
    458        1.1     matt 	pt_insertfunc_t insertfunc;
    459        1.1     matt 	pt_insertdata_t id;
    460        1.1     matt 
    461        1.1     matt 	/*
    462        1.8     matt 	 * If this node already exists in the tree, return failure.
    463        1.8     matt 	 */
    464        1.8     matt 	if (target == PT_NODE(pt->pt_root))
    465        1.8     matt 		return false;
    466        1.8     matt 
    467        1.8     matt 	/*
    468        1.1     matt 	 * We need a leaf so we can match against.  Until we get a leaf
    469        1.1     matt 	 * we having nothing to test against.
    470        1.1     matt 	 */
    471        1.1     matt 	if (__predict_false(PT_NULL_P(pt->pt_root))) {
    472        1.1     matt 		PTN_BRANCH_ROOT_SLOT(&pt->pt_rootnode) = PTN_LEAF(target);
    473        1.1     matt 		PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode) = PTN_LEAF(target);
    474        1.1     matt 		PTN_SET_LEAF_POSITION(target, PT_SLOT_ROOT);
    475        1.1     matt 		PTREE_CHECK(pt);
    476        1.1     matt 		return true;
    477        1.1     matt 	}
    478        1.1     matt 
    479        1.1     matt 	id.id_bitoff = 0;
    480        1.1     matt 	id.id_parent = &pt->pt_rootnode;
    481        1.1     matt 	id.id_parent_slot = PT_SLOT_ROOT;
    482        1.1     matt 	id.id_insertp = &PTN_BRANCH_ROOT_SLOT(id.id_parent);
    483        1.1     matt 	for (;;) {
    484        1.1     matt 		pt_bitoff_t branch_bitoff;
    485        1.1     matt 		pt_node_t * const ptn = PT_NODE(*id.id_insertp);
    486        1.1     matt 		id.id_node = *id.id_insertp;
    487        1.1     matt 
    488        1.1     matt 		/*
    489        1.8     matt 		 * If this node already exists in the tree, return failure.
    490        1.8     matt 		 */
    491        1.8     matt 		if (target == ptn)
    492        1.8     matt 			return false;
    493        1.8     matt 
    494        1.8     matt 		/*
    495        1.1     matt 		 * If we hit a leaf, try to insert target at leaf.  We could
    496        1.1     matt 		 * have inlined ptree_insert_leaf here but that would have
    497        1.1     matt 		 * made this routine much harder to understand.  Trust the
    498        1.1     matt 		 * compiler to optimize this properly.
    499        1.1     matt 		 */
    500        1.1     matt 		if (PT_LEAF_P(id.id_node)) {
    501        1.1     matt 			KASSERT(PTN_LEAF_POSITION(ptn) == id.id_parent_slot);
    502        1.1     matt 			insertfunc = ptree_insert_leaf;
    503        1.1     matt 			break;
    504        1.1     matt 		}
    505        1.1     matt 
    506        1.1     matt 		/*
    507        1.1     matt 		 * If we aren't a leaf, we must be a branch.  Make sure we are
    508        1.1     matt 		 * in the slot we think we are.
    509        1.1     matt 		 */
    510        1.1     matt 		KASSERT(PT_BRANCH_P(id.id_node));
    511        1.1     matt 		KASSERT(PTN_BRANCH_POSITION(ptn) == id.id_parent_slot);
    512        1.1     matt 
    513        1.1     matt 		/*
    514        1.1     matt 		 * Where is this branch?
    515        1.1     matt 		 */
    516        1.1     matt 		branch_bitoff = PTN_BRANCH_BITOFF(ptn);
    517        1.1     matt 
    518        1.1     matt #ifndef PTNOMASK
    519        1.1     matt 		/*
    520        1.1     matt 		 * If this is a one-way mask node, its offset must equal
    521        1.1     matt 		 * its mask's bitlen.
    522        1.1     matt 		 */
    523        1.1     matt 		KASSERT(!(PTN_ISMASK_P(ptn) && PTN_BRANCH_BITLEN(ptn) == 0) || PTN_MASK_BITLEN(ptn) == branch_bitoff);
    524        1.1     matt 
    525        1.1     matt 		/*
    526        1.1     matt 		 * If we are inserting a mask, and we know that at this point
    527        1.1     matt 		 * all bits before the current bit offset match both the target
    528        1.1     matt 		 * and the branch.  If the target's mask length is LEQ than
    529        1.1     matt 		 * this branch's bit offset, then this is where the mask needs
    530        1.1     matt 		 * to added to the tree.
    531        1.1     matt 		 */
    532        1.1     matt 		if (__predict_false(inserting_mask)
    533        1.1     matt 		    && (PTN_ISROOT_P(pt, id.id_parent)
    534        1.1     matt 			|| id.id_bitoff < target_masklen)
    535        1.1     matt 		    && target_masklen <= branch_bitoff) {
    536        1.1     matt 			/*
    537        1.1     matt 			 * We don't know about the bits (if any) between
    538        1.1     matt 			 * id.id_bitoff and the target's mask length match
    539        1.1     matt 			 * both the target and the branch.  If the target's
    540        1.1     matt 			 * mask length is greater than the current bit offset
    541        1.1     matt 			 * make sure the untested bits match both the target
    542        1.1     matt 			 * and the branch.
    543        1.1     matt 			 */
    544        1.1     matt 			if (target_masklen == id.id_bitoff
    545        1.1     matt 			    || ptree_matchnode(pt, target, ptn, target_masklen,
    546        1.1     matt 				    &id.id_bitoff, &id.id_slot)) {
    547        1.1     matt 				/*
    548        1.1     matt 				 * The bits matched, so insert the mask as a
    549        1.1     matt 				 * one-way branch.
    550        1.1     matt 				 */
    551        1.1     matt 				insertfunc = ptree_insert_mask_before_node;
    552        1.1     matt 				break;
    553        1.1     matt 			} else if (id.id_bitoff < branch_bitoff) {
    554        1.1     matt 				/*
    555        1.1     matt 				 * They didn't match, so create a normal branch
    556        1.1     matt 				 * because this mask needs to a be a new leaf.
    557        1.1     matt 				 */
    558        1.1     matt 				insertfunc = ptree_insert_branch_at_node;
    559        1.1     matt 				break;
    560        1.1     matt 			}
    561        1.1     matt 		}
    562        1.1     matt #endif /* PTNOMASK */
    563        1.1     matt 
    564        1.1     matt 		/*
    565        1.1     matt 		 * If we are skipping some bits, verify they match the node.
    566        1.1     matt 		 * If they don't match, it means we have a leaf to insert.
    567        1.1     matt 		 * Note that if we are advancing bit by bit, we'll skip
    568        1.1     matt 		 * doing matchnode and walk the tree bit by bit via testnode.
    569        1.1     matt 		 */
    570        1.1     matt 		if (id.id_bitoff < branch_bitoff
    571        1.1     matt 		    && !ptree_matchnode(pt, target, ptn, branch_bitoff,
    572        1.1     matt 					&id.id_bitoff, &id.id_slot)) {
    573        1.1     matt 			KASSERT(id.id_bitoff < branch_bitoff);
    574        1.1     matt 			insertfunc = ptree_insert_branch_at_node;
    575        1.1     matt 			break;
    576        1.1     matt 		}
    577        1.1     matt 
    578        1.1     matt 		/*
    579        1.1     matt 		 * At this point, all bits before branch_bitoff are known
    580        1.1     matt 		 * to match the target.
    581        1.1     matt 		 */
    582        1.1     matt 		KASSERT(id.id_bitoff >= branch_bitoff);
    583        1.1     matt 
    584        1.1     matt 		/*
    585        1.1     matt 		 * Decend the tree one level.
    586        1.1     matt 		 */
    587        1.1     matt 		id.id_parent = ptn;
    588        1.1     matt 		id.id_parent_slot = ptree_testnode(pt, target, id.id_parent);
    589        1.1     matt 		id.id_bitoff += PTN_BRANCH_BITLEN(id.id_parent);
    590        1.1     matt 		id.id_insertp = &PTN_BRANCH_SLOT(id.id_parent, id.id_parent_slot);
    591        1.1     matt 	}
    592        1.1     matt 
    593        1.1     matt 	/*
    594        1.1     matt 	 * Do the actual insertion.
    595        1.1     matt 	 */
    596        1.1     matt 	return (*insertfunc)(pt, target, &id);
    597        1.1     matt }
    598        1.1     matt 
    599        1.1     matt bool
    600        1.1     matt ptree_insert_node(pt_tree_t *pt, void *item)
    601        1.1     matt {
    602        1.1     matt 	pt_node_t * const target = ITEMTONODE(pt, item);
    603        1.1     matt 
    604        1.1     matt 	memset(target, 0, sizeof(*target));
    605        1.1     matt 	return ptree_insert_node_common(pt, target);
    606        1.1     matt }
    607        1.1     matt 
    608        1.1     matt #ifndef PTNOMASK
    609        1.1     matt bool
    610        1.1     matt ptree_insert_mask_node(pt_tree_t *pt, void *item, pt_bitlen_t mask_len)
    611        1.1     matt {
    612        1.1     matt 	pt_node_t * const target = ITEMTONODE(pt, item);
    613        1.1     matt 	pt_bitoff_t bitoff = mask_len;
    614        1.1     matt 	pt_slot_t slot;
    615        1.1     matt 
    616        1.1     matt 	memset(target, 0, sizeof(*target));
    617        1.1     matt 	KASSERT(mask_len == 0 || (~PT__MASK(PTN_MASK_BITLEN) & mask_len) == 0);
    618        1.1     matt 	/*
    619        1.1     matt 	 * Only the first <mask_len> bits can be non-zero.
    620        1.1     matt 	 * All other bits must be 0.
    621        1.1     matt 	 */
    622        1.1     matt 	if (!ptree_matchnode(pt, target, NULL, UINT_MAX, &bitoff, &slot))
    623        1.1     matt 		return false;
    624        1.1     matt 	PTN_SET_MASK_BITLEN(target, mask_len);
    625        1.1     matt 	PTN_MARK_MASK(target);
    626        1.1     matt 	return ptree_insert_node_common(pt, target);
    627        1.1     matt }
    628        1.1     matt #endif /* !PTNOMASH */
    629        1.1     matt 
    630        1.1     matt void *
    631        1.9    rmind ptree_find_filtered_node(pt_tree_t *pt, const void *key, pt_filter_t filter,
    632        1.1     matt 	void *filter_arg)
    633        1.1     matt {
    634        1.1     matt #ifndef PTNOMASK
    635        1.1     matt 	pt_node_t *mask = NULL;
    636        1.1     matt #endif
    637        1.1     matt 	bool at_mask = false;
    638        1.1     matt 	pt_node_t *ptn, *parent;
    639        1.1     matt 	pt_bitoff_t bitoff;
    640        1.1     matt 	pt_slot_t parent_slot;
    641        1.1     matt 
    642        1.1     matt 	if (PT_NULL_P(PTN_BRANCH_ROOT_SLOT(&pt->pt_rootnode)))
    643        1.1     matt 		return NULL;
    644        1.1     matt 
    645        1.1     matt 	bitoff = 0;
    646        1.1     matt 	parent = &pt->pt_rootnode;
    647        1.1     matt 	parent_slot = PT_SLOT_ROOT;
    648        1.1     matt 	for (;;) {
    649        1.1     matt 		const uintptr_t node = PTN_BRANCH_SLOT(parent, parent_slot);
    650        1.1     matt 		const pt_slot_t branch_bitoff = PTN_BRANCH_BITOFF(PT_NODE(node));
    651        1.1     matt 		ptn = PT_NODE(node);
    652        1.1     matt 
    653        1.1     matt 		if (PT_LEAF_P(node)) {
    654        1.1     matt #ifndef PTNOMASK
    655        1.1     matt 			at_mask = PTN_ISMASK_P(ptn);
    656        1.1     matt #endif
    657        1.1     matt 			break;
    658        1.1     matt 		}
    659        1.1     matt 
    660        1.1     matt 		if (bitoff < branch_bitoff) {
    661        1.1     matt 			if (!ptree_matchkey(pt, key, ptn, bitoff, branch_bitoff - bitoff)) {
    662        1.1     matt #ifndef PTNOMASK
    663        1.1     matt 				if (mask != NULL)
    664        1.1     matt 					return NODETOITEM(pt, mask);
    665        1.1     matt #endif
    666        1.1     matt 				return NULL;
    667        1.1     matt 			}
    668        1.1     matt 			bitoff = branch_bitoff;
    669        1.1     matt 		}
    670        1.1     matt 
    671        1.1     matt #ifndef PTNOMASK
    672        1.1     matt 		if (PTN_ISMASK_P(ptn) && PTN_BRANCH_BITLEN(ptn) == 0
    673        1.1     matt 		    && (!filter
    674        1.1     matt 		        || (*filter)(filter_arg, NODETOITEM(pt, ptn),
    675        1.1     matt 				     PT_FILTER_MASK)))
    676        1.1     matt 			mask = ptn;
    677        1.1     matt #endif
    678        1.1     matt 
    679        1.1     matt 		parent = ptn;
    680        1.1     matt 		parent_slot = ptree_testkey(pt, key, parent);
    681        1.1     matt 		bitoff += PTN_BRANCH_BITLEN(parent);
    682        1.1     matt 	}
    683        1.1     matt 
    684        1.1     matt 	KASSERT(PTN_ISROOT_P(pt, parent) || PTN_BRANCH_BITOFF(parent) + PTN_BRANCH_BITLEN(parent) == bitoff);
    685        1.1     matt 	if (!filter || (*filter)(filter_arg, NODETOITEM(pt, ptn), at_mask ? PT_FILTER_MASK : 0)) {
    686        1.1     matt #ifndef PTNOMASK
    687        1.1     matt 		if (PTN_ISMASK_P(ptn)) {
    688        1.1     matt 			const pt_bitlen_t mask_len = PTN_MASK_BITLEN(ptn);
    689        1.1     matt 			if (bitoff == PTN_MASK_BITLEN(ptn))
    690        1.1     matt 				return NODETOITEM(pt, ptn);
    691        1.1     matt 			if (ptree_matchkey(pt, key, ptn, bitoff, mask_len - bitoff))
    692        1.1     matt 				return NODETOITEM(pt, ptn);
    693        1.1     matt 		} else
    694        1.1     matt #endif /* !PTNOMASK */
    695        1.1     matt 		if (ptree_matchkey(pt, key, ptn, bitoff, UINT_MAX))
    696        1.1     matt 			return NODETOITEM(pt, ptn);
    697        1.1     matt 	}
    698        1.1     matt 
    699        1.1     matt #ifndef PTNOMASK
    700        1.1     matt 	/*
    701        1.1     matt 	 * By virtue of how the mask was placed in the tree,
    702        1.1     matt 	 * all nodes descended from it will match it.  But the bits
    703        1.1     matt 	 * before the mask still need to be checked and since the
    704        1.1     matt 	 * mask was a branch, that was done implicitly.
    705        1.1     matt 	 */
    706        1.1     matt 	if (mask != NULL) {
    707        1.1     matt 		KASSERT(ptree_matchkey(pt, key, mask, 0, PTN_MASK_BITLEN(mask)));
    708        1.1     matt 		return NODETOITEM(pt, mask);
    709        1.1     matt 	}
    710        1.1     matt #endif /* !PTNOMASK */
    711        1.1     matt 
    712        1.1     matt 	/*
    713        1.1     matt 	 * Nothing matched.
    714        1.1     matt 	 */
    715        1.1     matt 	return NULL;
    716        1.1     matt }
    717        1.1     matt 
    718        1.1     matt void *
    719        1.1     matt ptree_iterate(pt_tree_t *pt, const void *item, pt_direction_t direction)
    720        1.1     matt {
    721        1.1     matt 	const pt_node_t * const target = ITEMTONODE(pt, item);
    722        1.1     matt 	uintptr_t node, next_node;
    723        1.1     matt 
    724        1.1     matt 	if (direction != PT_ASCENDING && direction != PT_DESCENDING)
    725        1.1     matt 		return NULL;
    726        1.1     matt 
    727        1.1     matt 	node = PTN_BRANCH_ROOT_SLOT(&pt->pt_rootnode);
    728        1.1     matt 	if (PT_NULL_P(node))
    729        1.1     matt 		return NULL;
    730        1.1     matt 
    731        1.1     matt 	if (item == NULL) {
    732        1.1     matt 		pt_node_t * const ptn = PT_NODE(node);
    733        1.1     matt 		if (direction == PT_ASCENDING
    734        1.1     matt 		    && PTN_ISMASK_P(ptn) && PTN_BRANCH_BITLEN(ptn) == 0)
    735        1.1     matt 			return NODETOITEM(pt, ptn);
    736        1.1     matt 		next_node = node;
    737        1.1     matt 	} else {
    738        1.1     matt #ifndef PTNOMASK
    739        1.1     matt 		uintptr_t mask_node = PT_NULL;
    740        1.1     matt #endif /* !PTNOMASK */
    741        1.1     matt 		next_node = PT_NULL;
    742        1.1     matt 		while (!PT_LEAF_P(node)) {
    743        1.1     matt 			pt_node_t * const ptn = PT_NODE(node);
    744        1.1     matt 			pt_slot_t slot;
    745        1.1     matt #ifndef PTNOMASK
    746        1.1     matt 			if (PTN_ISMASK_P(ptn) && PTN_BRANCH_BITLEN(ptn) == 0) {
    747        1.1     matt 				if (ptn == target)
    748        1.1     matt 					break;
    749        1.1     matt 				if (direction == PT_DESCENDING) {
    750        1.1     matt 					mask_node = node;
    751        1.1     matt 					next_node = PT_NULL;
    752        1.1     matt 				}
    753        1.1     matt 			}
    754        1.1     matt #endif /* !PTNOMASK */
    755        1.1     matt 			slot = ptree_testnode(pt, target, ptn);
    756        1.1     matt 			node = PTN_BRANCH_SLOT(ptn, slot);
    757        1.1     matt 			if (direction == PT_ASCENDING) {
    758        1.4    lukem 				if (slot != (pt_slot_t)((1 << PTN_BRANCH_BITLEN(ptn)) - 1))
    759        1.1     matt 					next_node = PTN_BRANCH_SLOT(ptn, slot + 1);
    760        1.1     matt 			} else {
    761        1.1     matt 				if (slot > 0) {
    762        1.1     matt #ifndef PTNOMASK
    763        1.1     matt 					mask_node = PT_NULL;
    764        1.1     matt #endif /* !PTNOMASK */
    765        1.1     matt 					next_node = PTN_BRANCH_SLOT(ptn, slot - 1);
    766        1.1     matt 				}
    767        1.1     matt 			}
    768        1.1     matt 		}
    769        1.1     matt 		if (PT_NODE(node) != target)
    770        1.1     matt 			return NULL;
    771        1.1     matt #ifndef PTNOMASK
    772        1.1     matt 		if (PT_BRANCH_P(node)) {
    773        1.1     matt 			pt_node_t *ptn = PT_NODE(node);
    774        1.1     matt 			KASSERT(PTN_ISMASK_P(PT_NODE(node)) && PTN_BRANCH_BITLEN(PT_NODE(node)) == 0);
    775        1.1     matt 			if (direction == PT_ASCENDING) {
    776        1.1     matt 				next_node = PTN_BRANCH_ROOT_SLOT(ptn);
    777        1.1     matt 				ptn = PT_NODE(next_node);
    778        1.1     matt 			}
    779        1.1     matt 		}
    780        1.1     matt 		/*
    781        1.1     matt 		 * When descending, if we countered a mask node then that's
    782        1.1     matt 		 * we want to return.
    783        1.1     matt 		 */
    784        1.1     matt 		if (direction == PT_DESCENDING && !PT_NULL_P(mask_node)) {
    785        1.1     matt 			KASSERT(PT_NULL_P(next_node));
    786        1.1     matt 			return NODETOITEM(pt, PT_NODE(mask_node));
    787        1.1     matt 		}
    788        1.1     matt #endif /* !PTNOMASK */
    789        1.1     matt 	}
    790        1.1     matt 
    791        1.1     matt 	node = next_node;
    792        1.1     matt 	if (PT_NULL_P(node))
    793        1.1     matt 		return NULL;
    794        1.1     matt 
    795        1.1     matt 	while (!PT_LEAF_P(node)) {
    796        1.1     matt 		pt_node_t * const ptn = PT_NODE(node);
    797        1.1     matt 		pt_slot_t slot;
    798        1.1     matt 		if (direction == PT_ASCENDING) {
    799        1.1     matt #ifndef PTNOMASK
    800        1.1     matt 			if (PT_BRANCH_P(node)
    801        1.1     matt 			    && PTN_ISMASK_P(ptn)
    802        1.1     matt 			    && PTN_BRANCH_BITLEN(ptn) == 0)
    803        1.1     matt 				return NODETOITEM(pt, ptn);
    804        1.1     matt #endif /* !PTNOMASK */
    805        1.1     matt 			slot = PT_SLOT_LEFT;
    806        1.1     matt 		} else {
    807        1.1     matt 			slot = (1 << PTN_BRANCH_BITLEN(ptn)) - 1;
    808        1.1     matt 		}
    809        1.1     matt 		node = PTN_BRANCH_SLOT(ptn, slot);
    810        1.1     matt 	}
    811        1.1     matt 	return NODETOITEM(pt, PT_NODE(node));
    812        1.1     matt }
    813        1.1     matt 
    814        1.1     matt void
    815        1.1     matt ptree_remove_node(pt_tree_t *pt, void *item)
    816        1.1     matt {
    817        1.1     matt 	pt_node_t * const target = ITEMTONODE(pt, item);
    818        1.1     matt 	const pt_slot_t leaf_slot = PTN_LEAF_POSITION(target);
    819        1.1     matt 	const pt_slot_t branch_slot = PTN_BRANCH_POSITION(target);
    820        1.1     matt 	pt_node_t *ptn, *parent;
    821        1.1     matt 	uintptr_t node;
    822        1.1     matt 	uintptr_t *removep;
    823        1.1     matt 	uintptr_t *nodep;
    824        1.1     matt 	pt_bitoff_t bitoff;
    825        1.1     matt 	pt_slot_t parent_slot;
    826        1.1     matt #ifndef PTNOMASK
    827        1.1     matt 	bool at_mask;
    828        1.1     matt #endif
    829        1.1     matt 
    830        1.1     matt 	if (PT_NULL_P(PTN_BRANCH_ROOT_SLOT(&pt->pt_rootnode))) {
    831        1.1     matt 		KASSERT(!PT_NULL_P(PTN_BRANCH_ROOT_SLOT(&pt->pt_rootnode)));
    832        1.1     matt 		return;
    833        1.1     matt 	}
    834        1.1     matt 
    835        1.1     matt 	bitoff = 0;
    836        1.1     matt 	removep = NULL;
    837        1.1     matt 	nodep = NULL;
    838        1.1     matt 	parent = &pt->pt_rootnode;
    839        1.1     matt 	parent_slot = PT_SLOT_ROOT;
    840        1.1     matt 	for (;;) {
    841        1.1     matt 		node = PTN_BRANCH_SLOT(parent, parent_slot);
    842        1.1     matt 		ptn = PT_NODE(node);
    843        1.1     matt #ifndef PTNOMASK
    844        1.1     matt 		at_mask = PTN_ISMASK_P(ptn);
    845        1.1     matt #endif
    846        1.1     matt 
    847        1.1     matt 		if (PT_LEAF_P(node))
    848        1.1     matt 			break;
    849        1.1     matt 
    850        1.1     matt 		/*
    851        1.1     matt 		 * If we are at the target, then we are looking at its branch
    852        1.1     matt 		 * identity.  We need to remember who's pointing at it so we
    853        1.1     matt 		 * stop them from doing that.
    854        1.1     matt 		 */
    855        1.1     matt 		if (__predict_false(ptn == target)) {
    856        1.1     matt 			KASSERT(nodep == NULL);
    857        1.1     matt #ifndef PTNOMASK
    858        1.1     matt 			/*
    859        1.1     matt 			 * Interior mask nodes are trivial to get rid of.
    860        1.1     matt 			 */
    861        1.1     matt 			if (at_mask && PTN_BRANCH_BITLEN(ptn) == 0) {
    862        1.1     matt 				PTN_BRANCH_SLOT(parent, parent_slot) =
    863        1.1     matt 				    PTN_BRANCH_ROOT_SLOT(ptn);
    864        1.1     matt 				KASSERT(PT_NULL_P(PTN_BRANCH_ODDMAN_SLOT(ptn)));
    865        1.1     matt 				PTREE_CHECK(pt);
    866        1.1     matt 				return;
    867        1.1     matt 			}
    868        1.1     matt #endif /* !PTNOMASK */
    869        1.1     matt 			nodep = &PTN_BRANCH_SLOT(parent, parent_slot);
    870        1.1     matt 			KASSERT(*nodep == PTN_BRANCH(target));
    871        1.1     matt 		}
    872        1.1     matt 		/*
    873        1.1     matt 		 * We need also need to know who's pointing at our parent.
    874        1.1     matt 		 * After we remove ourselves from our parent, he'll only
    875        1.1     matt 		 * have one child and that's unacceptable.  So we replace
    876        1.1     matt 		 * the pointer to the parent with our abadoned sibling.
    877        1.1     matt 		 */
    878        1.1     matt 		removep = &PTN_BRANCH_SLOT(parent, parent_slot);
    879        1.1     matt 
    880        1.1     matt 		/*
    881        1.1     matt 		 * Descend into the tree.
    882        1.1     matt 		 */
    883        1.1     matt 		parent = ptn;
    884        1.1     matt 		parent_slot = ptree_testnode(pt, target, parent);
    885        1.1     matt 		bitoff += PTN_BRANCH_BITLEN(parent);
    886        1.1     matt 	}
    887        1.1     matt 
    888        1.1     matt 	/*
    889        1.1     matt 	 * We better have found that the leaf we are looking for is target.
    890        1.1     matt 	 */
    891        1.1     matt 	if (target != ptn) {
    892        1.1     matt 		KASSERT(target == ptn);
    893        1.1     matt 		return;
    894        1.1     matt 	}
    895        1.1     matt 
    896        1.1     matt 	/*
    897        1.1     matt 	 * If we didn't encounter target as branch, then target must be the
    898        1.1     matt 	 * oddman-out.
    899        1.1     matt 	 */
    900        1.1     matt 	if (nodep == NULL) {
    901        1.1     matt 		KASSERT(PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode) == PTN_LEAF(target));
    902        1.1     matt 		KASSERT(nodep == NULL);
    903        1.1     matt 		nodep = &PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode);
    904        1.1     matt 	}
    905        1.1     matt 
    906        1.1     matt 	KASSERT((removep == NULL) == (parent == &pt->pt_rootnode));
    907        1.1     matt 
    908        1.1     matt 	/*
    909        1.1     matt 	 * We have to special remove the last leaf from the root since
    910        1.1     matt 	 * the only time the tree can a PT_NULL node is when it's empty.
    911        1.1     matt 	 */
    912        1.1     matt 	if (__predict_false(PTN_ISROOT_P(pt, parent))) {
    913        1.1     matt 		KASSERT(removep == NULL);
    914        1.1     matt 		KASSERT(parent == &pt->pt_rootnode);
    915        1.1     matt 		KASSERT(nodep == &PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode));
    916        1.1     matt 		KASSERT(*nodep == PTN_LEAF(target));
    917        1.1     matt 		PTN_BRANCH_ROOT_SLOT(&pt->pt_rootnode) = PT_NULL;
    918        1.1     matt 		PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode) = PT_NULL;
    919        1.1     matt 		return;
    920        1.1     matt 	}
    921        1.1     matt 
    922        1.1     matt 	KASSERT((parent == target) == (removep == nodep));
    923        1.1     matt 	if (PTN_BRANCH(parent) == PTN_BRANCH_SLOT(target, PTN_BRANCH_POSITION(parent))) {
    924        1.1     matt 		/*
    925        1.1     matt 		 * The pointer to the parent actually lives in the target's
    926        1.1     matt 		 * branch identity.  We can't just move the target's branch
    927        1.1     matt 		 * identity since that would result in the parent pointing
    928        1.1     matt 		 * to its own branch identity and that's fobidden.
    929        1.1     matt 		 */
    930        1.1     matt 		const pt_slot_t slot = PTN_BRANCH_POSITION(parent);
    931        1.1     matt 		const pt_slot_t other_slot = slot ^ PT_SLOT_OTHER;
    932        1.1     matt 		const pt_bitlen_t parent_bitlen = PTN_BRANCH_BITLEN(parent);
    933        1.1     matt 
    934        1.1     matt 		KASSERT(PTN_BRANCH_BITOFF(target) < PTN_BRANCH_BITOFF(parent));
    935        1.1     matt 
    936        1.1     matt 		/*
    937        1.1     matt 		 * This gets so confusing.  The target's branch identity
    938        1.1     matt 		 * points to the branch identity of the parent of the target's
    939        1.1     matt 		 * leaf identity:
    940        1.1     matt 		 *
    941        1.1     matt 		 * 	TB = { X, PB = { TL, Y } }
    942        1.1     matt 		 *   or TB = { X, PB = { TL } }
    943        1.1     matt 		 *
    944        1.1     matt 		 * So we can't move the target's branch identity to the parent
    945        1.1     matt 		 * because that would corrupt the tree.
    946        1.1     matt 		 */
    947        1.1     matt 		if (__predict_true(parent_bitlen > 0)) {
    948        1.1     matt 			/*
    949        1.1     matt 			 * The parent is a two-way branch.  We have to have
    950        1.1     matt 			 * do to this chang in two steps to keep internally
    951        1.1     matt 			 * consistent.  First step is to copy our sibling from
    952        1.1     matt 			 * our parent to where we are pointing to parent's
    953        1.1     matt 			 * branch identiy.  This remove all references to his
    954        1.1     matt 			 * branch identity from the tree.  We then simply make
    955        1.1     matt 			 * the parent assume the target's branching duties.
    956        1.1     matt 			 *
    957        1.1     matt 			 *   TB = { X, PB = { Y, TL } } --> PB = { X, Y }.
    958        1.1     matt 			 *   TB = { X, PB = { TL, Y } } --> PB = { X, Y }.
    959        1.1     matt 			 *   TB = { PB = { Y, TL }, X } --> PB = { Y, X }.
    960        1.1     matt 			 *   TB = { PB = { TL, Y }, X } --> PB = { Y, X }.
    961        1.1     matt 			 */
    962        1.1     matt 			PTN_BRANCH_SLOT(target, slot) =
    963        1.1     matt 			    PTN_BRANCH_SLOT(parent, parent_slot ^ PT_SLOT_OTHER);
    964        1.1     matt 			*nodep = ptree_move_branch(pt, parent, target);
    965        1.1     matt 			PTREE_CHECK(pt);
    966        1.1     matt 			return;
    967        1.1     matt 		} else {
    968        1.1     matt 			/*
    969        1.1     matt 			 * If parent was a one-way branch, it must have been
    970        1.1     matt 			 * mask which pointed to a single leaf which we are
    971        1.1     matt 			 * removing.  This means we have to convert the
    972        1.1     matt 			 * parent back to a leaf node.  So in the same
    973        1.1     matt 			 * position that target pointed to parent, we place
    974        1.1     matt 			 * leaf pointer to parent.  In the other position,
    975        1.1     matt 			 * we just put the other node from target.
    976        1.1     matt 			 *
    977        1.1     matt 			 *   TB = { X, PB = { TL } } --> PB = { X, PL }
    978        1.1     matt 			 */
    979        1.1     matt 			KASSERT(PTN_ISMASK_P(parent));
    980        1.1     matt 			KASSERT(slot == ptree_testnode(pt, parent, target));
    981        1.1     matt 			PTN_BRANCH_SLOT(parent, slot) = PTN_LEAF(parent);
    982        1.1     matt 			PTN_BRANCH_SLOT(parent, other_slot) =
    983        1.1     matt 			   PTN_BRANCH_SLOT(target, other_slot);
    984        1.1     matt 			PTN_SET_LEAF_POSITION(parent,slot);
    985        1.1     matt 			PTN_SET_BRANCH_BITLEN(parent, 1);
    986        1.1     matt 		}
    987        1.1     matt 		PTN_SET_BRANCH_BITOFF(parent, PTN_BRANCH_BITOFF(target));
    988        1.1     matt 		PTN_SET_BRANCH_POSITION(parent, PTN_BRANCH_POSITION(target));
    989        1.1     matt 
    990        1.1     matt 		*nodep = PTN_BRANCH(parent);
    991        1.1     matt 		PTREE_CHECK(pt);
    992        1.1     matt 		return;
    993        1.1     matt 	}
    994        1.1     matt 
    995        1.1     matt #ifndef PTNOMASK
    996        1.1     matt 	if (__predict_false(PTN_BRANCH_BITLEN(parent) == 0)) {
    997        1.1     matt 		/*
    998        1.1     matt 		 * Parent was a one-way branch which is changing back to a leaf.
    999        1.1     matt 		 * Since parent is no longer a one-way branch, it can take over
   1000        1.1     matt 		 * target's branching duties.
   1001        1.1     matt 		 *
   1002        1.1     matt 		 *  GB = { PB = { TL } }	--> GB = { PL }
   1003        1.1     matt 		 *  TB = { X, Y }		--> PB = { X, Y }
   1004        1.1     matt 		 */
   1005        1.1     matt 		KASSERT(PTN_ISMASK_P(parent));
   1006        1.1     matt 		KASSERT(parent != target);
   1007        1.1     matt 		*removep = PTN_LEAF(parent);
   1008        1.1     matt 	} else
   1009        1.1     matt #endif /* !PTNOMASK */
   1010        1.1     matt 	{
   1011        1.1     matt 		/*
   1012        1.1     matt 		 * Now we are the normal removal case.  Since after the
   1013        1.1     matt 		 * target's leaf identity is removed from the its parent,
   1014        1.1     matt 		 * that parent will only have one decendent.  So we can
   1015        1.1     matt 		 * just as easily replace the node that has the parent's
   1016        1.1     matt 		 * branch identity with the surviving node.  This freeing
   1017        1.1     matt 		 * parent from its branching duties which means it can
   1018        1.1     matt 		 * take over target's branching duties.
   1019        1.1     matt 		 *
   1020        1.1     matt 		 *  GB = { PB = { X, TL } }	--> GB = { X }
   1021        1.1     matt 		 *  TB = { V, W }		--> PB = { V, W }
   1022        1.1     matt 		 */
   1023        1.1     matt 		const pt_slot_t other_slot = parent_slot ^ PT_SLOT_OTHER;
   1024        1.1     matt 		uintptr_t other_node = PTN_BRANCH_SLOT(parent, other_slot);
   1025        1.1     matt 		const pt_slot_t target_slot = (parent == target ? branch_slot : leaf_slot);
   1026        1.1     matt 
   1027        1.1     matt 		*removep = other_node;
   1028        1.1     matt 
   1029        1.1     matt 		ptree_set_position(other_node, target_slot);
   1030        1.1     matt 
   1031        1.1     matt 		/*
   1032        1.1     matt 		 * If target's branch identity contained its leaf identity, we
   1033        1.1     matt 		 * have nothing left to do.  We've already moved 'X' so there
   1034        1.1     matt 		 * is no longer anything in the target's branch identiy that
   1035        1.1     matt 		 * has to be preserved.
   1036        1.1     matt 		 */
   1037        1.1     matt 		if (parent == target) {
   1038        1.1     matt 			/*
   1039        1.1     matt 			 *  GB = { TB = { X, TL } }	--> GB = { X }
   1040        1.1     matt 			 *  TB = { X, TL }		--> don't care
   1041        1.1     matt 			 */
   1042        1.1     matt 			PTREE_CHECK(pt);
   1043        1.1     matt 			return;
   1044        1.1     matt 		}
   1045        1.1     matt 	}
   1046        1.1     matt 
   1047        1.1     matt 	/*
   1048        1.1     matt 	 * If target wasn't used as a branch, then it must have been the
   1049        1.1     matt 	 * oddman-out of the tree (the one node that doesn't have a branch
   1050        1.1     matt 	 * identity).  This makes parent the new oddman-out.
   1051        1.1     matt 	 */
   1052        1.1     matt 	if (*nodep == PTN_LEAF(target)) {
   1053        1.1     matt 		KASSERT(nodep == &PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode));
   1054        1.1     matt 		PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode) = PTN_LEAF(parent);
   1055        1.1     matt 		PTREE_CHECK(pt);
   1056        1.1     matt 		return;
   1057        1.1     matt 	}
   1058        1.1     matt 
   1059        1.1     matt 	/*
   1060        1.1     matt 	 * Finally move the target's branching duties to the parent.
   1061        1.1     matt 	 */
   1062        1.1     matt 	KASSERT(PTN_BRANCH_BITOFF(parent) > PTN_BRANCH_BITOFF(target));
   1063        1.1     matt 	*nodep = ptree_move_branch(pt, parent, target);
   1064        1.1     matt 	PTREE_CHECK(pt);
   1065        1.1     matt }
   1066        1.1     matt 
   1067        1.1     matt #ifdef PTCHECK
   1068        1.1     matt static const pt_node_t *
   1069        1.1     matt ptree_check_find_node2(const pt_tree_t *pt, const pt_node_t *parent,
   1070        1.1     matt 	uintptr_t target)
   1071        1.1     matt {
   1072        1.1     matt 	const pt_bitlen_t slots = 1 << PTN_BRANCH_BITLEN(parent);
   1073        1.1     matt 	pt_slot_t slot;
   1074        1.1     matt 
   1075        1.1     matt 	for (slot = 0; slot < slots; slot++) {
   1076        1.1     matt 		const uintptr_t node = PTN_BRANCH_SLOT(parent, slot);
   1077        1.1     matt 		if (PTN_BRANCH_SLOT(parent, slot) == node)
   1078        1.1     matt 			return parent;
   1079        1.1     matt 	}
   1080        1.1     matt 	for (slot = 0; slot < slots; slot++) {
   1081        1.1     matt 		const uintptr_t node = PTN_BRANCH_SLOT(parent, slot);
   1082        1.1     matt 		const pt_node_t *branch;
   1083        1.1     matt 		if (!PT_BRANCH_P(node))
   1084        1.1     matt 			continue;
   1085        1.1     matt 		branch = ptree_check_find_node2(pt, PT_NODE(node), target);
   1086        1.1     matt 		if (branch != NULL)
   1087        1.1     matt 			return branch;
   1088        1.1     matt 	}
   1089        1.1     matt 
   1090        1.1     matt 	return NULL;
   1091        1.1     matt }
   1092        1.1     matt 
   1093        1.1     matt static bool
   1094        1.1     matt ptree_check_leaf(const pt_tree_t *pt, const pt_node_t *parent,
   1095        1.1     matt 	const pt_node_t *ptn)
   1096        1.1     matt {
   1097        1.1     matt 	const pt_bitoff_t leaf_position = PTN_LEAF_POSITION(ptn);
   1098        1.1     matt 	const pt_bitlen_t bitlen = PTN_BRANCH_BITLEN(ptn);
   1099        1.1     matt 	const pt_bitlen_t mask_len = PTN_MASK_BITLEN(ptn);
   1100        1.1     matt 	const uintptr_t leaf_node = PTN_LEAF(ptn);
   1101        1.1     matt 	const bool is_parent_root = (parent == &pt->pt_rootnode);
   1102        1.1     matt 	const bool is_mask = PTN_ISMASK_P(ptn);
   1103        1.1     matt 	bool ok = true;
   1104        1.1     matt 
   1105        1.1     matt 	if (is_parent_root) {
   1106        1.1     matt 		ok = ok && PTN_BRANCH_ODDMAN_SLOT(parent) == leaf_node;
   1107        1.1     matt 		KASSERT(ok);
   1108        1.1     matt 		return ok;
   1109        1.1     matt 	}
   1110        1.1     matt 
   1111        1.1     matt 	if (is_mask && PTN_ISMASK_P(parent) && PTN_BRANCH_BITLEN(parent) == 0) {
   1112        1.1     matt 		ok = ok && PTN_MASK_BITLEN(parent) < mask_len;
   1113        1.1     matt 		KASSERT(ok);
   1114        1.1     matt 		ok = ok && PTN_BRANCH_BITOFF(parent) < mask_len;
   1115        1.1     matt 		KASSERT(ok);
   1116        1.1     matt 	}
   1117        1.1     matt 	ok = ok && PTN_BRANCH_SLOT(parent, leaf_position) == leaf_node;
   1118        1.1     matt 	KASSERT(ok);
   1119        1.1     matt 	ok = ok && leaf_position == ptree_testnode(pt, ptn, parent);
   1120        1.1     matt 	KASSERT(ok);
   1121        1.1     matt 	if (PTN_BRANCH_ODDMAN_SLOT(&pt->pt_rootnode) != leaf_node) {
   1122        1.1     matt 		ok = ok && bitlen > 0;
   1123        1.1     matt 		KASSERT(ok);
   1124        1.1     matt 		ok = ok && ptn == ptree_check_find_node2(pt, ptn, PTN_LEAF(ptn));
   1125        1.1     matt 		KASSERT(ok);
   1126        1.1     matt 	}
   1127        1.1     matt 	return ok;
   1128        1.1     matt }
   1129        1.1     matt 
   1130        1.1     matt static bool
   1131        1.1     matt ptree_check_branch(const pt_tree_t *pt, const pt_node_t *parent,
   1132        1.1     matt 	const pt_node_t *ptn)
   1133        1.1     matt {
   1134        1.1     matt 	const bool is_parent_root = (parent == &pt->pt_rootnode);
   1135        1.1     matt 	const pt_slot_t branch_slot = PTN_BRANCH_POSITION(ptn);
   1136        1.1     matt 	const pt_bitoff_t bitoff = PTN_BRANCH_BITOFF(ptn);
   1137        1.1     matt 	const pt_bitoff_t bitlen = PTN_BRANCH_BITLEN(ptn);
   1138        1.1     matt 	const pt_bitoff_t parent_bitoff = PTN_BRANCH_BITOFF(parent);
   1139        1.1     matt 	const pt_bitoff_t parent_bitlen = PTN_BRANCH_BITLEN(parent);
   1140        1.1     matt 	const bool is_parent_mask = PTN_ISMASK_P(parent) && parent_bitlen == 0;
   1141        1.1     matt 	const bool is_mask = PTN_ISMASK_P(ptn) && bitlen == 0;
   1142        1.1     matt 	const pt_bitoff_t parent_mask_len = PTN_MASK_BITLEN(parent);
   1143        1.1     matt 	const pt_bitoff_t mask_len = PTN_MASK_BITLEN(ptn);
   1144        1.1     matt 	const pt_bitlen_t slots = 1 << bitlen;
   1145        1.1     matt 	pt_slot_t slot;
   1146        1.1     matt 	bool ok = true;
   1147        1.1     matt 
   1148        1.1     matt 	ok = ok && PTN_BRANCH_SLOT(parent, branch_slot) == PTN_BRANCH(ptn);
   1149        1.1     matt 	KASSERT(ok);
   1150        1.1     matt 	ok = ok && branch_slot == ptree_testnode(pt, ptn, parent);
   1151        1.1     matt 	KASSERT(ok);
   1152        1.1     matt 
   1153        1.1     matt 	if (is_mask) {
   1154        1.1     matt 		ok = ok && bitoff == mask_len;
   1155        1.1     matt 		KASSERT(ok);
   1156        1.1     matt 		if (is_parent_mask) {
   1157        1.1     matt 			ok = ok && parent_mask_len < mask_len;
   1158        1.1     matt 			KASSERT(ok);
   1159        1.1     matt 			ok = ok && parent_bitoff < bitoff;
   1160        1.1     matt 			KASSERT(ok);
   1161        1.1     matt 		}
   1162        1.1     matt 	} else {
   1163        1.1     matt 		if (is_parent_mask) {
   1164        1.1     matt 			ok = ok && parent_bitoff <= bitoff;
   1165        1.1     matt 		} else if (!is_parent_root) {
   1166        1.1     matt 			ok = ok && parent_bitoff < bitoff;
   1167        1.1     matt 		}
   1168        1.1     matt 		KASSERT(ok);
   1169        1.1     matt 	}
   1170        1.1     matt 
   1171        1.1     matt 	for (slot = 0; slot < slots; slot++) {
   1172        1.1     matt 		const uintptr_t node = PTN_BRANCH_SLOT(ptn, slot);
   1173        1.1     matt 		pt_bitoff_t tmp_bitoff = 0;
   1174        1.1     matt 		pt_slot_t tmp_slot;
   1175        1.1     matt 		ok = ok && node != PTN_BRANCH(ptn);
   1176        1.1     matt 		KASSERT(ok);
   1177        1.1     matt 		if (bitlen > 0) {
   1178        1.1     matt 			ok = ok && ptree_matchnode(pt, PT_NODE(node), ptn, bitoff, &tmp_bitoff, &tmp_slot);
   1179        1.1     matt 			KASSERT(ok);
   1180        1.1     matt 			tmp_slot = ptree_testnode(pt, PT_NODE(node), ptn);
   1181        1.1     matt 			ok = ok && slot == tmp_slot;
   1182        1.1     matt 			KASSERT(ok);
   1183        1.1     matt 		}
   1184        1.1     matt 		if (PT_LEAF_P(node))
   1185        1.1     matt 			ok = ok && ptree_check_leaf(pt, ptn, PT_NODE(node));
   1186        1.1     matt 		else
   1187        1.1     matt 			ok = ok && ptree_check_branch(pt, ptn, PT_NODE(node));
   1188        1.1     matt 	}
   1189        1.1     matt 
   1190        1.1     matt 	return ok;
   1191        1.1     matt }
   1192        1.1     matt #endif /* PTCHECK */
   1193        1.1     matt 
   1194        1.2     matt /*ARGSUSED*/
   1195        1.1     matt bool
   1196        1.1     matt ptree_check(const pt_tree_t *pt)
   1197        1.1     matt {
   1198        1.1     matt 	bool ok = true;
   1199        1.1     matt #ifdef PTCHECK
   1200        1.1     matt 	const pt_node_t * const parent = &pt->pt_rootnode;
   1201        1.1     matt 	const uintptr_t node = pt->pt_root;
   1202        1.1     matt 	const pt_node_t * const ptn = PT_NODE(node);
   1203        1.1     matt 
   1204        1.1     matt 	ok = ok && PTN_BRANCH_BITOFF(parent) == 0;
   1205        1.1     matt 	ok = ok && !PTN_ISMASK_P(parent);
   1206        1.1     matt 
   1207        1.1     matt 	if (PT_NULL_P(node))
   1208        1.1     matt 		return ok;
   1209        1.1     matt 
   1210        1.1     matt 	if (PT_LEAF_P(node))
   1211        1.1     matt 		ok = ok && ptree_check_leaf(pt, parent, ptn);
   1212        1.1     matt 	else
   1213        1.1     matt 		ok = ok && ptree_check_branch(pt, parent, ptn);
   1214        1.1     matt #endif
   1215        1.1     matt 	return ok;
   1216        1.1     matt }
   1217       1.10     matt 
   1218       1.10     matt bool
   1219       1.10     matt ptree_mask_node_p(pt_tree_t *pt, const void *item, pt_bitlen_t *lenp)
   1220       1.10     matt {
   1221       1.10     matt 	const pt_node_t * const mask = ITEMTONODE(pt, item);
   1222       1.10     matt 
   1223       1.10     matt 	if (!PTN_ISMASK_P(mask))
   1224       1.10     matt 		return false;
   1225       1.10     matt 
   1226       1.10     matt 	if (lenp != NULL)
   1227       1.10     matt 		*lenp = PTN_MASK_BITLEN(mask);
   1228       1.10     matt 
   1229       1.10     matt 	return true;
   1230       1.10     matt }
   1231