* Look up the nearest entry at a position bigger than or equal to index, * assuming access is externally synchronized by a lock. */
| 479 | * assuming access is externally synchronized by a lock. |
| 480 | */ |
| 481 | uint64_t * |
| 482 | pctrie_lookup_ge(struct pctrie *ptree, uint64_t index) |
| 483 | { |
| 484 | struct pctrie_node *stack[PCTRIE_LIMIT]; |
| 485 | uint64_t inc; |
| 486 | uint64_t *m; |
| 487 | struct pctrie_node *child, *node; |
| 488 | #ifdef INVARIANTS |
| 489 | int loops = 0; |
| 490 | #endif |
| 491 | unsigned tos; |
| 492 | int slot; |
| 493 | |
| 494 | node = pctrie_root_load(ptree, NULL, PCTRIE_LOCKED); |
| 495 | if (node == NULL) |
| 496 | return (NULL); |
| 497 | else if (pctrie_isleaf(node)) { |
| 498 | m = pctrie_toval(node); |
| 499 | if (*m >= index) |
| 500 | return (m); |
| 501 | else |
| 502 | return (NULL); |
| 503 | } |
| 504 | tos = 0; |
| 505 | for (;;) { |
| 506 | /* |
| 507 | * If the keys differ before the current bisection node, |
| 508 | * then the search key might rollback to the earliest |
| 509 | * available bisection node or to the smallest key |
| 510 | * in the current node (if the owner is greater than the |
| 511 | * search key). |
| 512 | */ |
| 513 | if (pctrie_keybarr(node, index)) { |
| 514 | if (index > node->pn_owner) { |
| 515 | ascend: |
| 516 | KASSERT(++loops < 1000, |
| 517 | ("pctrie_lookup_ge: too many loops")); |
| 518 | |
| 519 | /* |
| 520 | * Pop nodes from the stack until either the |
| 521 | * stack is empty or a node that could have a |
| 522 | * matching descendant is found. |
| 523 | */ |
| 524 | do { |
| 525 | if (tos == 0) |
| 526 | return (NULL); |
| 527 | node = stack[--tos]; |
| 528 | } while (pctrie_slot(index, |
| 529 | node->pn_clev) == (PCTRIE_COUNT - 1)); |
| 530 | |
| 531 | /* |
| 532 | * The following computation cannot overflow |
| 533 | * because index's slot at the current level |
| 534 | * is less than PCTRIE_COUNT - 1. |
| 535 | */ |
| 536 | index = pctrie_trimkey(index, |
| 537 | node->pn_clev); |
| 538 | index += PCTRIE_UNITLEVEL(node->pn_clev); |
no test coverage detected