#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
#ifndef _SYS_SPINLOCK_H_
#include <sys/spinlock.h>
#endif
void rb_spin_lock(struct spinlock *spin);
void rb_spin_unlock(struct spinlock *spin);
#define SPLAY_HEAD(name, type) \
struct name { \
struct type *sph_root; \
}
#define SPLAY_INITIALIZER(root) \
{ NULL }
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while ( 0)
#define SPLAY_ENTRY(type) \
struct { \
struct type *spe_left; \
struct type *spe_right; \
}
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
#define SPLAY_ROOT(head) (head)->sph_root
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while ( 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while ( 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while ( 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while ( 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while ( 0)
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
void name##_SPLAY(struct name *, struct type *); \
void name##_SPLAY_MINMAX(struct name *, int); \
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
\
static __inline struct type * \
name##_SPLAY_FIND(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
return(NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) \
return (head->sph_root); \
return (NULL); \
} \
\
static __inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
elm = NULL; \
return (elm); \
} \
\
static __inline struct type * \
name##_SPLAY_MIN_MAX(struct name *head, int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
return (SPLAY_ROOT(head)); \
}
#define SPLAY_GENERATE(name, type, field, cmp) \
struct type * \
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
} else { \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if(__comp < 0) { \
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
return (NULL); \
} \
\
struct type * \
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *__tmp; \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
} else { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
name##_SPLAY(head, elm); \
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
} \
return (elm); \
} \
return (NULL); \
} \
\
void \
name##_SPLAY(struct name *head, struct type *elm) \
{ \
struct type __node, *__left, *__right, *__tmp; \
int __comp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0){ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
} \
\
\
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
{ \
struct type __node, *__left, *__right, *__tmp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
}
#define SPLAY_NEGINF -1
#define SPLAY_INF 1
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
#define SPLAY_FOREACH(x, name, head) \
for ((x) = SPLAY_MIN(name, head); \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
#define RB_SCAN_INFO(name, type) \
struct name##_scan_info { \
struct name##_scan_info *link; \
struct type *node; \
}
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; \
struct name##_scan_info *rbh_inprog; \
struct spinlock rbh_spin; \
}
#define RB_INITIALIZER(root) \
{ NULL, NULL, SPINLOCK_INITIALIZER(root.spin, "root.spin") }
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
(root)->rbh_inprog = NULL; \
} while ( 0)
#ifdef _KERNEL
#define RB_SCAN_LOCK(spin) rb_spin_lock(spin)
#define RB_SCAN_UNLOCK(spin) rb_spin_unlock(spin)
#else
#define RB_SCAN_LOCK(spin)
#define RB_SCAN_UNLOCK(spin)
#endif
#define RB_BLACK 0
#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; \
struct type *rbe_right; \
struct type *rbe_parent; \
int rbe_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_ROOT(head) (head)->rbh_root
#define RB_INPROG(head) (head)->rbh_inprog
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while ( 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while ( 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_LEFT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while ( 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_RIGHT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while ( 0)
#define RB_PROTOTYPE(name, type, field, cmp) \
_RB_PROTOTYPE(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
_RB_PROTOTYPE(name, type, field, cmp, __unused static)
#define _RB_PROTOTYPE(name, type, field, cmp, STORQUAL) \
STORQUAL void name##_RB_INSERT_COLOR(struct name *, struct type *); \
STORQUAL void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
STORQUAL struct type *name##_RB_REMOVE(struct name *, struct type *); \
STORQUAL struct type *name##_RB_INSERT(struct name *, struct type *); \
STORQUAL struct type *name##_RB_FIND(struct name *, struct type *); \
STORQUAL int name##_RB_SCAN(struct name *, int (*)(struct type *, void *),\
int (*)(struct type *, void *), void *); \
STORQUAL int name##_RB_SCAN_NOLK(struct name *, int (*)(struct type *, void *),\
int (*)(struct type *, void *), void *); \
STORQUAL struct type *name##_RB_NEXT(struct type *); \
STORQUAL struct type *name##_RB_PREV(struct type *); \
STORQUAL struct type *name##_RB_MINMAX(struct name *, int); \
RB_SCAN_INFO(name, type) \
#define RB_PROTOTYPE2(name, type, field, cmp, datatype) \
RB_PROTOTYPE(name, type, field, cmp); \
struct type *name##_RB_LOOKUP(struct name *, datatype); \
struct type *name##_RB_LOOKUP_REL(struct name *, datatype, struct type *) \
#define RB_PROTOTYPE3(name, type, field, cmp, datatype) \
RB_PROTOTYPE2(name, type, field, cmp, datatype); \
struct type *name##_RB_RLOOKUP(struct name *, datatype) \
#define RB_PROTOTYPE4(name, type, field, cmp, datatype) \
RB_PROTOTYPE2(name, type, field, cmp, datatype); \
struct type *name##_RB_RLOOKUP(struct name *, datatype) \
#define RB_PROTOTYPEX(name, ext, type, field, cmp, datatype) \
RB_PROTOTYPE(name, type, field, cmp); \
struct type *name##_RB_LOOKUP_##ext (struct name *, datatype) \
#define RB_GENERATE(name, type, field, cmp) \
_RB_GENERATE(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
_RB_GENERATE(name, type, field, cmp, __unused static)
#define _RB_GENERATE(name, type, field, cmp, STORQUAL) \
STORQUAL void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
} else { \
tmp = RB_LEFT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_LEFT(head, gparent, tmp, field); \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
} \
\
STORQUAL void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, \
struct type *elm) \
{ \
struct type *tmp; \
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
elm != RB_ROOT(head)) { \
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); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
tmp = RB_RIGHT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_RIGHT(tmp, field)) \
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_LEFT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} 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_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
tmp = RB_LEFT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_LEFT(tmp, field)) \
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_RIGHT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} \
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
} \
\
STORQUAL struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old; \
struct name##_scan_info *inprog; \
int color; \
\
for (inprog = RB_INPROG(head); inprog; inprog = inprog->link) { \
if (inprog->node == elm) \
inprog->node = RB_NEXT(name, head, elm); \
} \
\
old = elm; \
if (RB_LEFT(elm, field) == NULL) \
child = RB_RIGHT(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \
child = RB_LEFT(elm, field); \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field)) != NULL) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
if (RB_PARENT(elm, field) == old) \
parent = elm; \
(elm)->field = (old)->field; \
if (RB_PARENT(old, field)) { \
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
RB_LEFT(RB_PARENT(old, field), field) = elm;\
else \
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
RB_ROOT(head) = elm; \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
if (parent) { \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} \
goto color; \
} \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
color: \
if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
\
\
STORQUAL struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
struct type *parent = NULL; \
int comp = 0; \
tmp = RB_ROOT(head); \
while (tmp) { \
parent = tmp; \
comp = (cmp)(elm, parent); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return(tmp); \
} \
RB_SET(elm, parent, field); \
if (parent != NULL) { \
if (comp < 0) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
} \
\
\
STORQUAL struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (NULL); \
} \
\
\
static int \
name##_SCANCMP_ALL(struct type *type __unused, void *data __unused) \
{ \
return(0); \
} \
\
static __inline void \
name##_scan_info_link(struct name##_scan_info *scan, struct name *head) \
{ \
RB_SCAN_LOCK(&head->rbh_spin); \
scan->link = RB_INPROG(head); \
RB_INPROG(head) = scan; \
RB_SCAN_UNLOCK(&head->rbh_spin); \
} \
\
static __inline void \
name##_scan_info_done(struct name##_scan_info *scan, struct name *head) \
{ \
struct name##_scan_info **infopp; \
\
RB_SCAN_LOCK(&head->rbh_spin); \
infopp = &RB_INPROG(head); \
while (*infopp != scan) \
infopp = &(*infopp)->link; \
*infopp = scan->link; \
RB_SCAN_UNLOCK(&head->rbh_spin); \
} \
\
static __inline int \
_##name##_RB_SCAN(struct name *head, \
int (*scancmp)(struct type *, void *), \
int (*callback)(struct type *, void *), \
void *data, int uselock) \
{ \
struct name##_scan_info info; \
struct type *best; \
struct type *tmp; \
int count; \
int comp; \
\
if (scancmp == NULL) \
scancmp = name##_SCANCMP_ALL; \
\
\
tmp = RB_ROOT(head); \
best = NULL; \
while (tmp) { \
comp = scancmp(tmp, data); \
if (comp < 0) { \
tmp = RB_RIGHT(tmp, field); \
} else if (comp > 0) { \
tmp = RB_LEFT(tmp, field); \
} else { \
best = tmp; \
if (RB_LEFT(tmp, field) == NULL) \
break; \
tmp = RB_LEFT(tmp, field); \
} \
} \
count = 0; \
if (best) { \
info.node = RB_NEXT(name, head, best); \
if (uselock) \
name##_scan_info_link(&info, head); \
while ((comp = callback(best, data)) >= 0) { \
count += comp; \
best = info.node; \
if (best == NULL || scancmp(best, data) != 0) \
break; \
info.node = RB_NEXT(name, head, best); \
} \
if (uselock) \
name##_scan_info_done(&info, head); \
if (comp < 0) \
count = comp; \
} \
return(count); \
} \
\
STORQUAL int \
name##_RB_SCAN(struct name *head, \
int (*scancmp)(struct type *, void *), \
int (*callback)(struct type *, void *), \
void *data) \
{ \
return _##name##_RB_SCAN(head, scancmp, callback, data, 1); \
} \
\
STORQUAL int \
name##_RB_SCAN_NOLK(struct name *head, \
int (*scancmp)(struct type *, void *), \
int (*callback)(struct type *, void *), \
void *data) \
{ \
return _##name##_RB_SCAN(head, scancmp, callback, data, 0); \
} \
\
\
STORQUAL struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
elm = RB_RIGHT(elm, field); \
while (RB_LEFT(elm, field)) \
elm = RB_LEFT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
\
STORQUAL struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
STORQUAL struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *parent = NULL; \
while (tmp) { \
parent = tmp; \
if (val < 0) \
tmp = RB_LEFT(tmp, field); \
else \
tmp = RB_RIGHT(tmp, field); \
} \
return (parent); \
}
#define RB_GENERATE2(name, type, field, cmp, datatype, indexfield) \
RB_GENERATE(name, type, field, cmp) \
\
struct type * \
name##_RB_LOOKUP(struct name *head, datatype value) \
{ \
struct type *tmp; \
\
tmp = RB_ROOT(head); \
while (tmp) { \
if (value > tmp->indexfield) \
tmp = RB_RIGHT(tmp, field); \
else if (value < tmp->indexfield) \
tmp = RB_LEFT(tmp, field); \
else \
return(tmp); \
} \
return(NULL); \
} \
\
struct type * \
name##_RB_LOOKUP_REL(struct name *head, datatype value, struct type *rel)\
{ \
struct type *tmp; \
\
if (value == rel->indexfield - 1) { \
tmp = name##_RB_PREV(rel); \
if (tmp && value != tmp->indexfield) \
tmp = NULL; \
return tmp; \
} \
if (value == rel->indexfield + 1) { \
tmp = name##_RB_NEXT(rel); \
if (tmp && value != tmp->indexfield) \
tmp = NULL; \
return tmp; \
} \
\
tmp = RB_ROOT(head); \
while (tmp) { \
if (value > tmp->indexfield) \
tmp = RB_RIGHT(tmp, field); \
else if (value < tmp->indexfield) \
tmp = RB_LEFT(tmp, field); \
else \
return(tmp); \
} \
return(NULL); \
} \
#define RB_GENERATE3(name, type, field, cmp, datatype, begfield, endfield) \
RB_GENERATE2(name, type, field, cmp, datatype, begfield) \
\
struct type * \
name##_RB_RLOOKUP(struct name *head, datatype value) \
{ \
struct type *tmp; \
\
tmp = RB_ROOT(head); \
while (tmp) { \
if (value >= tmp->begfield && value <= tmp->endfield) \
return(tmp); \
if (value > tmp->begfield) \
tmp = RB_RIGHT(tmp, field); \
else \
tmp = RB_LEFT(tmp, field); \
} \
return(NULL); \
} \
#define RB_GENERATE4(name, type, field, cmp, datatype, begfield, sizefield) \
RB_GENERATE2(name, type, field, cmp, datatype, begfield) \
\
struct type * \
name##_RB_RLOOKUP(struct name *head, datatype value) \
{ \
struct type *tmp; \
\
tmp = RB_ROOT(head); \
while (tmp) { \
if (value >= tmp->begfield && \
value < tmp->begfield + tmp->sizefield) { \
return(tmp); \
} \
if (value > tmp->begfield) \
tmp = RB_RIGHT(tmp, field); \
else \
tmp = RB_LEFT(tmp, field); \
} \
return(NULL); \
} \
#define RB_GENERATE_XLOOKUP(name, ext, type, field, xcmp, datatype) \
_RB_GENERATE_XLOOKUP(name, ext, type, field, xcmp, datatype,)
#define RB_GENERATE_XLOOKUP_STATIC(name, ext, type, field, xcmp, datatype) \
_RB_GENERATE_XLOOKUP(name, ext, type, field, xcmp, datatype, __unused static)
#define _RB_GENERATE_XLOOKUP(name, ext, type, field, xcmp, datatype, STORQUAL)\
\
STORQUAL struct type * \
name##_RB_LOOKUP_##ext (struct name *head, datatype value) \
{ \
struct type *tmp; \
int r; \
\
tmp = RB_ROOT(head); \
while (tmp) { \
r = xcmp(value, tmp); \
if (r == 0) \
return(tmp); \
if (r > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
tmp = RB_LEFT(tmp, field); \
} \
return(NULL); \
} \
#define RB_NEGINF -1
#define RB_INF 1
#define RB_INSERT(name, root, elm) name##_RB_INSERT(root, elm)
#define RB_REMOVE(name, root, elm) name##_RB_REMOVE(root, elm)
#define RB_FIND(name, root, elm) name##_RB_FIND(root, elm)
#define RB_LOOKUP(name, root, value) name##_RB_LOOKUP(root, value)
#define RB_RLOOKUP(name, root, value) name##_RB_RLOOKUP(root, value)
#define RB_SCAN(name, root, cmp, callback, data) \
name##_RB_SCAN(root, cmp, callback, data)
#define RB_SCAN_NOLK(name, root, cmp, callback, data) \
name##_RB_SCAN_NOLK(root, cmp, callback, data)
#define RB_FIRST(name, root) name##_RB_MINMAX(root, RB_NEGINF)
#define RB_NEXT(name, root, elm) name##_RB_NEXT(elm)
#define RB_PREV(name, root, elm) name##_RB_PREV(elm)
#define RB_MIN(name, root) name##_RB_MINMAX(root, RB_NEGINF)
#define RB_MAX(name, root) name##_RB_MINMAX(root, RB_INF)
#define RB_FOREACH(x, name, head) \
for ((x) = RB_MIN(name, head); \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#endif