From: Liam R. Howlett Date: Thu, 29 May 2025 01:03:32 +0000 (-0400) Subject: only expand null when needed, use right->insert_off instead of r_mas->offset X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=1dcebc58c349e154b75686d773acea075d9e7e85;p=users%2Fjedix%2Flinux-maple.git only expand null when needed, use right->insert_off instead of r_mas->offset Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index f603948e18d4..4538db620e4e 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -1633,7 +1633,6 @@ static inline void mas_update_gap(struct ma_state *mas) max_gap = mas_max_gap(mas); penode = mas->node; - printk("penode is %p\n", penode); do { /* Ascend */ pnode = mte_parent(penode); @@ -5018,7 +5017,7 @@ static void mas_wr_spanning_store(struct ma_wr_state *wr_mas) mas = wr_mas->mas; trace_ma_op(__func__, mas); printk("\n\n\n\t\t\t\t%s\n", __func__); - mt_dump(mas->tree, mt_dump_dec); + //mt_dump(mas->tree, mt_dump_dec); printk("Storing %lu - %lu -> %p\n", mas->index, mas->last, wr_mas->entry); if (mt_is_alloc(mas->tree)) @@ -5066,7 +5065,8 @@ static void mas_wr_spanning_store(struct ma_wr_state *wr_mas) /* Set up left side. */ mas_wr_walk_index(wr_mas); - mas_wr_extend_null(wr_mas); + if (!wr_mas->entry) + mas_wr_extend_null(wr_mas); printk("index %lu last %lu\n", mas->index, r_mas.last); if (unlikely(!mas->index && r_mas.last == ULONG_MAX)) { mas->last = ULONG_MAX; @@ -5123,14 +5123,14 @@ static void mas_wr_spanning_store(struct ma_wr_state *wr_mas) sd.new_end = mas->end - part.skip + part.size; if (mas->offset) { printk("offset %u < %u\n", mas->offset, mas->end); - max_s = 1; + max_s++; } if (r_mas.node != mas->node) { sd.new_end += r_mas.end + 1; } - if (r_mas.offset < r_mas.end) { + if (right.insert_off < r_mas.end) { printk("offset_end %u < %u\n", r_wr_mas.offset_end, r_mas.end); max_s++; } @@ -5430,222 +5430,10 @@ new_root: printk("replace %p with %p\n", mte_to_node(left.enode), mte_to_node(mas->node)); mas_wmb_replace(mas, left.enode); mtree_range_walk(mas); - mt_dump(mas->tree, mt_dump_dec); + //mt_dump(mas->tree, mt_dump_dec); fflush(stdout); mt_validate(mas->tree); } -#if 0 -static void mas_wr_spanning_store(struct ma_wr_state *wr_mas) -{ - struct ma_state *mas; - MA_STATE(r_mas, NULL, 0, 0); - MA_WR_STATE(r_wr_mas, &r_mas, wr_mas->entry); - struct ma_node_info src, r_src, other_src; - struct ma_node_info *sources[3]; - struct ma_node_info *destinations[3]; - struct ma_node_info left, right, middle; - struct ma_node_info parent, r_parent, new_parent; - struct ma_node_part part; - struct split_data sd; - unsigned char height, s, d; - bool append, prepend; - - mas = wr_mas->mas; - trace_ma_op(__func__, mas); - - mt_dump(mas->tree, mt_dump_dec); - printk("\t\t\t\t%s\n", __func__); - printk("Storing %lu - %lu -> %p\n", mas->index, mas->last, wr_mas->entry); - - if (unlikely(!mas->index && mas->last == ULONG_MAX)) - return mas_new_root(mas, wr_mas->entry); - - r_mas = *mas; - printk("r_wr_mas\n"); - r_mas.index = r_mas.last; - mas_wr_walk_index(&r_wr_mas); - r_mas.index = r_mas.min; - r_mas.offset = 0; - mas_wr_end_piv(&r_wr_mas); - - /* Set up left side. */ - printk("\nwr_mas\n"); - mas_wr_walk_index(wr_mas); - - - printk("At %p and %p\n", mas_mn(mas), mas_mn(&r_mas)); - printk("r_mas: end piv is %lu\n", r_wr_mas.end_piv); - - wr_mas->end_piv = r_wr_mas.end_piv; - mni_mas_init(&src, mas); - mni_mas_init(&r_src, &r_mas); - printk("offset end is %u\n", r_wr_mas.offset_end); - sd.len = 0; - sd.offset = 0; - sd.left_store = true; - sd.insert = mas->offset; - sd.src_ins_end = wr_mas->offset_end + mas->end + 1; - wr_mas->offset_end = r_wr_mas.offset_end + mas->end + 1; - printk("src is %p slots is %p\n", r_src.node, r_src.slots); - mns_node_part_span_leaf_init(&part, wr_mas, &r_wr_mas, &r_src); - do { - /* - * - * Set up sources (up to 4) - * Move mas or r_mas, if necessary - * Set up destinations (up to 3) - * Set up limits for destinations (up to 3) - * This will generate up to 6 copy segments! - * - * Iterate sd.offset until sd.new_end - * store from source up to limit or source max - * store part when sd.offset is in the correct limit - * Validate it doesn't end in NULL when switching destinations - * correct if it does - * finalise what is necessary - * Continue until parents meet with sufficient data - * - */ - - struct ma_node_state *state; - - for (int i = 0; i < part.size; i++) - printk("slot %u is %lu -> %p\n", i, part.pivots[i], part.slots[i]); - printk("skip %u\n", part.skip); - - sd.new_end = r_mas.end + mas->end - part.skip + 1 + part.size; - printk("r is %u l is %u part skip is %u\n", r_mas.end, mas->end, part.skip); - sd.len = 0; - r_src.offset = r_wr_mas.offset_end + 1; - printk("new end is %u\n", sd.new_end); - - left.min = src.min; - mas_wr_ascend_init(mas, &parent); - printk("parent is %p[%u]\n", parent.node, parent.insert_off); - mas->end = parent.end; - mas_wr_ascend_init(&r_mas, &r_parent); - r_mas.end = r_parent.end; - if (sd.new_end < mt_min_slots[src.type] && - !ma_is_root(src.node)) { - /* Take in more nodes */ - printk("!!! %d min slots not met\n", __LINE__); - if (r_parent.insert_off < r_parent.end) { - prepend = true; - mas_next_node(&r_mas, r_parent.node, ULONG_MAX); - other_src = parent; - other_src.insert_off++; - printk("Looks like there is a right sibling\n"); - } else if (parent.insert_off) { - append = true; - mas_prev_node(mas, 0); - other_src = parent; - other_src.insert_off--; - printk("Looks like there is a left sibling\n"); - } else if (r_parent.max > ULONG_MAX) { - prepend = true; - mas_next_node(&r_mas, r_parent.node, ULONG_MAX); - mni_mas_init(&other_src, &r_mas); - printk("Looks like there is a right cousin\n"); - BUG_ON(1); - } else { - append = true; - BUG_ON(!parent.min); - mas_prev_node(mas, 0); - mni_mas_init(&other_src, &r_mas); - printk("Looks like there is a left cousin\n"); - BUG_ON(1); - } - - mni_descend(&other_src); - sd.new_end += other_src.end + 1; - if (sd.new_end < mt_slots[src.type]) - sd.split = sd.new_end; - sd.split = (sd.new_end + 1) /2; - printk("new end is now %u\n", sd.new_end); - } - } - - s = 0; - if (append) { - source[s++] = &other_src; - append = false; - } - - source[s++] = &src; - source[s++] = &r_src; - if (prepend) { - source[s++] = &other_src; - prepend= false; - } - - d = 0; - destinations[d++] = &left; - if (sd.new_end < mt_slots[src.type]) { - /* Single node at this level */ - printk("%d\n", __LINE__); - left.max = r_src.max; - right.node = NULL; - middle.node = NULL; - sd.split = mt_slots[src.type]; - rebalance_reduce(&left, &src, &r_src, &part, &sd); - if (ma_is_root(parent.node)) { - printk("r offset %u p offset %u end %u\n", - r_parent.offset, parent.offset, parent.end); - sd.new_end = r_parent.insert_off - parent.insert_off; - sd.new_end = parent.end - sd.new_end; - printk("sd.new_end is %u\n", sd.new_end); - /* This is wrong... - * We have parent.end != 1, but we have - * replaced all the data.. - * */ - if (sd.new_end > 1) - break; - src.enode = mas->node; - left.node->parent = mas_mn(mas)->parent; - mas->node = left.enode; - mas->depth = mas_mt_height(mas) - 1; - mas_set_height(mas); - goto new_root; - } - } else if (sd.new_end < 2 * mt_slots[src.type]) { - printk("%d\n", __LINE__); - sd.split = (sd.new_end + 1) / 2; - printk("split at %u\n", sd.split); - mni_node_init(&right, mas_pop_node(mas), r_src.type); - destinations[d++] = &right; - } else { - printk("%d\n", __LINE__); - mni_node_init(&right, mas_pop_node(mas), r_src.type); - mni_node_init(&middle, mas_pop_node(mas), src.type); - destinations[d++] = &right; - destinations[d++] = &middle; - right.max = r_src.max; - } - - destination[0].min = src[0].min; - /* Uhh */ - do { - - } while(sd.new_end <= sd.offset); - - - sd.len = 0; - sd.offset = 0; - } while ((parent.node != r_parent.node) && - sd.new_end >= mt_slots[parent.type]); - - mas_wr_converged(&parent, &new_parent, &part, mas, &sd); - src.enode = parent.enode; - mas->node = new_parent.enode; - printk("replace %p with %p\n", src.enode, mas->node); - -new_root: - mas_wmb_replace(mas, src.enode); - mtree_range_walk(mas); - mt_dump(mas->tree, mt_dump_dec); - mt_validate(mas->tree); -} -#endif /* * mas_wr_store_entry() - Internal call to store a value diff --git a/tools/testing/radix-tree/maple.c b/tools/testing/radix-tree/maple.c index 53d985196e22..8cb08b5257ab 100644 --- a/tools/testing/radix-tree/maple.c +++ b/tools/testing/radix-tree/maple.c @@ -34847,6 +34847,7 @@ struct rcu_test_struct { unsigned long removed; /* The index of the removed entry */ unsigned long added; /* The index of the removed entry */ unsigned long toggle; /* The index of the removed entry */ + pthread_mutex_t dump; }; static inline @@ -34939,7 +34940,10 @@ static void *rcu_loop(void *ptr) /* Out of the interesting range */ if (mas.index < test->index || mas.index > test->last) { if (entry != expected) { - printk("%lx - %lx = %p not %p\n", + if (pthread_mutex_trylock(&test->dump) != 0) + break; + fflush(stdout); + printk("\nERROR: %lx - %lx = %p not %p\n", mas.index, mas.last, entry, expected); } MT_BUG_ON(test->mt, entry != expected); @@ -34958,6 +34962,7 @@ static void *rcu_loop(void *ptr) mas_set(&mas, test->range_start); } + fflush(stdout); rcu_unregister_thread(); return NULL; } @@ -35287,6 +35292,7 @@ static noinline void __init check_rcu_threaded(struct maple_tree *mt) vals.range_end = ULONG_MAX; vals.seen_entry2 = 0; vals.seen_entry3 = 0; + pthread_mutex_init(&vals.dump, NULL); run_check_rcu(mt, &vals); mtree_destroy(mt); @@ -36370,8 +36376,8 @@ void farmer_tests(void) struct maple_node *node; DEFINE_MTREE(tree); - goto skip; mt_dump(&tree, mt_dump_dec); + goto skip; mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN | MT_FLAGS_USE_RCU); check_vma_modification(&tree); @@ -36415,7 +36421,6 @@ void farmer_tests(void) check_prealloc(&tree); mtree_destroy(&tree); -skip: mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); check_spanning_write(&tree); mtree_destroy(&tree); @@ -36437,6 +36442,7 @@ skip: check_new_node(&tree); mtree_destroy(&tree); +skip: if (!MAPLE_32BIT) { mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); check_rcu_simulated(&tree); @@ -36545,10 +36551,10 @@ static void regression_tests(void) void maple_tree_tests(void) { -// maple_tree_seed(); -// maple_tree_harvest(); + //maple_tree_seed(); + //maple_tree_harvest(); #if !defined(BENCH) -// regression_tests(); + //regression_tests(); farmer_tests(); #endif }