Restore avl_update() calls and related functions

The macOS kmem implementation uses avl_update() and related
functions.  These same function exist in the Solaris AVL code but
were removed because they were unused.  Restore them.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Jorgen Lundman <lundman@lundman.net>
Closes #10390
This commit is contained in:
Jorgen Lundman 2020-06-04 01:49:32 +09:00 committed by GitHub
parent 3bf3b164ee
commit 081de9a86d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 0 deletions

View File

@ -259,6 +259,17 @@ extern void avl_add(avl_tree_t *tree, void *node);
*/
extern void avl_remove(avl_tree_t *tree, void *node);
/*
* Reinsert a node only if its order has changed relative to its nearest
* neighbors. To optimize performance avl_update_lt() checks only the previous
* node and avl_update_gt() checks only the next node. Use avl_update_lt() and
* avl_update_gt() only if you know the direction in which the order of the
* node may change.
*/
extern boolean_t avl_update(avl_tree_t *, void *);
extern boolean_t avl_update_lt(avl_tree_t *, void *);
extern boolean_t avl_update_gt(avl_tree_t *, void *);
/*
* Swaps the contents of the two trees.
*/

View File

@ -809,6 +809,64 @@ avl_remove(avl_tree_t *tree, void *data)
} while (parent != NULL);
}
#define AVL_REINSERT(tree, obj) \
avl_remove((tree), (obj)); \
avl_add((tree), (obj))
boolean_t
avl_update_lt(avl_tree_t *t, void *obj)
{
void *neighbor;
ASSERT(((neighbor = AVL_NEXT(t, obj)) == NULL) ||
(t->avl_compar(obj, neighbor) <= 0));
neighbor = AVL_PREV(t, obj);
if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) < 0)) {
AVL_REINSERT(t, obj);
return (B_TRUE);
}
return (B_FALSE);
}
boolean_t
avl_update_gt(avl_tree_t *t, void *obj)
{
void *neighbor;
ASSERT(((neighbor = AVL_PREV(t, obj)) == NULL) ||
(t->avl_compar(obj, neighbor) >= 0));
neighbor = AVL_NEXT(t, obj);
if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) > 0)) {
AVL_REINSERT(t, obj);
return (B_TRUE);
}
return (B_FALSE);
}
boolean_t
avl_update(avl_tree_t *t, void *obj)
{
void *neighbor;
neighbor = AVL_PREV(t, obj);
if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) < 0)) {
AVL_REINSERT(t, obj);
return (B_TRUE);
}
neighbor = AVL_NEXT(t, obj);
if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) > 0)) {
AVL_REINSERT(t, obj);
return (B_TRUE);
}
return (B_FALSE);
}
void
avl_swap(avl_tree_t *tree1, avl_tree_t *tree2)
{
@ -1030,3 +1088,6 @@ EXPORT_SYMBOL(avl_remove);
EXPORT_SYMBOL(avl_numnodes);
EXPORT_SYMBOL(avl_destroy_nodes);
EXPORT_SYMBOL(avl_destroy);
EXPORT_SYMBOL(avl_update_lt);
EXPORT_SYMBOL(avl_update_gt);
EXPORT_SYMBOL(avl_update);