static void mas_ascend(struct ma_state *mas)
{
- struct maple_enode *p_enode = mas->node; // parent enode.
- struct maple_enode *a_enode = mas->node; // ancestor enode.
+ struct maple_enode *p_enode; // parent enode.
+ struct maple_enode *a_enode; // ancestor enode.
struct maple_node *a_node = mas_mn(mas); // ancestor node.
- unsigned char a_slot = 0;
- enum maple_type a_type = mte_node_type(mas->node);
- unsigned long max = 0, min = ULONG_MAX;
+ unsigned char a_slot;
+ enum maple_type a_type;
+ unsigned long min, max;
+ unsigned long *pivots;
bool set_max = false, set_min = false;
if (ma_is_root(a_node))
- goto no_parent;
+ return;
a_type = mas_parent_enum(mas, mas->node);
a_enode = mt_mk_node(mte_parent(mas->node), a_type);
- p_enode = a_enode;
- if (mte_is_root(a_enode))
- goto parent_is_root;
-
- mas->node = p_enode;
-ascend:
- a_type = mas_parent_enum(mas, mas->node);
- a_node = mte_parent(mas->node);
- a_slot = mte_parent_slot(mas->node);
- a_enode = mt_mk_node(a_node, a_type);
- if (!set_min && a_slot) {
- set_min = true;
- min = mte_pivot(a_enode, a_slot - 1) + 1;
- }
-
- if (!set_max && a_slot < mt_pivots[a_type]) {
- set_max = true;
- max = mte_pivot(a_enode, a_slot);
- }
-
-no_parent:
- if (unlikely(ma_is_root(a_node))) {
-parent_is_root:
- if (!set_min)
- min = 0;
- if (!set_max)
- max = mt_max[a_type];
+ mas->node = a_enode;
+ if (mte_is_root(a_enode)) {
+ mas->max = ULONG_MAX;
+ mas->min = 0;
+ return;
}
- if (!max || min == ULONG_MAX) {
- if (mas->node == a_enode) {
+ min = 0;
+ max = ULONG_MAX;
+ p_enode = a_enode;
+ do {
+ a_type = mas_parent_enum(mas, p_enode);
+ a_node = mte_parent(p_enode);
+ a_slot = mte_parent_slot(p_enode);
+ pivots = ma_pivots(a_node, a_type);
+ a_enode = mt_mk_node(a_node, a_type);
+
+ if (unlikely(p_enode == a_enode)) {
+ // Dead node.
pr_err("Failed on node %p (%p)\n", mas_mn(mas),
a_enode);
//FIXME: Restart and retry if the lock is held.
- MT_BUG_ON(mas->tree, mas->node == a_enode);
+ MT_BUG_ON(mas->tree, p_enode == a_enode);
}
- mas->node = a_enode;
- goto ascend;
- }
+
+ if (!set_min && a_slot) {
+ set_min = true;
+ min = pivots[a_slot - 1] + 1;
+ }
+
+ if (!set_max && a_slot < mt_pivots[a_type]) {
+ set_max = true;
+ max = pivots[a_slot];
+ }
+
+ if (unlikely(ma_is_root(a_node))) {
+ break;
+ }
+
+ p_enode = a_enode;
+ } while (!set_min || !set_max);
mas->max = max;
mas->min = min;
- mas->node = p_enode;
}
static inline struct maple_node *mas_pop_node(struct ma_state *mas)