unsigned char end;
unsigned char insert_off;
unsigned char offset; /* Operating position */
- bool is_alloc;
};
struct ma_node_state {
if (wr_mas->r_min < wr_mas->mas->index) {
part->pivots[0] = wr_mas->mas->index - 1;
part->slots[0] = wr_mas->content;
+ printk("%s zero piv is %lu\n", __func__,part->pivots[part->size]);
part->size++;
}
part->pivots[part->size] = wr_mas->mas->last;
part->slots[part->size] = wr_mas->entry;
+ printk("%s one piv is %lu\n", __func__,part->pivots[part->size]);
part->size++;
if (wr_mas->end_piv > wr_mas->mas->last) {
part->pivots[part->size] = wr_mas->end_piv;
part->slots[part->size] = src->slots[wr_mas->offset_end];
+ printk("%s last piv is %lx\n", __func__,part->pivots[part->size]);
part->size++;
}
part->skip = wr_mas->offset_end - wr_mas->mas->offset + 1;
+ printk("skip %u\n", part->skip);
part->leaf = true;
}
mni->slots = ma_slots(node, type);
mni->pivots = ma_pivots(node, type);
mni->gaps = ma_gaps(node, type);
- mni->is_alloc = false;
}
static inline
src->offset += len;
}
+struct split_data {
+ /*
+ * Used to split the data between two nodes.
+ * The user of this struct, mt_wr_split_data(), must keep track of the
+ * offset into the entire data (up to two nodes worth), so that the
+ * insert can be placed in the correct place while the source data that
+ * is overwritten is skipped.
+ */
+ unsigned char offset; /* Offset into destination data (entire set) */
+ unsigned char space; /* The space left in the current destination node */
+ unsigned char split; /* Proposed split of data */
+ unsigned char insert; /* Insert location of destination */
+ unsigned char insert_end;/* Insert end location of destination */
+ unsigned char new_end; /* Total data */
+ unsigned char src_ins_end; /* Offset into source data where the write ends */
+ unsigned char len; /* Number of ma_node_states in the states array */
+ struct ma_node_state states[5];
+ bool is_alloc;
+};
+
/*
*
* Zero any area that needs to be zeroed and set the metadata.
* metadata needs the largest gap for non-leaves.
*/
static __always_inline
-void mni_finalise(struct ma_node_info *p)
+void mni_finalise(struct ma_node_info *p, struct split_data *sd)
{
unsigned long max_gap;
unsigned char len;
+ if (!sd->is_alloc)
+ printk("\n\n\nNOT ALLOC\n\n\n");
len = mt_slots[p->type] - p->offset;
if (len) {
memset(p->slots + p->offset, 0, len * sizeof(void *));
unsigned long *pivs;
void **slots;
- if (!p->is_alloc)
+ if (!sd->is_alloc)
goto finalise_leaf;
i = 0;
offset = p->offset - 2;
if (p->offset <= mt_pivots[p->type]) {
ma_set_meta(p->node, p->type, 0, p->offset - 1);
}
+ if (p->max != ULONG_MAX) {
+ if (p->slots[p->offset - 1] == NULL) {
+ printk("last slot %u has %lu\n", p->offset - 1,
+ p->pivots[p->offset - 1]);
+ }
+ BUG_ON(p->slots[p->offset - 1] == NULL);
+ }
} else {
unsigned long gap_off = 0;
if (p->gaps) {
if (last_dst != ns->dst) {
WARN_ON_ONCE(!max);
ns->dst->min = max + 1;
+ printk("%p max set to %lu\n", last_dst->node, last_dst->max);
+ printk("%p min set to %lu\n", ns->dst->node, ns->dst->min);
}
last_dst = ns->dst;
if (ns->start + size > mt_pivots[ns->info->type]) {
piv_overflow = 1;
max = ns->info->max;
+ printk("max fro ns->info->max\n");
} else {
+ printk("max from %lu\n", size - 1 );
max = s_piv[size - 1];
}
}
}
}
-struct split_data {
- /*
- * Used to split the data between two nodes.
- * The user of this struct, mt_wr_split_data(), must keep track of the
- * offset into the entire data (up to two nodes worth), so that the
- * insert can be placed in the correct place while the source data that
- * is overwritten is skipped.
- */
- unsigned char offset; /* Offset into destination data (entire set) */
- unsigned char space; /* The space left in the current destination node */
- unsigned char split; /* Proposed split of data */
- unsigned char insert; /* Insert location of destination */
- unsigned char insert_end;/* Insert end location of destination */
- unsigned char new_end; /* Total data */
- unsigned char src_ins_end; /* Offset into source data where the write ends */
- unsigned char len; /* Number of ma_node_states in the states array */
- struct ma_node_state states[5];
-};
-
static inline void mas_wr_converged(struct ma_node_info *src,
struct ma_node_info *dst, struct ma_node_part *part,
struct ma_state *mas, struct split_data *sd)
mns_assemble(sd->states, sd->len);
dst->node->parent = src->node->parent;
- mni_finalise(dst);
+ mni_finalise(dst, sd);
}
/*
copied = min(part->size - part->pos, sd->space);
state->part = part;
printk("insert part at %u first entry is %p\n", sd->offset, part->slots[0]);
+ printk("Size is %u/%u\n", copied, part->size);
mns_mni_init(state, dst, part->pos , copied);
state->use_part = true;
part->pos += copied;
src->offset = sd->src_ins_end + 1;
+ printk("Set src %p offset to %u\n", src->node, src->offset);
} else {
state->info = src;
if (sd->offset < sd->insert_end) {
* First part of node, may split across node
* boundaries though
*/
+ printk("%d\n", __LINE__);
copied = min(sd->space, sd->insert - sd->offset);
} else {
+ printk("%d\n", __LINE__);
copied = min(sd->space, (src->end - src->offset + 1));
}
BUG_ON(copied == 0);
+ printk("src offset is %u\n", src->offset);
mns_mni_init(state, dst, src->offset, copied);
src->offset += copied;
}
}
mns_assemble(sd->states, sd->len);
- mni_finalise(left);
- mni_finalise(right);
+ mni_finalise(left, sd);
+ mni_finalise(right, sd);
mni_node_part_init(part, left, right);
mas_ascend(mas);
mas->end = parent.end;
bool left_store)
{
struct ma_node_info *dst;
+ struct ma_node_state *state;
- printk("\t\t%s\n", __func__);
+ printk("\t\t%s \n", __func__);
sd->insert_end = sd->insert + part->size - 1;
if (!left_store) {
char len;
* the right node
*/
printk("store is in right\n");
+ state = &sd->states[sd->len];
left->min = src2->min;
right->max = src->max;
sd->offset = src2->end + 1;
- sd->split++;
- sd->states[sd->len].info = src2;
+ state->info = src2;
printk("cp from %p\n", src2->node);
/* The first state to copy is the left node */
- printk("cp to left %u-%u\n", 0, sd->split);
- mns_mni_init(&sd->states[sd->len], left, 0, sd->split);
+ printk("cp to left %u+%u\n", 0, sd->split);
+ mns_mni_init(state, left, 0, sd->split);
+ if (ma_is_leaf(src->type) && mns_ends_in_null(state)) {
+ printk("ends in null\n");
+ sd->split--;
+ state->size--;
+ printk("NEW cp to left %u-%u\n", 0, sd->split);
+ }
sd->len++;
/* Copy the remainder of the left to the start of the right */
len = src2->end + 1 - sd->split;
sd->states[sd->len].info = src2;
mns_mni_init(&sd->states[sd->len], right, sd->split, len);
- printk("cp to right %u-%u\n", sd->split, len);
+ printk("cp to right %u-%u (%u + 1 - %u\n", sd->split, len, src2->end, sd->split);
sd->len++;
sd->space = mt_slots[right->type];
dst = right;
+ printk("src ins end is %u\n", wr_mas->offset_end);
+ printk("\n");
} else {
printk("store left\n");
sd->space = sd->split;
if (left_store) {
char len;
+ if (sd->offset >= sd->insert && sd->offset <= sd->insert_end)
+ printk("BING\n");
+
+ state = &sd->states[sd->len];
sd->split = (sd->new_end + 1) / 2;
printk("sd is at offset %u splut %u\n", sd->offset, sd->split);
len = sd->split - sd->offset;
- sd->states[sd->len].info = src2;
+ state->info = src2;
printk("cp right->%u + %u to left\n", 0, len);
- mns_mni_init(&sd->states[sd->len], left, 0, len);
- sd->len++;
+ mns_mni_init(state, left, 0, len);
+ if (ma_is_leaf(src->type) && mns_ends_in_null(state)) {
+ printk("ends in null\n");
+ sd->split--;
+ sd->offset--;
+ sd->space++;
+ state->size--;
+ len--;
+ }
+
+ printk("state %d: cp %p[%u] + %u to %s\n", sd->len, src->node,
+ sd->states[sd->len].start,
+ sd->states[sd->len].size, dst == left ? "left" : "right");
printk("cp the right->to right->%u + %u\n", len, src2->end + 1);
+ sd->len++;
/* Stored to the left, copy the last of the right->in src2 */
sd->states[sd->len].info = src2;
mns_mni_init(&sd->states[sd->len], right, len, src2->end + 1 - len);
+ printk("state %d: cp %p[%u] + %u to %s\n", sd->len, src->node,
+ sd->states[sd->len].start,
+ sd->states[sd->len].size, dst == left ? "left" : "right");
sd->len++;
}
mns_assemble(sd->states, sd->len);
- mni_finalise(left);
- mni_finalise(right);
+ mni_finalise(left, sd);
+ mni_finalise(right, sd);
mni_node_part_init(part, left, right);
part->skip = 2;
}
}
mns_assemble(sd->states, sd->len);
- mni_finalise(left);
+ mni_finalise(left, sd);
mni_node_part_init(part, left, NULL);
part->skip = 2;
}
*/
mt_dump(mas->tree, mt_dump_dec);
printk("Rebalance %p offset %u - %u\n", mas->node, mas->offset, wr_mas->offset_end);
- printk("Store %lu - %lu\n", mas->index, mas->last);
+ printk("Store %p %lu - %lu\n", wr_mas->entry, mas->index, mas->last);
height = mas_mt_height(mas);
mni_mas_init(&src, mas);
src.end = mas->end;
+ printk("HERE\n");
mns_node_part_leaf_init(&part, wr_mas, &src);
sd.new_end = mas->end + part.size - part.skip + 1;
sd.src_ins_end = wr_mas->offset_end;
sd.len = 0;
mni_node_init(&left, mas_pop_node(mas), wr_mas->type);
+ printk("left is %p\n", left.node);
if (mt_is_alloc(mas->tree))
- left.is_alloc = true;
+ sd.is_alloc = true;
+ else
+ sd.is_alloc = false;
+
do {
printk("\tloop\n");
tmp_mas = *mas;
printk("rebalance %p %p\n", src.node, src2.node);
sd.new_end += src2.end + 1;
+ printk("new end %u\n", sd.new_end);
if (sd.new_end < mt_min_slots[left.type]) {
printk("Not enough tdata\n");
exit(0);
}
- if (sd.split < mt_min_slots[left.type]) {
- printk("Too small split\n");
- exit(0);
- }
+ printk("Total data is %u\n", sd.new_end);
+ printk("sd insert is %u\n", sd.insert);
+ if (sd.new_end >= mt_slots[left.type]) {
if (sd.new_end - sd.split < mt_min_slots[left.type]) {
printk("Too big split\n");
exit(0);
}
- printk("Total data is %u\n", sd.new_end);
- printk("sd insert is %u\n", sd.insert);
- if (sd.new_end >= mt_slots[left.type]) {
mni_node_init(&right, mas_pop_node(mas), mte_node_type(mas->node));
+ printk("right is %p\n", right.node);
+ printk("%s end with %lu - %lu\n", __func__, mas->index, mas->last);
mas_wr_rebalance_two(wr_mas, &left, &right, &src, &src2, &part, &sd, left_store);
mas_ascend(mas);
mas->end = parent.end;
mas->offset = parent.insert_off;
- printk("Replacing 2 nodes, break\n");
+ printk("Replacing 2 nodes (%d), break\n", sd.new_end);
printk("mas is %p\n", mas->node);
break;
}
printk("REDUCE %p %p\n", src.node, src2.node);
- sd.split = 255;
mas_wr_rebalance_reduce(wr_mas, &left, &src, &src2, &part, &sd, left_store);
/* Must go again */
mas_wr_converged(&parent, &new_parent, &part, mas, &sd);
src.enode = parent.enode;
- printk("Replace %p with %p\n", parent.node, new_parent.enode);
+ printk("Replace %p with %p\n", parent.node, mte_to_node(new_parent.enode));
mas->node = new_parent.enode;
new_root:
mas_wmb_replace(mas, src.enode);
mni_node_init(&right, mas_pop_node(mas), wr_mas->type);
if (mt_is_alloc(mas->tree))
- right.is_alloc = left.is_alloc = true;
+ sd.is_alloc = true;
+ else
+ sd.is_alloc = false;
mns_node_part_leaf_init(&part, wr_mas, &src);
sd.new_end = mas->end + part.size; /* - skip + 1 */
mt_wr_split_data(&src, &left, &right, &part, &sd);
mns_assemble(sd.states, sd.len);
- mni_finalise(&left);
- mni_finalise(&right);
+ mni_finalise(&left, &sd);
+ mni_finalise(&right, &sd);
if (height == 1)
goto new_root;
mt_wr_split_data(&src, &left, &right, &part, &sd);
mns_assemble(sd.states, sd.len);
- mni_finalise(&left);
- mni_finalise(&right);
+ mni_finalise(&left, &sd);
+ mni_finalise(&right, &sd);
}
new_root:
#include "../../../lib/test_maple_tree.c"
#define RCU_RANGE_COUNT 1000
-#define RCU_MT_BUG_ON(test, y) {if (y) { test->stop = true; } MT_BUG_ON(test->mt, y); }
+#define RCU_MT_BUG_ON(_test, _y) {if (_y) { {if (_test->stop != true) MT_BUG_ON(_test->mt, _y);} _test->stop = true; }}
struct rcu_test_struct2 {
struct maple_tree *mt;
/* Shrinking tree test. */
- for (int i = 13; i < ARRAY_SIZE(set); i++)
+ for (int i = 13; i < ARRAY_SIZE(set); i++) {
+ mt_dump(mt, mt_dump_dec);
+ printk("STORE %lu -> %p\n", set[i], entry[i%2]);
erase_check_insert(mt, i);
+ }
mt_set_non_kernel(99);
for (int i = 18; i < ARRAY_SIZE(set); i++) {
bool toggled, modified, deleted, added;
int i;
void *entry, *prev = NULL;
+ struct maple_node *p_node = NULL;
MA_STATE(mas, test->mt, 0, 0);
rcu_reader_register(test);
}
}
+ if (mas.index != r_start) {
+ alt = xa_mk_value(index + i * 2 + 1 +
+ RCU_RANGE_COUNT);
+ printk("Error: mas %p %lu-%lu %p != %lu-%lu %p %p line %d i %d, pnode %p\n",
+ mte_to_node(mas.node), mas.index, mas.last, entry,
+ r_start, r_end, expected, alt,
+ __LINE__, i, p_node);
+ }
RCU_MT_BUG_ON(test, mas.index != r_start);
+ if (mas.last != r_end) {
+ printk("last is wrong: %lx vs %lx\n", mas.last, r_end);
+ }
RCU_MT_BUG_ON(test, mas.last != r_end);
if (i == reader->flip) {
}
i++;
+ p_node = mte_to_node(mas.node);
}
rcu_read_unlock();
usleep(test->pause);
alt = xa_mk_value(index + i * 2 + 1 +
RCU_RANGE_COUNT);
mt_dump(test->mt, mt_dump_dec);
- printk("Error: %lu-%lu %p != %lu-%lu %p %p line %d i %d\n",
- mas.index, mas.last, entry,
+ printk("Error: mas %p %lu-%lu %p != %lu-%lu %p %p line %d i %d\n",
+ mas.node, mas.index, mas.last, entry,
r_start, r_end, expected, alt,
line, i);
}
struct maple_node *node;
DEFINE_MTREE(tree);
- //goto skip;
+ goto skip;
mt_dump(&tree, mt_dump_dec);
mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN | MT_FLAGS_USE_RCU);
check_mtree_dup(&tree);
mtree_destroy(&tree);
-skip:
/* RCU testing */
+skip:
mt_init_flags(&tree, 0);
check_erase_testset(&tree);
mtree_destroy(&tree);
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
}