Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jun 2020 00:55:14 +0200
From:      Mateusz Guzik <mjguzik@gmail.com>
To:        Doug Moore <dougm@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r361984 - in head/sys: compat/linuxkpi/common/include/linux sys
Message-ID:  <CAGudoHF8bDuxQ8CS%2Bezq9B9Ro=XYopJHNmAjiZsR7ftJBfO8VA@mail.gmail.com>
In-Reply-To: <202006092019.059KJCLG039099@repo.freebsd.org>
References:  <202006092019.059KJCLG039099@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This broke lint kernels as they define DIAGNOSTIC and fail in kern/subr_stat.c:

/usr/src/sys/kern/subr_stats.c:3384:9: error: implicit declaration of
function 'RB_COLOR' is invalid in C99
[-Werror,-Wimplicit-function-declaration]
                                    RB_COLOR(rbctd64, rblnk),
                                    ^
/usr/src/sys/kern/subr_stats.c:3384:27: error: use of undeclared
identifier 'rblnk'
                                    RB_COLOR(rbctd64, rblnk),


On 6/9/20, Doug Moore <dougm@freebsd.org> wrote:
> Author: dougm
> Date: Tue Jun  9 20:19:11 2020
> New Revision: 361984
> URL: https://svnweb.freebsd.org/changeset/base/361984
>
> Log:
>   To reduce the size of an rb_node, drop the color field. Set the least
>   significant bit in the pointer to the node from its parent to indicate
>   that the node is red. Have the tree rotation macros leave the
>   old-parent/new-child node red and the new-parent/old-child node black.
>
>   This change makes RB_LEFT and RB_RIGHT no longer assignable, and
>   RB_COLOR no longer defined. Any code that modifies the tree or
>   examines a node color would have to be modified after this change.
>
>   Reviewed by:	markj
>   Tested by:	pho
>   Differential Revision:	https://reviews.freebsd.org/D25105
>
> Modified:
>   head/sys/compat/linuxkpi/common/include/linux/rbtree.h
>   head/sys/sys/tree.h
>
> Modified: head/sys/compat/linuxkpi/common/include/linux/rbtree.h
> ==============================================================================
> --- head/sys/compat/linuxkpi/common/include/linux/rbtree.h	Tue Jun  9
> 19:16:49 2020	(r361983)
> +++ head/sys/compat/linuxkpi/common/include/linux/rbtree.h	Tue Jun  9
> 20:19:11 2020	(r361984)
> @@ -57,11 +57,7 @@ RB_HEAD(linux_root, rb_node);
>  RB_PROTOTYPE(linux_root, rb_node, __entry, panic_cmp);
>
>  #define	rb_parent(r)	RB_PARENT(r, __entry)
> -#define	rb_color(r)	RB_COLOR(r, __entry)
> -#define	rb_is_red(r)	(rb_color(r) == RB_RED)
> -#define	rb_is_black(r)	(rb_color(r) == RB_BLACK)
>  #define	rb_set_parent(r, p)	rb_parent((r)) = (p)
> -#define	rb_set_color(r, c)	rb_color((r)) = (c)
>  #define	rb_entry(ptr, type, member)	container_of(ptr, type, member)
>
>  #define RB_EMPTY_ROOT(root)     RB_EMPTY((struct linux_root *)root)
> @@ -82,7 +78,6 @@ rb_link_node(struct rb_node *node, struct rb_node *par
>      struct rb_node **rb_link)
>  {
>  	rb_set_parent(node, parent);
> -	rb_set_color(node, RB_RED);
>  	node->__entry.rbe_left = node->__entry.rbe_right = NULL;
>  	*rb_link = node;
>  }
>
> Modified: head/sys/sys/tree.h
> ==============================================================================
> --- head/sys/sys/tree.h	Tue Jun  9 19:16:49 2020	(r361983)
> +++ head/sys/sys/tree.h	Tue Jun  9 20:19:11 2020	(r361984)
> @@ -307,35 +307,32 @@ struct name {								\
>  	(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_LF(elm, field)		(elm)->field.rbe_left
> +#define RB_RT(elm, field)		(elm)->field.rbe_right
> +#define RB_FLIP(elm)			(*(__uintptr_t *)&(elm) ^= 1)
> +#define RB_FLIP_LF(elm, field)		RB_FLIP(RB_LF(elm, field))
> +#define RB_FLIP_RT(elm, field)		RB_FLIP(RB_RT(elm, field))
> +#define RB_ISRED(elm)			((*(__uintptr_t *)&(elm) & 1) != 0)
> +#define RB_RED_LF(elm, field)		RB_ISRED(RB_LF(elm, field))
> +#define RB_RED_RT(elm, field)		RB_ISRED(RB_RT(elm, field))
> +#define RB_PTR(elm, field)		((__typeof(elm->field.rbe_parent)) \
> +					 ((__uintptr_t)(elm) & ~(__uintptr_t)1))
> +#define RB_LEFT(elm, field)		RB_PTR(RB_LF(elm, field), field)
> +#define RB_RIGHT(elm, field)		RB_PTR(RB_RT(elm, field), field)
>  #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)
>  #define RB_ROOT(head)			(head)->rbh_root
>  #define RB_EMPTY(head)			(RB_ROOT(head) == NULL)
> +#define RB_BOOL				int
> +#define RB_TRUE				1
> +#define RB_FALSE			0
>
> -#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 (/*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)
> -
>  /*
>   * Something to be invoked in a loop at the root of every modified
> subtree,
>   * from the bottom up to the root, to update augmented node data.
> @@ -344,37 +341,42 @@ struct {								\
>  #define RB_AUGMENT(x)	break
>  #endif
>
> +/*
> + * Fix pointers to a parent, and from a parent, as part of rotation.
> + */
> +#define RB_ROTATE_PARENT(head, elm, tmp, field) do {			\
> +	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) == NULL)    \
> +		RB_ROOT(head) = (tmp);					\
> +	else if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))	\
> +		RB_LF(RB_PARENT(elm, field), field) = (tmp);		\
> +	else								\
> +		RB_RT(RB_PARENT(elm, field), field) = (tmp);		\
> +	RB_PARENT(elm, field) = (tmp);					\
> +} while (/*CONSTCOND*/ 0)
> +
> +/*
> + * Rotation makes the descending node red, and the ascending
> + * node not-red.
> + */
>  #define RB_ROTATE_LEFT(head, elm, tmp, field) do {			\
>  	(tmp) = RB_RIGHT(elm, field);					\
> -	if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) {	\
> +	if ((RB_RT(elm, field) = RB_LF(tmp, field)) != NULL) {		\
>  		RB_PARENT(RB_LEFT(tmp, field), field) = (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_ROTATE_PARENT(head, elm, tmp, field);			\
> +	RB_LF(tmp, field) = (elm);					\
> +	RB_FLIP_LF(tmp, field);						\
>  	RB_AUGMENT(elm);						\
>  } while (/*CONSTCOND*/ 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) {	\
> +	if ((RB_LF(elm, field) = RB_RT(tmp, field)) != NULL) {		\
>  		RB_PARENT(RB_RIGHT(tmp, field), field) = (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_ROTATE_PARENT(head, elm, tmp, field);			\
> +	RB_RT(tmp, field) = (elm);					\
> +	RB_FLIP_RT(tmp, field);						\
>  	RB_AUGMENT(elm);						\
>  } while (/*CONSTCOND*/ 0)
>
> @@ -439,110 +441,105 @@ struct {								\
>  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_LF(parent, field);			\
> +		else							\
> +			RB_FLIP_RT(parent, field);			\
> +		if ((gparent = RB_PARENT(parent, field)) == NULL)	\
> +			break;						\
> +		if (RB_RED_LF(gparent, field) &&			\
> +		    RB_RED_RT(gparent, field)) {			\
> +			RB_FLIP_LF(gparent, field);			\
> +			RB_FLIP_RT(gparent, field);			\
> +			elm = gparent;					\
> +			continue;					\
> +		}							\
> +		if (RB_RED_LF(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);\
>  				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);	\
> +		} else if (RB_RED_RT(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);\
>  				parent = elm;				\
> -				elm = tmp;				\
>  			}						\
> -			RB_SET_BLACKRED(parent, gparent, field);	\
> -			RB_ROTATE_LEFT(head, gparent, tmp, field);	\
> +			RB_ROTATE_LEFT(head, gparent, 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 *elm)		\
>  {									\
> -	struct type *elm, *tmp;						\
> -	elm = NULL;							\
> +	struct type *par, *sib, *tmp;					\
> +	RB_BOOL go_left, left_child, red_par;				\
> +	left_child = (RB_LEFT(elm, 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);		\
> +		go_left = left_child;					\
> +		if (go_left ?						\
> +		    !RB_RED_RT(elm, field) :				\
> +		    !RB_RED_LF(elm, field)) {				\
> +			par = RB_PARENT(elm, field);			\
> +			left_child = par != NULL &&			\
> +			    RB_LEFT(par, field) == elm;			\
> +			red_par = left_child ? RB_RED_LF(par, field) :	\
> +			  par == NULL ? RB_TRUE :			\
> +			  RB_RED_RT(par, field);			\
> +		}							\
> +		if (go_left) {						\
> +			if (RB_RED_RT(elm, field)) {			\
> +				red_par = RB_TRUE;			\
> +				RB_ROTATE_LEFT(head, elm, par, field);	\
>  			}						\
> -			if (RB_ISRED(RB_LEFT(tmp, field), field)) {	\
> -				struct type *oleft;			\
> -				oleft = RB_LEFT(tmp, field);		\
> -				RB_COLOR(oleft, field) = RB_BLACK;	\
> -				RB_COLOR(tmp, field) = RB_RED;		\
> -				RB_ROTATE_RIGHT(head, tmp, oleft, field); \
> -				tmp = RB_RIGHT(parent, field);		\
> -			} else if (!RB_ISRED(RB_RIGHT(tmp, field), field)) { \
> -				RB_COLOR(tmp, field) = RB_RED;		\
> -				elm = parent;				\
> -				parent = RB_PARENT(elm, field);		\
> +			sib = RB_RIGHT(elm, field);			\
> +			if (RB_RED_LF(sib, field)) {			\
> +				RB_ROTATE_RIGHT(head, sib, tmp, field);	\
> +				sib = tmp;				\
> +			} else if (!RB_RED_RT(sib, field)) {		\
> +				RB_FLIP_RT(elm, field);			\
> +				elm = par;				\
>  				continue;				\
>  			}						\
> -			if (RB_ISRED(RB_RIGHT(tmp, field), field))	\
> -				RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \
> -			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);				\
> +			if (RB_RED_RT(sib, field))			\
> +				RB_FLIP_RT(sib, field);			\
> +			RB_ROTATE_LEFT(head, elm, sib, field);		\
> +			RB_FLIP_LF(sib, field);				\
>  			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_RED_LF(elm, field)) {			\
> +				red_par = RB_TRUE;			\
> +				RB_ROTATE_RIGHT(head, elm, par, field); \
>  			}						\
> -			if (RB_ISRED(RB_RIGHT(tmp, field), field)) {	\
> -				struct type *oright;			\
> -				oright = RB_RIGHT(tmp, field);		\
> -				RB_COLOR(oright, field) = RB_BLACK;	\
> -				RB_COLOR(tmp, field) = RB_RED;		\
> -				RB_ROTATE_LEFT(head, tmp, oright, field); \
> -				tmp = RB_LEFT(parent, field);		\
> -			} 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(elm, field);			\
> +			if (RB_RED_RT(sib, field)) {			\
> +				RB_ROTATE_LEFT(head, sib, tmp, field);	\
> +				sib = tmp;				\
> +			} else if (!RB_RED_LF(sib, field)) {		\
> +				RB_FLIP_LF(elm, field);			\
> +				elm = par;				\
>  				continue;				\
>  			}						\
> -			if (RB_ISRED(RB_LEFT(tmp, field), field))	\
> -				RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \
> -			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);				\
> +			if (RB_RED_LF(sib, field))			\
> +				RB_FLIP_LF(sib, field);			\
> +			RB_ROTATE_RIGHT(head, elm, sib, field);		\
> +			RB_FLIP_RT(sib, field);				\
>  			break;						\
>  		}							\
> -	} while (!RB_ISRED(elm, field) && parent != NULL);		\
> -	RB_COLOR(elm, field) = RB_BLACK;				\
> +	} while (!red_par);						\
> +	if (par != NULL && red_par) {					\
> +		if (left_child)						\
> +			RB_FLIP_LF(par, field);				\
> +		else							\
> +			RB_FLIP_RT(par, field);				\
> +	}								\
>  }
>
>  #define RB_GENERATE_REMOVE(name, type, field, attr)			\
> @@ -550,12 +547,11 @@ attr struct type *							\
>  name##_RB_REMOVE(struct name *head, struct type *elm)			\
>  {									\
>  	struct type *child, *old, *parent, *parent_old, *right;		\
> -	int color;							\
> +	RB_BOOL old_red, red;						\
>  									\
>  	old = elm;							\
>  	parent_old = 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)						\
> @@ -563,7 +559,8 @@ name##_RB_REMOVE(struct name *head, struct type *elm)	
>  	else {								\
>  		if ((child = RB_LEFT(right, field)) == NULL) {		\
>  			child = RB_RIGHT(right, field);			\
> -			RB_RIGHT(old, field) = child;			\
> +			red = RB_RED_RT(old, field);			\
> +			RB_RT(old, field) = child;			\
>  			parent = elm = right;				\
>  		} else {						\
>  			do						\
> @@ -571,23 +568,31 @@ name##_RB_REMOVE(struct name *head, struct type
> *elm)	
>  			while ((child = RB_LEFT(elm, field)) != NULL);	\
>  			child = RB_RIGHT(elm, field);			\
>  			parent = RB_PARENT(elm, field);			\
> -			RB_LEFT(parent, field) = child;			\
> +			red = RB_RED_LF(parent, field);			\
> +			RB_LF(parent, field) = child;			\
>  			RB_PARENT(RB_RIGHT(old, field), field) = elm;	\
>  		}							\
>  		RB_PARENT(RB_LEFT(old, field), field) = elm;		\
> -		color = RB_COLOR(elm, field);				\
>  		elm->field = old->field;				\
>  	}								\
> -	if (parent_old == NULL)						\
> +	if (parent_old == NULL)	{					\
>  		RB_ROOT(head) = elm;					\
> -	else if (RB_LEFT(parent_old, field) == old)			\
> -		RB_LEFT(parent_old, field) = elm;			\
> -	else								\
> -		RB_RIGHT(parent_old, field) = elm;			\
> -	if (child != NULL) {						\
> +		old_red = RB_FALSE;					\
> +	} else if (RB_LEFT(parent_old, field) == old) {			\
> +		old_red = RB_RED_LF(parent_old, field);			\
> +		RB_LF(parent_old, field) = elm;				\
> +		if (old_red && parent != parent_old)			\
> +			RB_FLIP_LF(parent_old, field);			\
> +	} else {							\
> +		old_red = RB_RED_RT(parent_old, field);			\
> +		RB_RT(parent_old, field) = elm;				\
> +		if (old_red && parent != parent_old)			\
> +			RB_FLIP_RT(parent_old, field);			\
> +	}								\
> +	if (child != NULL)						\
>  		RB_PARENT(child, field) = parent;			\
> -		RB_COLOR(child, field) = RB_BLACK;			\
> -	} else if (color != RB_RED && parent != NULL)			\
> +	else if (parent != NULL &&					\
> +		 (parent != parent_old ? !red : !old_red))		\
>  		name##_RB_REMOVE_COLOR(head, parent);			\
>  	while (parent != NULL) {					\
>  		RB_AUGMENT(parent);					\
> @@ -615,14 +620,14 @@ name##_RB_INSERT(struct name *head, struct type
> *elm)	
>  		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;			\
> -	} else								\
> +	RB_PARENT(elm, field) = parent;					\
> +	RB_LF(elm, field) = RB_RT(elm, field) = NULL;			\
> +	if (parent == NULL)						\
>  		RB_ROOT(head) = elm;					\
> +	else if (comp < 0)						\
> +		RB_LF(parent, field) = elm;				\
> +	else								\
> +		RB_RT(parent, field) = elm;				\
>  	name##_RB_INSERT_COLOR(head, elm);				\
>  	while (elm != NULL) {						\
>  		RB_AUGMENT(elm);					\
>


-- 
Mateusz Guzik <mjguzik gmail.com>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAGudoHF8bDuxQ8CS%2Bezq9B9Ro=XYopJHNmAjiZsR7ftJBfO8VA>