lib/rbtree: Fix & document insert comparison order

The scheduler priq implementation was taking advantage of a subtle
behavior of the way the tree presents the order of its arguments (the
node being inserted is always first).  But it turns out the tree got
that wrong in one spot.

As this was subtle voodoo to begin with, it should have been
documented first.  Similarly add a little code to the test case to
guarantee this in the future.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2018-05-16 12:05:11 -07:00 committed by Anas Nashif
commit 6040bf7773
3 changed files with 22 additions and 1 deletions

View file

@ -53,6 +53,12 @@ struct rbnode {
* *
* Compares the two nodes and returns 1 if node A is strictly less * Compares the two nodes and returns 1 if node A is strictly less
* than B according to the tree's sorting criteria, 0 otherwise. * than B according to the tree's sorting criteria, 0 otherwise.
*
* Note that during insert, the new node being inserted will always be
* "A", where "B" is the existing node within the tree against which
* it is being compared. This trait can be used (with care!) to
* implement "most/least recently added" semantics between nodes which
* would otherwise compare as equal.
*/ */
typedef int (*rb_lessthan_t)(struct rbnode *a, struct rbnode *b); typedef int (*rb_lessthan_t)(struct rbnode *a, struct rbnode *b);

View file

@ -227,7 +227,7 @@ void rb_insert(struct rbtree *tree, struct rbnode *node)
struct rbnode *parent = stack[stacksz - 1]; struct rbnode *parent = stack[stacksz - 1];
int side = tree->lessthan_fn(parent, node); int side = !tree->lessthan_fn(node, parent);
set_child(parent, side, node); set_child(parent, side, node);
set_color(node, RED); set_color(node, RED);

View file

@ -23,6 +23,9 @@ static unsigned int node_mask[(MAX_NODES + 31)/32];
/* Array of nodes dumed via rb_walk */ /* Array of nodes dumed via rb_walk */
static struct rbnode *walked_nodes[MAX_NODES]; static struct rbnode *walked_nodes[MAX_NODES];
/* Node currently being inserted, for testing lessthan() argument order */
static struct rbnode *current_insertee;
void set_node_mask(int node, int val) void set_node_mask(int node, int val)
{ {
unsigned int *p = &node_mask[node / 32]; unsigned int *p = &node_mask[node / 32];
@ -48,6 +51,11 @@ int node_index(struct rbnode *n)
/* Our "lessthan" is just the location of the struct */ /* Our "lessthan" is just the location of the struct */
int node_lessthan(struct rbnode *a, struct rbnode *b) int node_lessthan(struct rbnode *a, struct rbnode *b)
{ {
if (current_insertee) {
CHECK(a == current_insertee);
CHECK(b != current_insertee);
}
return a < b; return a < b;
} }
@ -178,6 +186,13 @@ void check_tree(int size)
_check_tree(size, 1); _check_tree(size, 1);
} }
void checked_insert(struct rbtree *tree, struct rbnode *node)
{
current_insertee = node;
rb_insert(tree, node);
current_insertee = NULL;
}
void test_tree(int size) void test_tree(int size)
{ {
int i, j; int i, j;