mirror of
https://github.com/opnsense/src.git
synced 2026-06-04 14:26:03 -04:00
iommu_gas: avoid pointless augmentation
iommu_gas_augment_entry updates a map entry element. Invoked as
RB_AUGMENT in RB tree code, it is applied from the point where the
tree is modified, all the way up to the root, and is also applied when
rotation moves a node down in the tree.
There are several opportunities to invoke it less. The automatic
augmentation with every rotation is a mistake. Delaying these
augmentations until RB_INSERT_COLOR or RB_REMOVE_COLOR are finishing
allows the augmentation code to be duplicated less, to work when there
is less register pressure, and to be skipped when conditions allow it:
In the double-rotate case of RB_INSERT_COLOR, augmentation after
the first rotation is not necessary when the element being moved
down the tree becomes a leaf. It was in the tree, and was a leaf,
before the RB_INSERT operation began, and so recomputing
augmentation for it would do nothing.
In the final (possibly only) rotation of RB_REMOVE_COLOR, both the
elements - the one moving up and the one moving down - end up in
the path from the deletion point to the tree root, so there's no
need to augment either of them immediately.
In RB_REMOVE, when the right child of the removed node replaces it
in tree, it began with a null left child. Replacement creates a
non-NULL left child, and then rotation may put a NULL node back in
that place. If that happens, start the augmenting-up-to-root with
the parent of that node, since augmentation would do nothing.
Adjust to avoid these needless augmentations.
Reviewed by: alc
MFC after: 3 weeks
Differential Revision: https://reviews.freebsd.org/D35502
This commit is contained in:
parent
7f46deccbe
commit
7f2ec173e4
1 changed files with 29 additions and 14 deletions
|
|
@ -372,7 +372,7 @@ struct { \
|
|||
#endif
|
||||
|
||||
#define RB_UPDATE_AUGMENT(elm, field) do { \
|
||||
__typeof(elm) rb_update_tmp = (elm); \
|
||||
__typeof(elm) rb_update_tmp = (elm); \
|
||||
do { \
|
||||
RB_AUGMENT(rb_update_tmp); \
|
||||
} while ((rb_update_tmp = RB_PARENT(rb_update_tmp, field)) != NULL); \
|
||||
|
|
@ -395,7 +395,6 @@ struct { \
|
|||
RB_SWAP_CHILD(head, elm, tmp, field); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
RB_SET_PARENT(elm, tmp, field); \
|
||||
RB_AUGMENT(elm); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||
|
|
@ -406,7 +405,6 @@ struct { \
|
|||
RB_SWAP_CHILD(head, elm, tmp, field); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
RB_SET_PARENT(elm, tmp, field); \
|
||||
RB_AUGMENT(elm); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
|
@ -494,7 +492,9 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
|||
elm = parent; \
|
||||
continue; \
|
||||
} \
|
||||
if (!RB_RED_RIGHT(elm, field)) { \
|
||||
if (RB_RED_RIGHT(elm, field)) \
|
||||
child = elm; \
|
||||
else { \
|
||||
/* coverity[uninit_use] */ \
|
||||
RB_ROTATE_LEFT(head, elm, child, field);\
|
||||
if (RB_RED_RIGHT(child, field)) \
|
||||
|
|
@ -503,9 +503,11 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
|||
RB_FLIP_ALL(elm, field); \
|
||||
else \
|
||||
RB_FLIP_LEFT(elm, field); \
|
||||
elm = child; \
|
||||
if ((RB_BITS(child, field) & \
|
||||
RB_RED_MASK) == 0) \
|
||||
elm = child; \
|
||||
} \
|
||||
RB_ROTATE_RIGHT(head, parent, elm, field); \
|
||||
RB_ROTATE_RIGHT(head, parent, child, field); \
|
||||
} else { \
|
||||
if (RB_RED_RIGHT(parent, field)) { \
|
||||
RB_FLIP_RIGHT(parent, field); \
|
||||
|
|
@ -517,7 +519,9 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
|||
elm = parent; \
|
||||
continue; \
|
||||
} \
|
||||
if (!RB_RED_LEFT(elm, field)) { \
|
||||
if (RB_RED_LEFT(elm, field)) \
|
||||
child = elm; \
|
||||
else { \
|
||||
/* coverity[uninit_use] */ \
|
||||
RB_ROTATE_RIGHT(head, elm, child, field);\
|
||||
if (RB_RED_LEFT(child, field)) \
|
||||
|
|
@ -526,11 +530,16 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
|||
RB_FLIP_ALL(elm, field); \
|
||||
else \
|
||||
RB_FLIP_RIGHT(elm, field); \
|
||||
elm = child; \
|
||||
if ((RB_BITS(child, field) & \
|
||||
RB_RED_MASK) == 0) \
|
||||
elm = child; \
|
||||
} \
|
||||
RB_ROTATE_LEFT(head, parent, elm, field); \
|
||||
RB_ROTATE_LEFT(head, parent, child, field); \
|
||||
} \
|
||||
RB_BITS(elm, field) &= ~RB_RED_MASK; \
|
||||
RB_BITS(child, field) &= ~RB_RED_MASK; \
|
||||
if (elm != child) \
|
||||
RB_AUGMENT(elm); \
|
||||
RB_AUGMENT(parent); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
|
@ -589,21 +598,22 @@ name##_RB_REMOVE_COLOR(struct name *head, \
|
|||
else \
|
||||
RB_FLIP_RIGHT(sib, field); \
|
||||
RB_BITS(elm, field) |= RB_RED_MASK; \
|
||||
sib = elm; \
|
||||
break; \
|
||||
case RB_RED_L: \
|
||||
if (RB_STRICT_HST && elm != NULL) { \
|
||||
RB_FLIP_RIGHT(parent, field); \
|
||||
RB_FLIP_ALL(sib, field); \
|
||||
elm = sib; \
|
||||
break; \
|
||||
} \
|
||||
RB_FLIP_LEFT(parent, field); \
|
||||
/* FALLTHROUGH */ \
|
||||
default: \
|
||||
RB_FLIP_RIGHT(sib, field); \
|
||||
elm = sib; \
|
||||
break; \
|
||||
} \
|
||||
RB_ROTATE_LEFT(head, parent, sib, field); \
|
||||
RB_ROTATE_LEFT(head, parent, elm, field); \
|
||||
} else { \
|
||||
if (!RB_RED_RIGHT(parent, field)) { \
|
||||
RB_FLIP_RIGHT(parent, field); \
|
||||
|
|
@ -632,22 +642,25 @@ name##_RB_REMOVE_COLOR(struct name *head, \
|
|||
else \
|
||||
RB_FLIP_LEFT(sib, field); \
|
||||
RB_BITS(elm, field) |= RB_RED_MASK; \
|
||||
sib = elm; \
|
||||
break; \
|
||||
case RB_RED_R: \
|
||||
if (RB_STRICT_HST && elm != NULL) { \
|
||||
RB_FLIP_LEFT(parent, field); \
|
||||
RB_FLIP_ALL(sib, field); \
|
||||
elm = sib; \
|
||||
break; \
|
||||
} \
|
||||
RB_FLIP_RIGHT(parent, field); \
|
||||
/* FALLTHROUGH */ \
|
||||
default: \
|
||||
RB_FLIP_LEFT(sib, field); \
|
||||
elm = sib; \
|
||||
break; \
|
||||
} \
|
||||
RB_ROTATE_RIGHT(head, parent, sib, field); \
|
||||
RB_ROTATE_RIGHT(head, parent, elm, field); \
|
||||
} \
|
||||
if (sib != elm) \
|
||||
RB_AUGMENT(sib); \
|
||||
break; \
|
||||
} while ((parent = RB_PARENT(elm, field)) != NULL); \
|
||||
}
|
||||
|
|
@ -687,6 +700,8 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
|
|||
RB_SET_PARENT(child, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
if (parent == elm && RB_LEFT(parent, field) == NULL) \
|
||||
parent = RB_PARENT(parent, field); \
|
||||
RB_UPDATE_AUGMENT(parent, field); \
|
||||
} \
|
||||
return (old); \
|
||||
|
|
|
|||
Loading…
Reference in a new issue