Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107471831
D25418.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D25418.diff
View Options
Index: head/sys/sys/tree.h
===================================================================
--- head/sys/sys/tree.h
+++ head/sys/sys/tree.h
@@ -307,38 +307,60 @@
(root)->rbh_root = NULL; \
} while (/*CONSTCOND*/ 0)
-#define RB_BLACK 0
-#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
- int rbe_color; /* node color */ \
}
#define RB_LEFT(elm, field) (elm)->field.rbe_left
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
-#define RB_PARENT(elm, field) (elm)->field.rbe_parent
-#define RB_COLOR(elm, field) (elm)->field.rbe_color
-#define RB_ISRED(elm, field) ((elm) != NULL && RB_COLOR(elm, field) == RB_RED)
+
+/*
+ * With the expectation that any object of struct type has an
+ * address that is a multiple of 4, and that therefore the
+ * 2 least significant bits of a pointer to struct type are
+ * always zero, this implementation sets those bits to indicate
+ * that the left or right child of the tree node is "red".
+ */
+#define RB_UP(elm, field) (elm)->field.rbe_parent
+#define RB_BITS(elm, field) *(__uintptr_t *)&RB_UP(elm, field)
+#define RB_RED_L (__uintptr_t)1
+#define RB_RED_R (__uintptr_t)2
+#define RB_RED_MASK (__uintptr_t)3
+#define RB_FLIP_LEFT(elm, field) (RB_BITS(elm, field) ^= RB_RED_L)
+#define RB_FLIP_RIGHT(elm, field) (RB_BITS(elm, field) ^= RB_RED_R)
+#define RB_RED_LEFT(elm, field) ((RB_BITS(elm, field) & RB_RED_L) != 0)
+#define RB_RED_RIGHT(elm, field) ((RB_BITS(elm, field) & RB_RED_R) != 0)
+#define RB_PARENT(elm, field) ((__typeof(RB_UP(elm, field))) \
+ (RB_BITS(elm, field) & ~RB_RED_MASK))
+
+/*
+ * This header may appear in user code where 'bool' is not defined,
+ * so it defines its own boolean type to avoid breaking that code.
+ */
+#define RB_BOOL int
+#define RB_TRUE 1
+#define RB_FALSE 0
+
#define RB_ROOT(head) (head)->rbh_root
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET_PARENT(dst, src, field) do { \
- RB_PARENT(dst, field) = src; \
+ RB_BITS(dst, field) &= RB_RED_MASK; \
+ RB_BITS(dst, field) |= (__uintptr_t)src; \
} while (/*CONSTCOND*/ 0)
#define RB_SET(elm, parent, field) do { \
- RB_SET_PARENT(elm, parent, field); \
+ RB_UP(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
- RB_COLOR(elm, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
-#define RB_SET_BLACKRED(black, red, field) do { \
- RB_COLOR(black, field) = RB_BLACK; \
- RB_COLOR(red, field) = RB_RED; \
-} while (/*CONSTCOND*/ 0)
+#define RB_COLOR(elm, field) (RB_PARENT(elm, field) == NULL ? RB_FALSE : \
+ RB_LEFT(RB_PARENT(elm, field), field) == elm ? \
+ RB_RED_LEFT(RB_PARENT(elm, field), field) : \
+ RB_RED_RIGHT(RB_PARENT(elm, field), field))
/*
* Something to be invoked in a loop at the root of every modified subtree,
@@ -442,106 +464,123 @@
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
- struct type *parent, *gparent, *tmp; \
- while (RB_ISRED((parent = RB_PARENT(elm, field)), field)) { \
- gparent = RB_PARENT(parent, field); \
- if (parent == RB_LEFT(gparent, field)) { \
- tmp = RB_RIGHT(gparent, field); \
- if (RB_ISRED(tmp, field)) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
+ struct type *gparent, *parent; \
+ while ((parent = RB_PARENT(elm, field)) != NULL) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_FLIP_LEFT(parent, field); \
+ else \
+ RB_FLIP_RIGHT(parent, field); \
+ if ((gparent = RB_PARENT(parent, field)) == NULL) \
+ break; \
+ if (RB_RED_LEFT(gparent, field) && \
+ RB_RED_RIGHT(gparent, field)) { \
+ RB_FLIP_LEFT(gparent, field); \
+ RB_FLIP_RIGHT(gparent, field); \
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_RED_LEFT(gparent, field) && \
+ parent == RB_LEFT(gparent, field)) { \
if (RB_RIGHT(parent, field) == elm) { \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = parent; \
+ RB_ROTATE_LEFT(head, parent, elm, field);\
+ RB_FLIP_RIGHT(parent, field); \
+ RB_FLIP_LEFT(elm, field); \
parent = elm; \
- elm = tmp; \
} \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_RIGHT(head, gparent, tmp, field); \
- } else { \
- tmp = RB_LEFT(gparent, field); \
- if (RB_ISRED(tmp, field)) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
+ RB_ROTATE_RIGHT(head, gparent, parent, field); \
+ RB_FLIP_LEFT(gparent, field); \
+ RB_FLIP_RIGHT(parent, field); \
+ } else if (RB_RED_RIGHT(gparent, field) && \
+ parent == RB_RIGHT(gparent, field)) { \
if (RB_LEFT(parent, field) == elm) { \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = parent; \
+ RB_ROTATE_RIGHT(head, parent, elm, field);\
+ RB_FLIP_LEFT(parent, field); \
+ RB_FLIP_RIGHT(elm, field); \
parent = elm; \
- elm = tmp; \
} \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_LEFT(head, gparent, tmp, field); \
+ RB_ROTATE_LEFT(head, gparent, parent, field); \
+ RB_FLIP_RIGHT(gparent, field); \
+ RB_FLIP_LEFT(parent, field); \
} \
+ break; \
} \
- RB_COLOR(head->rbh_root, field) = RB_BLACK; \
}
#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
attr void \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent) \
+name##_RB_REMOVE_COLOR(struct name *head, struct type *par) \
{ \
- struct type *elm, *tmp; \
- elm = NULL; \
+ struct type *gpr, *sib, *nec; \
+ RB_BOOL left_elm, left_par, red_gpr; \
+ left_par = (RB_LEFT(par, field) == NULL); \
do { \
- if (RB_LEFT(parent, field) == elm) { \
- tmp = RB_RIGHT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = RB_RIGHT(parent, field); \
+ left_elm = left_par; \
+ if (left_elm ? \
+ !RB_RED_RIGHT(par, field) : \
+ !RB_RED_LEFT(par, field)) { \
+ gpr = RB_PARENT(par, field); \
+ left_par = gpr != NULL && \
+ RB_LEFT(gpr, field) == par; \
+ red_gpr = gpr == NULL ? \
+ RB_TRUE: RB_COLOR(par, field); \
+ } \
+ if (left_elm) { \
+ if (RB_RED_RIGHT(par, field)) { \
+ red_gpr = RB_TRUE; \
+ RB_ROTATE_LEFT(head, par, gpr, field); \
+ RB_FLIP_RIGHT(par, field); \
+ RB_FLIP_LEFT(gpr, field); \
} \
- if (RB_ISRED(RB_RIGHT(tmp, field), field)) \
- RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \
- else if (RB_ISRED(RB_LEFT(tmp, field), field)) { \
- struct type *oleft; \
- RB_ROTATE_RIGHT(head, tmp, oleft, field); \
- RB_COLOR(oleft, field) = RB_BLACK; \
- tmp = oleft; \
+ sib = RB_RIGHT(par, field); \
+ if (RB_RED_RIGHT(sib, field)) { \
+ if (RB_RED_LEFT(sib, field)) { \
+ RB_FLIP_LEFT(sib, field); \
+ RB_FLIP_RIGHT(par, field); \
+ } \
+ RB_FLIP_RIGHT(sib, field); \
+ } else if (RB_RED_LEFT(sib, field)) { \
+ RB_ROTATE_RIGHT(head, sib, nec, field); \
+ RB_FLIP_LEFT(sib, field); \
+ sib = nec; \
} else { \
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
+ RB_FLIP_RIGHT(par, field); \
+ par = gpr; \
continue; \
} \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field); \
- RB_COLOR(parent, field) = RB_BLACK; \
- RB_ROTATE_LEFT(head, parent, tmp, field); \
- elm = RB_ROOT(head); \
- break; \
+ RB_ROTATE_LEFT(head, par, sib, field); \
+ return; \
} else { \
- tmp = RB_LEFT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = RB_LEFT(parent, field); \
+ if (RB_RED_LEFT(par, field)) { \
+ red_gpr = RB_TRUE; \
+ RB_ROTATE_RIGHT(head, par, gpr, field); \
+ RB_FLIP_LEFT(par, field); \
+ RB_FLIP_RIGHT(gpr, field); \
} \
- if (RB_ISRED(RB_LEFT(tmp, field), field)) \
- RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \
- else if (RB_ISRED(RB_RIGHT(tmp, field), field)) { \
- struct type *oright; \
- RB_ROTATE_LEFT(head, tmp, oright, field); \
- RB_COLOR(oright, field) = RB_BLACK; \
- tmp = oright; \
- } else if (!RB_ISRED(RB_LEFT(tmp, field), field)) { \
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
+ sib = RB_LEFT(par, field); \
+ if (RB_RED_LEFT(sib, field)) { \
+ if (RB_RED_RIGHT(sib, field)) { \
+ RB_FLIP_RIGHT(sib, field); \
+ RB_FLIP_LEFT(par, field); \
+ } \
+ RB_FLIP_LEFT(sib, field); \
+ } else if (RB_RED_RIGHT(sib, field)) { \
+ RB_ROTATE_LEFT(head, sib, nec, field); \
+ RB_FLIP_RIGHT(sib, field); \
+ sib = nec; \
+ } else { \
+ RB_FLIP_LEFT(par, field); \
+ par = gpr; \
continue; \
} \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field); \
- RB_COLOR(parent, field) = RB_BLACK; \
- RB_ROTATE_RIGHT(head, parent, tmp, field); \
- elm = RB_ROOT(head); \
- break; \
+ RB_ROTATE_RIGHT(head, par, sib, field); \
+ return; \
} \
- } while (!RB_ISRED(elm, field) && parent != NULL); \
- RB_COLOR(elm, field) = RB_BLACK; \
+ } while (!red_gpr); \
+ if (gpr == NULL); \
+ else if (left_par) \
+ RB_FLIP_LEFT(gpr, field); \
+ else \
+ RB_FLIP_RIGHT(gpr, field); \
}
#define RB_GENERATE_REMOVE(name, type, field, attr) \
@@ -549,12 +588,11 @@
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *old, *parent, *right; \
- int color; \
+ RB_BOOL red; \
\
old = elm; \
parent = RB_PARENT(elm, field); \
right = RB_RIGHT(elm, field); \
- color = RB_COLOR(elm, field); \
if (RB_LEFT(elm, field) == NULL) \
elm = child = right; \
else if (right == NULL) \
@@ -562,6 +600,9 @@
else { \
if ((child = RB_LEFT(right, field)) == NULL) { \
child = RB_RIGHT(right, field); \
+ red = RB_RED_RIGHT(old, field); \
+ if (red) \
+ RB_FLIP_RIGHT(old, field); \
RB_RIGHT(old, field) = child; \
parent = elm = right; \
} else { \
@@ -570,18 +611,27 @@
while ((child = RB_LEFT(elm, field)) != NULL); \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
+ red = RB_RED_LEFT(parent, field); \
+ if (red) \
+ RB_FLIP_LEFT(parent, field); \
RB_LEFT(parent, field) = child; \
RB_SET_PARENT(RB_RIGHT(old, field), elm, field); \
} \
RB_SET_PARENT(RB_LEFT(old, field), elm, field); \
- color = RB_COLOR(elm, field); \
elm->field = old->field; \
} \
+ if (elm == child) { \
+ red = RB_COLOR(old, field); \
+ if (!red); \
+ else if (RB_LEFT(parent, field) == old) \
+ RB_FLIP_LEFT(parent, field); \
+ else \
+ RB_FLIP_RIGHT(parent, field); \
+ } \
RB_SWAP_CHILD(head, old, elm, field); \
- if (child != NULL) { \
+ if (child != NULL) \
RB_SET_PARENT(child, parent, field); \
- RB_COLOR(child, field) = RB_BLACK; \
- } else if (color != RB_RED && parent != NULL) \
+ else if (!red && parent != NULL) \
name##_RB_REMOVE_COLOR(head, parent); \
while (parent != NULL) { \
RB_AUGMENT(parent); \
@@ -610,13 +660,12 @@
return (tmp); \
} \
RB_SET(elm, parent, field); \
- if (parent != NULL) { \
- if (comp < 0) \
- RB_LEFT(parent, field) = elm; \
- else \
- RB_RIGHT(parent, field) = elm; \
- } else \
+ if (parent == NULL) \
RB_ROOT(head) = elm; \
+ else if (comp < 0) \
+ RB_LEFT(parent, field) = elm; \
+ else \
+ RB_RIGHT(parent, field) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
while (elm != NULL) { \
RB_AUGMENT(elm); \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 15, 4:13 PM (13 h, 10 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15812646
Default Alt Text
D25418.diff (12 KB)
Attached To
Mode
D25418: Replace RB color field with tag bits in the parent pointer
Attached
Detach File
Event Timeline
Log In to Comment