The branch main has been updated by dougm:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=44d6f4b314ad39502d21854b6d1db8fee4ffeafe

commit 44d6f4b314ad39502d21854b6d1db8fee4ffeafe
Author:     Doug Moore <do...@freebsd.org>
AuthorDate: 2025-06-26 06:27:21 +0000
Commit:     Doug Moore <do...@freebsd.org>
CommitDate: 2025-06-26 06:27:21 +0000

    pctrie: use one lookup function
    
    Several of the functions that implement pctries have their own loops
    for walking down the trie searching for an exact match. Change them
    all to use _pctrie_lookup_node for that.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D50839
---
 sys/kern/subr_pctrie.c | 400 ++++++++++++++++++++-----------------------------
 1 file changed, 163 insertions(+), 237 deletions(-)

diff --git a/sys/kern/subr_pctrie.c b/sys/kern/subr_pctrie.c
index e8098c6052e3..194e96ced471 100644
--- a/sys/kern/subr_pctrie.c
+++ b/sys/kern/subr_pctrie.c
@@ -267,6 +267,111 @@ pctrie_node_size(void)
        return (sizeof(struct pctrie_node));
 }
 
+/*
+ * Return the value associated with the node, if the node is a leaf that 
matches
+ * the index; otherwise NULL.
+ */
+static __always_inline uint64_t *
+pctrie_match_value(struct pctrie_node *node, uint64_t index)
+{
+       uint64_t *m;
+
+       if (!pctrie_isleaf(node) || (m = pctrie_toval(node)) == NULL ||
+           *m != index)
+               m = NULL;
+       return (m);
+}
+
+/*
+ * Returns the last node examined in the search for the index, and sets the
+ * parent of that node.
+ */
+static __always_inline struct pctrie_node *
+_pctrie_lookup_node(struct pctrie *ptree, struct pctrie_node *node,
+    uint64_t index, struct pctrie_node **parent_out,
+    smr_t smr, enum pctrie_access access)
+{
+       struct pctrie_node *parent;
+       int slot;
+
+       parent = node;
+       if (parent == NULL)
+               node = pctrie_root_load(ptree, smr, access);
+
+       /*
+        * Climb the search path to find the lowest node from which to start the
+        * search for a value matching 'index'.
+        */
+       while (parent != NULL) {
+               KASSERT(access == PCTRIE_SMR || !powerof2(parent->pn_popmap),
+                   ("%s: freed node in iter path", __func__));
+               node = parent;
+               if (!pctrie_keybarr(node, index, &slot))
+                       break;
+               parent = pctrie_parent(node);
+       }
+
+       /* Seek a node that matches index. */
+       while (!pctrie_isleaf(node) && !pctrie_keybarr(node, index, &slot)) {
+               parent = node;
+               KASSERT(access == PCTRIE_SMR || !powerof2(parent->pn_popmap),
+                   ("%s: freed node in iter path", __func__));
+               node = pctrie_node_load(&node->pn_child[slot], smr, access);
+       }
+       *parent_out = parent;
+       return (node);
+}
+
+/*
+ * Returns the value stored at the index, assuming access is externally
+ * synchronized by a lock.
+ *
+ * If the index is not present, NULL is returned.
+ */
+uint64_t *
+pctrie_lookup(struct pctrie *ptree, uint64_t index)
+{
+       struct pctrie_node *node, *parent;
+
+       node = _pctrie_lookup_node(ptree, NULL, index, &parent, NULL,
+           PCTRIE_LOCKED);
+       return (pctrie_match_value(node, index));
+}
+
+/*
+ * Returns the value stored at the index without requiring an external lock.
+ *
+ * If the index is not present, NULL is returned.
+ */
+uint64_t *
+pctrie_lookup_unlocked(struct pctrie *ptree, uint64_t index, smr_t smr)
+{
+       struct pctrie_node *node, *parent;
+       uint64_t *res;
+
+       smr_enter(smr);
+       node = _pctrie_lookup_node(ptree, NULL, index, &parent, smr,
+           PCTRIE_SMR);
+       res = pctrie_match_value(node, index);
+       smr_exit(smr);
+       return (res);
+}
+
+/*
+ * Returns the value stored at a given index value, possibly NULL, assuming
+ * access is externally synchronized by a lock.
+ */
+uint64_t *
+pctrie_iter_lookup(struct pctrie_iter *it, uint64_t index)
+{
+       struct pctrie_node *node;
+
+       node = _pctrie_lookup_node(it->ptree, it->node, index, &it->node,
+           NULL, PCTRIE_LOCKED);
+       it->index = index;
+       return (pctrie_match_value(node, index));
+}
+
 /*
  * Look for where to insert the key-value pair into the trie.  Complete the
  * insertion if it replaces a null leaf.  Return the insertion location if the
@@ -276,45 +381,26 @@ pctrie_node_size(void)
  * pctrie_lookup().
  */
 static __always_inline void *
