{
mas->node = MA_ERROR(err);
}
+static inline bool mas_is_ptr(struct ma_state *mas)
+{
+ return mas->node == MAS_ROOT;
+}
+static inline bool mas_is_none(struct ma_state *mas)
+{
+ return mas->node == MAS_NONE;
+}
+
static inline bool mas_is_start(struct ma_state *mas)
{
return mas->node == MAS_START;
return ms->alloc;
}
+/** Private
+ * Sets up maple state for operations by setting mas->min = 0 & mas->node to
+ * certain values.
+ * returns:
+ * - If it's an empty tree: NULL & mas->node == MAS_NONE
+ * - If it's a single entry: The entry & mas->node == MAS_ROOT
+ * - If it's a tree: NULL & mas->node == safe root node.
+ */
static inline struct maple_enode *mas_start(struct ma_state *mas)
{
+ void *entry = NULL;
+
+ if (mas_is_err(mas))
+ goto done;
+
if (mas_is_start(mas)) {
struct maple_enode *root;
+ mas->node = MAS_NONE;
mas->min = 0;
if (!mas->tree->ma_root) // empty tree.
- return NULL;
+ goto done;
+
+ root = mte_safe_root(mas->tree->ma_root);
if (!xa_is_node(mas->tree->ma_root)) {
+ // Single entry tree.
if (mas->index > 0)
- return NULL;
+ goto done;
+
+ entry = mas->tree->ma_root;
mas->node = MAS_ROOT;
mas_set_slot(mas, MAPLE_NODE_SLOTS);
- return mas->node;
+ } else {
+ mas->node = root;
}
- root = mte_safe_root(mas->tree->ma_root);
- mas->max = mt_node_max(root);
- return root;
}
- return mas->node;
+
+done:
+ return entry;
}
/* Private
restart_prev_node:
level = 0;
slot = mas_get_slot(mas);
- if (mte_is_root(mas->node))
+ if (mte_is_root(mas->node) || mas->node == MAS_NONE)
goto no_entry;
while (1) {
struct maple_enode *mn;
unsigned long prev_piv;
+ if (mte_is_root(mas->node) || mas->node == MAS_NONE)
+ goto no_entry;
+
mn = mas->node;
slot = mas_get_slot(mas);
start_piv = mas_get_safe_pivot(mas, slot);
level++;
- if (!mte_is_root(mas->node))
- mas_encoded_parent(mas);
+ mas_encoded_parent(mas);
if (!mas_safe_slot(mas, &slot, 1)) {
if (mte_is_root(mas->node))
static inline bool _mas_walk(struct ma_state *mas)
{
- mas->node = mas_start(mas);
- if (!mas->node) {
+ void *entry = mas_start(mas);
+ if (entry)
+ return true;
+
+ if (mas_is_none(mas)) {
mas_set_slot(mas, MAPLE_NODE_SLOTS);
return false;
}
- if (mas->node == MAS_ROOT)
+ if (mas_is_ptr(mas))
return true;
mas_set_slot(mas, 0);
static inline int mas_dead_node(struct ma_state *mas, unsigned long index)
{
+ if (mas->node == MAS_NONE)
+ return 0;
+
if (!mas->node)
return 0;
goto not_found;
if (mas_is_start(mas)) {
- _mas_walk(mas);
- if (!mas->node)
+ if (!_mas_walk(mas))
return NULL;
if (mas->node == MAS_ROOT)
do {} while (mas_dead_node(mas, mas->index));
+ if (mas->node == MAS_NONE)
+ goto not_found;
+
slot = mas_get_slot(mas);
last_piv = mas_get_safe_pivot(mas, slot);
rcu_read_lock();
_mas_walk(&mas);
- if (!mas.node)
+
+ if (mas_is_none(&mas))
goto done;
- if (mas.node == MAS_ROOT) {
- entry = mas.tree->ma_root;
+ if (mas_is_ptr(&mas)) {
+ if (!start)
+ entry = mas.tree->ma_root;
goto done;
}
retry:
mas_safe_next_entry(&mas, max);
- if (mas.node == MAS_NONE)
+ if (mas_is_none(&mas))
goto done;
rcu_read_lock();
_mas_walk(&mas);
- if (!mas.node)
+ if (mas_is_none(&mas))
goto done;
- if (mas.node == MAS_ROOT) {
- entry = mas.tree->ma_root;
+ if (mas_is_ptr(&mas))
goto done;
- }
+
retry:
mas_set_slot(&mas, mas_get_slot(&mas) + 1);
mas_safe_next_entry(&mas, max);
- if (mas.node == MAS_NONE)
+ if (mas_is_none(&mas))
goto done;
slot = mas_get_slot(&mas);
unsigned long last_piv;
unsigned char slot, coalesce;
- mas->node = mas_start(mas);
- if (!mas->node) {
+ mas_start(mas);
+ if (mas_is_none(mas)) {
mas_set_slot(mas, MAPLE_NODE_SLOTS);
return;
}
+
+ if (mas_is_ptr(mas))
+ return;
+
slot = mas_data_end(mas, mte_node_type(mas->node), &last_piv, &coalesce);
mas_set_slot(mas, slot);
{
struct maple_enode *last = NULL;
- mas->node = mas_start(mas);
- if (!mas->node)
+ mas_start(mas);
+ if (mas_is_none(mas))
+ return;
+
+ if (mas_is_ptr(mas))
return;
mas_set_slot(mas, 0);
leaf = _mas_walk(mas);
slot = mas_get_slot(mas);
- if (leaf == true && slot != MAPLE_NODE_SLOTS) {
- if (!overwrite) {
+ if (leaf == true) {
+ if (slot == MAPLE_NODE_SLOTS) {
+ if (mas->index == 0 && !overwrite)
+ goto exists;
+ } else if (!overwrite) {
void *entry = mte_get_rcu_slot(mas->node, slot);
if (!mt_is_empty(entry))
* and a size (size), find the lowest location in the min-max window in the
* tree which this allocation fits and set index to that value.
*
- * Returns: 0 on success, -EBUSY otherwise.
+ * Returns: 0 on success, -ENOMEM if allocation fails, -EBUSY otherwise.
*/
static inline int ma_alloc(struct ma_state *mas, void *entry,
unsigned long size, unsigned long *index)
{
unsigned char slot = MAPLE_NODE_SLOTS;
unsigned long min;
+ mas_start(mas);
- mas->node = mas_start(mas);
- if (!mas->node) {
- slot = 0;
- goto empty_tree;
- }
-
- if (!xa_is_node(rcu_dereference(mas->tree->ma_root))) {
+ if (mas_is_none(mas) || mas_is_ptr(mas)) {
ma_root_expand(mas, entry);
+ if (mas_is_err(mas))
+ return xa_err(mas->node);
+
if (!mas->index)
return mte_get_pivot(mas->node, 0);
return mte_get_pivot(mas->node, 1);
}
- mas_awalk(mas, size);
- // cannot be an empty tree here.
+ mas_awalk(mas, size); // Must be walking a tree.
if (mas_is_err(mas))
return xa_err(mas->node);
if (mas->index < min)
mas->index = min;
-empty_tree:
return mas_fill_gap(mas, entry, slot, size, index);
no_gap:
{
unsigned char slot = MAPLE_NODE_SLOTS;
- mas->node = mas_start(mas);
- if (!mas->node) {
+ mas_start(mas);
+
+ if (mas_is_none(mas)) {
slot = 0;
goto empty_tree;
}
- if (!xa_is_node(rcu_dereference(mas->tree->ma_root))) {
+ if (mas_is_ptr(mas)) {
ma_root_expand(mas, entry);
if (!mas->index)
return mte_get_pivot(mas->node, 0);
leaf = _mas_walk(mas);
slot = mas_get_slot(mas);
- if (leaf == true && slot != MAPLE_NODE_SLOTS)
- entry = mte_get_rcu_slot(mas->node, slot);
+ if (leaf == true) {
+ if (slot == MAPLE_NODE_SLOTS) {
+ if (mas->index == 0)
+ return root;
+ } else {
+ entry = mte_get_rcu_slot(mas->node, slot);
+ }
+ }
return entry;
}