unsigned char piv, enum maple_type type)
{
unsigned long lpiv = _mas_safe_pivot(mas, pivots, piv, type);
+
if (!lpiv && piv)
return mas->max;
return lpiv;
ma_set_slot(mte_to_node(mn), slot, mte_node_type(mn), val);
}
+#define MA_META_END_MASK 0b1111
+#define MA_META_GAP_SHIFT 4
+static inline void ma_set_meta(struct maple_node *mn, enum maple_type mt,
+ unsigned char offset, unsigned char end)
+{
+
+ BUG_ON(mt != maple_arange_64);
+ mn->ma64.meta = (offset << MA_META_GAP_SHIFT) | end;
+}
+static inline unsigned char ma_meta_end(struct maple_node *mn,
+ enum maple_type mt)
+{
+
+ BUG_ON(mt != maple_arange_64);
+ return mn->ma64.meta & MA_META_END_MASK;
+}
+static inline unsigned char ma_meta_gap(struct maple_node *mn,
+ enum maple_type mt)
+{
+
+ BUG_ON(mt != maple_arange_64);
+ return mn->ma64.meta >> MA_META_GAP_SHIFT;
+}
+static inline void ma_set_meta_gap(struct maple_node *mn, enum maple_type mt,
+ unsigned char offset)
+{
+
+ BUG_ON(mt != maple_arange_64);
+ mn->ma64.meta = (offset << MA_META_GAP_SHIFT) |
+ (mn->ma64.meta & MA_META_END_MASK);
+}
/*
* mat_add() - Add a @dead_enode to the ma_topiary of a list of dead nodes.
*
{
enum maple_type type = mte_node_type(mas->node);
unsigned char offset = mt_min_slots[type];
- unsigned long piv, *pivots = ma_pivots(mas_mn(mas), type);
+ unsigned long *pivots = ma_pivots(mas_mn(mas), type);
- if (pivots[offset]) {
- do {
- piv = mas_logical_pivot(mas, pivots, offset, type);
- if (piv >= mas->max)
- break;
+ if (type == maple_arange_64)
+ return ma_meta_end(mte_to_node(mas->node), type);
- } while (++offset < mt_slots[type]);
- } else {
- while (--offset) {
- if (pivots[offset]) {
- if (pivots[offset] < mas->max)
- offset++;
- break;
- }
- };
+ if (!pivots[offset])
+ goto decrement;
+
+ // Higher than the min.
+ offset = mt_pivots[type] - 1;
+ // Check exceptions outside of the loop.
+ if (pivots[offset]) { // almost full.
+ if (pivots[offset] != mas->max) // Totally full.
+ return offset + 1;
+ return offset;
}
+decrement:
+ while (--offset) {
+ if (pivots[offset])
+ break;
+ };
+ if (pivots[offset] < mas->max)
+ offset++;
+
return offset;
}
unsigned long *pivots = ma_pivots(mn, mt);
void **slots = ma_slots(mn, mt);
unsigned char i;
+ unsigned char max_piv;
if (ma_is_dense(mt)) {
for (i = 0; i < mt_slot_count(mas->node); i++) {
return max_gap;
}
+ // Removing the pivot overflow optimizes the loop below.
+ max_piv = mt_pivots[mt] - 1;
+ if (pivots[max_piv] && pivots[max_piv] != mas->max &&
+ !slots[max_piv + 1])
+ max_gap = mas->max - pivots[max_piv];
+
pstart = mas->min;
- for (i = 0; i < mt_slots[mt]; i++) {
- pend = mas_logical_pivot(mas, pivots, i, mt);
+ for (i = 0; i < mt_pivots[mt]; i++) {
+ pend = pivots[i];
+ if (!pend && i)
+ pend = mas->max;
if (slots[i])
goto next;
+
gap = pend - pstart + 1;
if (gap > max_gap)
max_gap = gap;
return max_gap;
}
static inline unsigned long
-ma_max_gap(unsigned long *pivots, unsigned long *gaps, enum maple_type mt)
+ma_max_gap(struct maple_node *node, unsigned long *gaps, enum maple_type mt,
+ unsigned char *offset)
{
- unsigned char i = mt_slots[mt] - 1;
- unsigned long max_gap = gaps[i--];
- do {
- if (!pivots[i])
- continue;
+ unsigned char i = ma_meta_end(node, mt);
+ unsigned long max_gap = 0;
- if (gaps[i] > max_gap)
+ do {
+ if (gaps[i] > max_gap) {
max_gap = gaps[i];
+ *offset = i;
+ }
} while(i--);
return max_gap;
}
+
/*
* mas_max_gap() - find the largest gap in a non-leaf node and set the slot.
*/
static inline unsigned long mas_max_gap(struct ma_state *mas)
{
- unsigned long *gaps, *pivots;
+ unsigned long *gaps;//, *pivots;
+ unsigned char offset;
enum maple_type mt;
if (mte_is_leaf(mas->node))
return mas_leaf_max_gap(mas);
mt = mte_node_type(mas->node);
gaps = ma_gaps(mas_mn(mas), mt);
- pivots = ma_pivots(mas_mn(mas), mt);
- return ma_max_gap(pivots, gaps, mt);
+ offset = ma_meta_gap(mas_mn(mas), mt);
+ if (offset == 15)
+ return 0;
+
+ return gaps[offset];
}
static inline unsigned long mas_tree_gap(struct ma_state *mas)
{
}
return mas_max_gap(mas);
}
-
-static inline void mas_parent_gap(struct ma_state *mas, unsigned char slot,
+static inline void mas_parent_gap(struct ma_state *mas, unsigned char offset,
unsigned long new)
{
- unsigned long old_max_gap = 0;
- struct maple_node *pnode, *gpnode = NULL; // parent and grand parent nodes.
+ unsigned long meta_gap = 0;
+ struct maple_node *pnode;
struct maple_enode *penode;
- unsigned long *ppivots, *pgaps, *gpgaps = NULL;
- enum maple_type pmt, gpmt;
- unsigned char pslot = slot;
+ unsigned long *pgaps;
+ unsigned char meta_offset;
+ enum maple_type pmt;
pnode = mte_parent(mas->node);
- pmt = gpmt = mas_parent_enum(mas, mas->node);
+ pmt = mas_parent_enum(mas, mas->node);
penode = mt_mk_node(pnode, pmt);
pgaps = ma_gaps(pnode, pmt);
ascend:
- if (!mte_is_root(penode)) {
- gpnode = mte_parent(penode);
- gpmt = mas_parent_enum(mas, penode);
- gpgaps = ma_gaps(gpnode, gpmt);
- pslot = mte_parent_slot(penode);
- old_max_gap = gpgaps[pslot];
- }
- pgaps[slot] = new;
- if (mte_is_root(penode))
+ meta_offset = ma_meta_gap(pnode, pmt);
+ if (meta_offset == 15)
+ meta_gap = 0;
+ else
+ meta_gap = pgaps[meta_offset];
+
+ pgaps[offset] = new;
+
+ if (meta_gap == new)
return;
- ppivots = ma_pivots(pnode, pmt);
- new = ma_max_gap(ppivots, pgaps, pmt);
- if (new == old_max_gap)
+ if (offset != meta_offset) {
+ if (meta_gap > new)
+ return;
+
+ ma_set_meta_gap(pnode, pmt, offset);
+ } else if (new < meta_gap) {
+ meta_offset = 15;
+ new = ma_max_gap(pnode, pgaps, pmt, &meta_offset);
+ ma_set_meta_gap(pnode, pmt, meta_offset);
+ }
+
+ if (ma_is_root(pnode))
return;
/* Go to the parent node. */
- pnode = gpnode;
- pmt = gpmt;
- pgaps = gpgaps;
- slot = pslot;
+ pnode = mte_parent(penode);
+ pmt = mas_parent_enum(mas, penode);
+ pgaps = ma_gaps(pnode, pmt);
+ offset = mte_parent_slot(penode);
penode = mt_mk_node(pnode, pmt);
goto ascend;
}
return;
max_gap = mas_max_gap(mas);
- /* Get the gap reported in the parent */
+
pslot = mte_parent_slot(mas->node);
p_gap = ma_gaps(mte_parent(mas->node),
mas_parent_enum(mas, mas->node))[pslot];
unsigned long *pivots = ma_pivots(node, mt);
unsigned long *gaps = NULL;
+ if (mab_end - mab_start > mt_pivots[mt])
+ mab_end--;
+
for (i = mab_start; i <= mab_end; i++, j++) {
if (j && !b_node->pivot[i])
break;
- if (j < mt_pivots[mt])
- pivots[j] = b_node->pivot[i];
+ pivots[j] = b_node->pivot[i];
}
memcpy(slots, b_node->slot + mab_start,
sizeof(void*) * (i - mab_start));
if (!ma_is_leaf(mt) && mt_is_alloc(mas->tree)) {
+ unsigned long max_gap = 0;
+ unsigned char offset = 15, tmp;
+ unsigned char end = i - mab_start;
gaps = ma_gaps(mas_mn(mas), mt);
- memcpy(gaps, b_node->gap + mab_start,
- sizeof(unsigned long) * (i - mab_start));
+ for (tmp = 0; tmp < end; tmp++) {
+ gaps[tmp] = b_node->gap[mab_start + tmp];
+ if (gaps[tmp] > max_gap) {
+ offset = tmp;
+ max_gap = gaps[tmp];
+ }
+ }
+// memcpy(gaps, b_node->gap + mab_start,
+// sizeof(unsigned long) * end);
+ ma_set_meta(node, mt, offset, end - 1);
}
mas->max = b_node->pivot[--i];
}
if (!ma_is_leaf(type))
gaps = ma_gaps(node, type);
- if (offset == mt_pivots[type]) {
- // Initial start, walk until the end of the data.
- while (--offset) {
- if (pivots[offset]) {
- if (pivots[offset] < mas->max)
- offset++;
- break;
- }
- }
- }
-
min = _mas_safe_pivot(mas, pivots, offset, type) + 1;
do {
max = min - 1;
break;
} while (offset--);
- if (offset >= mt_slots[type]) { // node exhausted.
+ if (offset >= mt_slots[type]) { // Overflow, node exhausted.
offset = 0;
goto ascend;
}
mas->node = mas_slot(mas, slots, offset);
mas->min = min;
mas->max = max;
- mas->offset = mt_pivot_count(mas->node);
+ mas->offset = mas_data_end(mas);
return false;
ascend:
{
enum maple_type type = mte_node_type(mas->node);
unsigned long pivot, min, gap = 0;
- unsigned char offset = 0, pivot_count = mt_pivots[type];
+ unsigned char offset = 0;
unsigned long *gaps = NULL, *pivots = ma_pivots(mas_mn(mas), type);
void **slots = ma_slots(mas_mn(mas), type);
bool found = false;
}
min = mas_safe_min(mas, pivots, offset);
- for (; offset <= pivot_count; offset++) {
+ for (; offset < mt_slots[type]; offset++) {
pivot = _mas_safe_pivot(mas, pivots, offset, type);
if (offset && !pivot)
break;
{
struct maple_enode *last = NULL;
- mas->offset = mt_pivot_count(mas->node);
+ mas->offset = mas_data_end(mas);
/* There are 4 options:
* go to child (descend)
* Returns: 0 on success, -EBUSY otherwise.
*/
static inline int mas_rev_alloc(struct ma_state *mas, unsigned long min,
- unsigned long max, void *entry,
- unsigned long size, unsigned long *index)
+ unsigned long max, void *entry,
+ unsigned long size, unsigned long *index)
{
int ret = 0;
* range_min and range_max will be set accordingly.
*
*/
-static inline void *mas_range_load(struct ma_state *mas, unsigned long *range_min,
- unsigned long *range_max)
+static inline void *mas_range_load(struct ma_state *mas,
+ unsigned long *range_min, unsigned long *range_max)
{
void *entry = NULL;
pr_cont(" contents: ");
for (i = 0; i < MAPLE_ARANGE64_SLOTS; i++)
pr_cont("%lu ", node->gap[i]);
- pr_cont("| ");
+ pr_cont("| %02X | ", node->meta);
for (i = 0; i < MAPLE_ARANGE64_SLOTS - 1; i++)
pr_cont(MA_PTR" %lu ", node->slot[i], node->pivot[i]);
pr_cont(MA_PTR"\n", node->slot[i]);