mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-03 21:01:50 +00:00
lib/interval_tree: fast overlap detection
Allow interval trees to quickly check for overlaps to avoid unnecesary tree lookups in interval_tree_iter_first(). As of this patch, all interval tree flavors will require using a 'rb_root_cached' such that we can have the leftmost node easily available. While most users will make use of this feature, those with special functions (in addition to the generic insert, delete, search calls) will avoid using the cached option as they can do funky things with insertions -- for example, vma_interval_tree_insert_after(). [jglisse@redhat.com: fix deadlock from typo vm_lock_anon_vma()] Link: http://lkml.kernel.org/r/20170808225719.20723-1-jglisse@redhat.com Link: http://lkml.kernel.org/r/20170719014603.19029-12-dave@stgolabs.net Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Signed-off-by: Jérôme Glisse <jglisse@redhat.com> Acked-by: Christian König <christian.koenig@amd.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Doug Ledford <dledford@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Cc: David Airlie <airlied@linux.ie> Cc: Jason Wang <jasowang@redhat.com> Cc: Christian Benvenuti <benve@cisco.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
09663c86e2
commit
f808c13fd3
33 changed files with 145 additions and 105 deletions
|
@ -65,11 +65,13 @@ RB_DECLARE_CALLBACKS(static, ITPREFIX ## _augment, ITSTRUCT, ITRB, \
|
|||
\
|
||||
/* Insert / remove interval nodes from the tree */ \
|
||||
\
|
||||
ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, struct rb_root *root) \
|
||||
ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, \
|
||||
struct rb_root_cached *root) \
|
||||
{ \
|
||||
struct rb_node **link = &root->rb_node, *rb_parent = NULL; \
|
||||
struct rb_node **link = &root->rb_root.rb_node, *rb_parent = NULL; \
|
||||
ITTYPE start = ITSTART(node), last = ITLAST(node); \
|
||||
ITSTRUCT *parent; \
|
||||
bool leftmost = true; \
|
||||
\
|
||||
while (*link) { \
|
||||
rb_parent = *link; \
|
||||
|
@ -78,18 +80,22 @@ ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, struct rb_root *root) \
|
|||
parent->ITSUBTREE = last; \
|
||||
if (start < ITSTART(parent)) \
|
||||
link = &parent->ITRB.rb_left; \
|
||||
else \
|
||||
else { \
|
||||
link = &parent->ITRB.rb_right; \
|
||||
leftmost = false; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
node->ITSUBTREE = last; \
|
||||
rb_link_node(&node->ITRB, rb_parent, link); \
|
||||
rb_insert_augmented(&node->ITRB, root, &ITPREFIX ## _augment); \
|
||||
rb_insert_augmented_cached(&node->ITRB, root, \
|
||||
leftmost, &ITPREFIX ## _augment); \
|
||||
} \
|
||||
\
|
||||
ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node, struct rb_root *root) \
|
||||
ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node, \
|
||||
struct rb_root_cached *root) \
|
||||
{ \
|
||||
rb_erase_augmented(&node->ITRB, root, &ITPREFIX ## _augment); \
|
||||
rb_erase_augmented_cached(&node->ITRB, root, &ITPREFIX ## _augment); \
|
||||
} \
|
||||
\
|
||||
/* \
|
||||
|
@ -140,15 +146,35 @@ ITPREFIX ## _subtree_search(ITSTRUCT *node, ITTYPE start, ITTYPE last) \
|
|||
} \
|
||||
\
|
||||
ITSTATIC ITSTRUCT * \
|
||||
ITPREFIX ## _iter_first(struct rb_root *root, ITTYPE start, ITTYPE last) \
|
||||
ITPREFIX ## _iter_first(struct rb_root_cached *root, \
|
||||
ITTYPE start, ITTYPE last) \
|
||||
{ \
|
||||
ITSTRUCT *node; \
|
||||
ITSTRUCT *node, *leftmost; \
|
||||
\
|
||||
if (!root->rb_node) \
|
||||
if (!root->rb_root.rb_node) \
|
||||
return NULL; \
|
||||
node = rb_entry(root->rb_node, ITSTRUCT, ITRB); \
|
||||
\
|
||||
/* \
|
||||
* Fastpath range intersection/overlap between A: [a0, a1] and \
|
||||
* B: [b0, b1] is given by: \
|
||||
* \
|
||||
* a0 <= b1 && b0 <= a1 \
|
||||
* \
|
||||
* ... where A holds the lock range and B holds the smallest \
|
||||
* 'start' and largest 'last' in the tree. For the later, we \
|
||||
* rely on the root node, which by augmented interval tree \
|
||||
* property, holds the largest value in its last-in-subtree. \
|
||||
* This allows mitigating some of the tree walk overhead for \
|
||||
* for non-intersecting ranges, maintained and consulted in O(1). \
|
||||
*/ \
|
||||
node = rb_entry(root->rb_root.rb_node, ITSTRUCT, ITRB); \
|
||||
if (node->ITSUBTREE < start) \
|
||||
return NULL; \
|
||||
\
|
||||
leftmost = rb_entry(root->rb_leftmost, ITSTRUCT, ITRB); \
|
||||
if (ITSTART(leftmost) > last) \
|
||||
return NULL; \
|
||||
\
|
||||
return ITPREFIX ## _subtree_search(node, start, last); \
|
||||
} \
|
||||
\
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue