* Look up the nearest entry at a position less than or equal to index, * assuming access is externally synchronized by a lock. */
| 594 | * assuming access is externally synchronized by a lock. |
| 595 | */ |
| 596 | uint64_t * |
| 597 | pctrie_lookup_le(struct pctrie *ptree, uint64_t index) |
| 598 | { |
| 599 | struct pctrie_node *stack[PCTRIE_LIMIT]; |
| 600 | uint64_t inc; |
| 601 | uint64_t *m; |
| 602 | struct pctrie_node *child, *node; |
| 603 | #ifdef INVARIANTS |
| 604 | int loops = 0; |
| 605 | #endif |
| 606 | unsigned tos; |
| 607 | int slot; |
| 608 | |
| 609 | node = pctrie_root_load(ptree, NULL, PCTRIE_LOCKED); |
| 610 | if (node == NULL) |
| 611 | return (NULL); |
| 612 | else if (pctrie_isleaf(node)) { |
| 613 | m = pctrie_toval(node); |
| 614 | if (*m <= index) |
| 615 | return (m); |
| 616 | else |
| 617 | return (NULL); |
| 618 | } |
| 619 | tos = 0; |
| 620 | for (;;) { |
| 621 | /* |
| 622 | * If the keys differ before the current bisection node, |
| 623 | * then the search key might rollback to the earliest |
| 624 | * available bisection node or to the largest key |
| 625 | * in the current node (if the owner is smaller than the |
| 626 | * search key). |
| 627 | */ |
| 628 | if (pctrie_keybarr(node, index)) { |
| 629 | if (index > node->pn_owner) { |
| 630 | index = node->pn_owner + PCTRIE_COUNT * |
| 631 | PCTRIE_UNITLEVEL(node->pn_clev); |
| 632 | } else { |
| 633 | ascend: |
| 634 | KASSERT(++loops < 1000, |
| 635 | ("pctrie_lookup_le: too many loops")); |
| 636 | |
| 637 | /* |
| 638 | * Pop nodes from the stack until either the |
| 639 | * stack is empty or a node that could have a |
| 640 | * matching descendant is found. |
| 641 | */ |
| 642 | do { |
| 643 | if (tos == 0) |
| 644 | return (NULL); |
| 645 | node = stack[--tos]; |
| 646 | } while (pctrie_slot(index, |
| 647 | node->pn_clev) == 0); |
| 648 | |
| 649 | /* |
| 650 | * The following computation cannot overflow |
| 651 | * because index's slot at the current level |
| 652 | * is greater than 0. |
| 653 | */ |
no test coverage detected