unsigned long lmax; /* Logical max. */
unsigned char offset = mas->offset;
- if (min == mas->index && max == mas->last) {
- /* exact fit. */
- rcu_assign_pointer(slots[offset], entry);
- goto done;
- }
-
- /* out of room. */
- if (unlikely(offset + 1 >= mt_slots[mt]))
- return false;
-
if (max > mas->last) {
if ((min != mas->index) || (offset != end))
goto try_node_store;
*/
static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite)
{
- unsigned long r_max, r_min;
+ unsigned long r_max, r_min; /* Ranges */
+ unsigned long end_piv;
unsigned char end, zero;
void *content = NULL;
struct maple_big_node b_node;
void __rcu **slots;
enum maple_type mt;
struct maple_node *node;
+ unsigned long *pivots;
+ unsigned char offset_end;
int ret = 0;
mas_set_err(mas, -EEXIST);
return content;
}
+
+ pivots = ma_pivots(node, mt);
+ offset_end = mas->offset;
+ end_piv = r_max;
+ end = mas_data_end(mas);
+ while ((mas->last > end_piv) && (offset_end < end))
+ end_piv = pivots[++offset_end];
+
+ if (mas->last > end_piv)
+ end_piv = mas->max;
+
+
// FIXME: Try finding end offset out here and passing it through.
// Maybe a struct for writes?
// lmax and offset_end ?
if (!entry) {
- unsigned char offset_end = mas->offset;
+ /* Check next slot(s) if we are overwriting the end */
+ if ((mas->last == end_piv) && !slots[offset_end + 1]) {
+ if (offset_end + 1 == end)
+ mas->last = mas->max;
+ else
+ mas->last = pivots[offset_end + 1];
+ } else if ((mas->last > end_piv) && !slots[offset_end])
+ mas->last = end_piv;
if (!content) {
/* If this one is null, the next and prev are not */
mas->index = r_min;
- if (mas->last < r_max)
- mas->last = r_max;
} else {
- unsigned long *pivots = ma_pivots(node, mt);
- unsigned long piv = r_max;
-
- /* Check next slot(s) if we are overwriting the end */
- if (mas->last >= piv) {
- while (mas->last >= piv && mas->last != ULONG_MAX)
- piv = mas_logical_pivot(mas, pivots,
- ++offset_end, mt);
-
- if (!slots[offset_end])
- mas->last = piv;
- }
-
/* Check prev slot if we are overwriting the start */
if (mas->index == r_min && mas->offset &&
!slots[mas->offset - 1]) {
}
}
- end = mas_data_end(mas);
- if (mas_slot_store(mas, entry, r_min, r_max, end, content, mt, slots))
+ if (r_min == mas->index && r_max == mas->last) {
+ rcu_assign_pointer(slots[mas->offset], entry);
+ if (!!entry ^ !!content)
+ mas_update_gap(mas);
+ return content;
+ }
+
+ if (unlikely(mas->offset + 1 >= mt_slots[mt]))
+ goto slow_path;
+
+ if ((offset_end - mas->offset <= 1) &&
+ mas_slot_store(mas, entry, r_min, r_max, end, content, mt, slots))
return content;
+ else if ((mas->offset + 1 >= mt_slots[mt]) &&
+ mas_node_store(mas, entry, r_min, r_max, end, content, mt, slots, pivots))
+ return content;
if (mas_is_err(mas))
return content;
- /* Slow path. */
+slow_path:
b_node.type = mte_node_type(mas->node);
b_node.b_end = mas_store_b_node(mas, &b_node, entry, end);
b_node.min = mas->min;