-pctrie_insert_lookup_compound(struct pctrie *ptree, uint64_t *val,
-    struct pctrie_node **parent_out, uint64_t **found_out)
+_pctrie_insert_lookup(struct pctrie *ptree, struct pctrie_node *parent,
+    uint64_t *val, struct pctrie_node **parent_out, uint64_t **found_out)
 {
-       uint64_t index;
-       struct pctrie_node *node, *parent;
-       int slot;
-
-       index = *val;
+       struct pctrie_node *node;
 
-       /*
-        * The owner of record for root is not really important because it
-        * will never be used.
-        */
-       node = pctrie_root_load(ptree, NULL, PCTRIE_LOCKED);
-       parent = NULL;
-       for (;;) {
-               if (pctrie_isleaf(node)) {
-                       if (node == PCTRIE_NULL) {
-                               if (parent == NULL)
-                                       pctrie_node_store(pctrie_root(ptree),
-                                           pctrie_toleaf(val), PCTRIE_LOCKED);
-                               else
-                                       pctrie_addnode(parent, index,
-                                           pctrie_toleaf(val), PCTRIE_LOCKED);
-                               *parent_out = parent;
-                               return (NULL);
-                       }
-                       if (*pctrie_toval(node) == index) {
-                               *found_out = pctrie_toval(node);
-                               *parent_out = parent;
-                               return (NULL);
-                       }
-                       break;
-               }
-               if (pctrie_keybarr(node, index, &slot))
-                       break;
-               parent = node;
-               node = pctrie_node_load(&node->pn_child[slot], NULL,
-                   PCTRIE_LOCKED);
+       node = _pctrie_lookup_node(ptree, parent, *val, parent_out, NULL,
+           PCTRIE_LOCKED);
+       *found_out = NULL;
+       if (node == PCTRIE_NULL) {
+               if (*parent_out == NULL)
+                       pctrie_node_store(pctrie_root(ptree),
+                           pctrie_toleaf(val), PCTRIE_LOCKED);
+               else
+                       pctrie_addnode(*parent_out, *val,
+                           pctrie_toleaf(val), PCTRIE_LOCKED);
+               return (NULL);
+       }
+       if (__predict_false(pctrie_match_value(node, *val) != NULL)) {
+               *found_out = pctrie_toval(node);
+               return (NULL);
        }
 
        /*
@@ -322,12 +408,11 @@ pctrie_insert_lookup_compound(struct pctrie *ptree, 
uint64_t *val,
         * children 'node' and 'val'. Return the place that points to 'node'
         * now, and will point to to the new branching node later.
         */
-       *parent_out = parent;
-       return ((parent == NULL) ? pctrie_root(ptree): &parent->pn_child[slot]);
+       return (pctrie_child(ptree, *parent_out, *val));
 }
 
 /*
- * Wrap pctrie_insert_lookup_compound to implement a strict insertion.  Panic
+ * Wrap _pctrie_insert_lookup to implement a strict insertion.  Panic
  * if the key already exists, and do not look for neighboring entries.
  */
 void *
@@ -337,9 +422,7 @@ pctrie_insert_lookup_strict(struct pctrie *ptree, uint64_t 
*val,
        void *parentp;
        uint64_t *found;
 
-       found = NULL;
-       parentp = pctrie_insert_lookup_compound(ptree, val, parent_out,
-           &found);
+       parentp = _pctrie_insert_lookup(ptree, NULL, val, parent_out, &found);
        if (__predict_false(found != NULL))
                panic("%s: key %jx is already present", __func__,
                    (uintmax_t)*val);
@@ -347,16 +430,34 @@ pctrie_insert_lookup_strict(struct pctrie *ptree, 
uint64_t *val,
 }
 
 /*
- * Wrap pctrie_insert_lookup_compound to implement find-or-insert.  Do not look
+ * Wrap _pctrie_insert_lookup to implement find-or-insert.  Do not look
  * for neighboring entries.
  */
 void *
 pctrie_insert_lookup(struct pctrie *ptree, uint64_t *val,
     struct pctrie_node **parent_out, uint64_t **found_out)
 {
-       *found_out = NULL;
-       return (pctrie_insert_lookup_compound(ptree, val, parent_out,
-           found_out));
+       return (_pctrie_insert_lookup(ptree, NULL, val, parent_out, found_out));
+}
+
+/*
+ * Insert the val in the trie, starting search with iterator.  Return a pointer
+ * to indicate where a new node must be allocated to complete insertion.
+ * Assumes access is externally synchronized by a lock.
+ */
+void *
+pctrie_iter_insert_lookup(struct pctrie_iter *it, uint64_t *val)
+{
+       void *res;
+       uint64_t *found;
+
+       it->index = *val;
+       res = _pctrie_insert_lookup(it->ptree, it->node, val, &it->node,
+           &found);
+       if (__predict_false(found != NULL))
+               panic("%s: key %jx is already present", __func__,
+                   (uintmax_t)it->index);
+       return (res);
 }
 
 /*
@@ -416,156 +517,6 @@ pctrie_insert_node(uint64_t *val, struct pctrie_node 
*parent, void *parentp,
        pctrie_node_store(parentp, child, PCTRIE_LOCKED);
 }
 
-/*
- * Return the value associated with the node, if the node is a leaf that 
matches
- * the index; otherwise NULL.
- */
-static __always_inline uint64_t *
-pctrie_match_value(struct pctrie_node *node, uint64_t index)
-{
-       uint64_t *m;
-
-       if (!pctrie_isleaf(node) || (m = pctrie_toval(node)) == NULL ||
-           *m != index)
-               m = NULL;
-       return (m);
-}
-
-/*
- * Returns the value stored at the index.  If the index is not present,
- * NULL is returned.
- */
-static __always_inline uint64_t *
-_pctrie_lookup(struct pctrie *ptree, uint64_t index, smr_t smr,
-    enum pctrie_access access)
-{
-       struct pctrie_node *node;
-       int slot;
-
-       node = pctrie_root_load(ptree, smr, access);
-       /* Seek a node that matches index. */
-       while (!pctrie_isleaf(node) && !pctrie_keybarr(node, index, &slot))
-               node = pctrie_node_load(&node->pn_child[slot], smr, access);
-       return (pctrie_match_value(node, index));
-}
-
-/*
- * Returns the value stored at the index, assuming access is externally
- * synchronized by a lock.
- *
- * If the index is not present, NULL is returned.
- */
-uint64_t *
-pctrie_lookup(struct pctrie *ptree, uint64_t index)
-{
-       return (_pctrie_lookup(ptree, index, NULL, PCTRIE_LOCKED));
-}
-
-/*
- * Returns the value stored at the index without requiring an external lock.
- *
- * If the index is not present, NULL is returned.
- */
-uint64_t *
-pctrie_lookup_unlocked(struct pctrie *ptree, uint64_t index, smr_t smr)
-{
-       uint64_t *res;
-
-       smr_enter(smr);
-       res = _pctrie_lookup(ptree, index, smr, PCTRIE_SMR);
-       smr_exit(smr);
-       return (res);
-}
-
-/*
- * Returns the last node examined in the search for the index, and sets the
- * parent of that node.
- */
-static __always_inline struct pctrie_node *
-_pctrie_lookup_node(struct pctrie *ptree, struct pctrie_node *node,
-    uint64_t index, struct pctrie_node **parent_out,
-    smr_t smr, enum pctrie_access access)
-{
-       struct pctrie_node *parent;
-       int slot;
-
-       parent = node;
-       if (parent == NULL)
-               node = pctrie_root_load(ptree, smr, access);
-
-       /*
-        * Climb the search path to find the lowest node from which to start the
-        * search for a value matching 'index'.
-        */
-       while (parent != NULL) {
-               KASSERT(access == PCTRIE_SMR || !powerof2(parent->pn_popmap),
-                   ("%s: freed node in iter path", __func__));
-               node = parent;
-               if (!pctrie_keybarr(node, index, &slot))
-                       break;
-               parent = pctrie_parent(node);
-       }
-
-       /* Seek a node that matches index. */
-       while (!pctrie_isleaf(node) && !pctrie_keybarr(node, index, &slot)) {
-               parent = node;
-               KASSERT(access == PCTRIE_SMR || !powerof2(parent->pn_popmap),
-                   ("%s: freed node in iter path", __func__));
-               node = pctrie_node_load(&node->pn_child[slot], smr, access);
-       }
-       *parent_out = parent;
-       return (node);
-}
-
-/*
- * Returns the value stored at a given index value, possibly NULL, assuming
- * access is externally synchronized by a lock.
- */
-uint64_t *
-pctrie_iter_lookup(struct pctrie_iter *it, uint64_t index)
-{
-       struct pctrie_node *node;
-
-       node = _pctrie_lookup_node(it->ptree, it->node, index, &it->node,
-           NULL, PCTRIE_LOCKED);
-       it->index = index;
-       return (pctrie_match_value(node, index));
-}
-
-/*
- * Insert the val in the trie, starting search with iterator.  Return a pointer
- * to indicate where a new node must be allocated to complete insertion.
- * Assumes access is externally synchronized by a lock.
- */
-void *
-pctrie_iter_insert_lookup(struct pctrie_iter *it, uint64_t *val)
-{
-       struct pctrie_node *node;
-
-       node = _pctrie_lookup_node(it->ptree, it->node, *val, &it->node,
-           NULL, PCTRIE_LOCKED);
-       it->index = *val;
-       if (node == PCTRIE_NULL) {
-               if (it->node == NULL)
-                       pctrie_node_store(pctrie_root(it->ptree),
-                           pctrie_toleaf(val), PCTRIE_LOCKED);
-               else
-                       pctrie_addnode(it->node, it->index,
-                           pctrie_toleaf(val), PCTRIE_LOCKED);
-               return (NULL);
-       }
-       if (__predict_false(pctrie_match_value(node, it->index) != NULL))
-               panic("%s: key %jx is already present", __func__,
-                   (uintmax_t)it->index);
-
-       /*
-        * 'node' must be replaced in the tree with a new branch node, with
-        * children 'node' and 'val'. Return the place that points to 'node'
-        * now, and will point to to the new branching node later.
-        */
-       return (pctrie_child(it->ptree, it->node, it->index));
-}
-
 /*
  * Returns the value stored at a fixed offset from the current index value,
  * possibly NULL.
@@ -966,20 +917,14 @@ uint64_t *
 pctrie_remove_lookup(struct pctrie *ptree, uint64_t index,
     struct pctrie_node **freenode)
 {
-       struct pctrie_node *child, *node;
+       struct pctrie_node *node, *parent;
        uint64_t *m;
-       int slot;
 
-       node = NULL;
-       child = pctrie_root_load(ptree, NULL, PCTRIE_LOCKED);
-       while (!pctrie_isleaf(child)) {
-               node = child;
-               slot = pctrie_slot(node, index);
-               child = pctrie_node_load(&node->pn_child[slot], NULL,
-                   PCTRIE_LOCKED);
-       }
-       if ((m = pctrie_match_value(child, index)) != NULL)
-               pctrie_remove(ptree, node, index, freenode);
+       node = _pctrie_lookup_node(ptree, NULL, index, &parent, NULL,
+           PCTRIE_LOCKED);
+       m = pctrie_match_value(node, index);
+       if (m != NULL)
+               pctrie_remove(ptree, parent, index, freenode);
        else
                *freenode = NULL;
        return (m);
@@ -1117,36 +1062,17 @@ pctrie_reclaim_begin_cb(struct pctrie_node **pnode, 
struct pctrie *ptree,
 uint64_t *
 pctrie_replace(struct pctrie *ptree, uint64_t *newval)
 {
-       struct pctrie_node *leaf, *parent, *node;
+       struct pctrie_node *node, *parent;
        uint64_t *m;
-       uint64_t index;
-       int slot;
 
-       leaf = pctrie_toleaf(newval);
-       index = *newval;
-       node = pctrie_root_load(ptree, NULL, PCTRIE_LOCKED);
-       parent = NULL;
-       for (;;) {
-               if (pctrie_isleaf(node)) {
-                       if ((m = pctrie_toval(node)) != NULL && *m == index) {
-                               if (parent == NULL)
-                                       pctrie_node_store(pctrie_root(ptree),
-                                           leaf, PCTRIE_LOCKED);
-                               else
-                                       pctrie_node_store(
-                                           &parent->pn_child[slot], leaf,
-                                           PCTRIE_LOCKED);
-                               return (m);
-                       }
-                       break;
-               }
-               if (pctrie_keybarr(node, index, &slot))
-                       break;
-               parent = node;
-               node = pctrie_node_load(&node->pn_child[slot], NULL,
-                   PCTRIE_LOCKED);
-       }
-       panic("%s: original replacing value not found", __func__);
+       node = _pctrie_lookup_node(ptree, NULL, *newval, &parent, NULL,
+           PCTRIE_LOCKED);
+       m = pctrie_match_value(node, *newval);
+       if (m == NULL)
+               panic("%s: original replacing value not found", __func__);
+       pctrie_node_store(pctrie_child(ptree, parent, *newval),
+           pctrie_toleaf(newval), PCTRIE_LOCKED);
+       return (m);
 }
 
 #ifdef DDB

Reply via email to