Linux Audio

Check our new training course

Loading...
v5.14.15
  1/* SPDX-License-Identifier: GPL-2.0-or-later */
  2/*
  3  Red Black Trees
  4  (C) 1999  Andrea Arcangeli <andrea@suse.de>
  5  (C) 2002  David Woodhouse <dwmw2@infradead.org>
  6  (C) 2012  Michel Lespinasse <walken@google.com>
  7
 
 
 
 
 
 
 
 
 
 
 
 
 
  8
  9  linux/include/linux/rbtree_augmented.h
 10*/
 11
 12#ifndef _LINUX_RBTREE_AUGMENTED_H
 13#define _LINUX_RBTREE_AUGMENTED_H
 14
 15#include <linux/compiler.h>
 16#include <linux/rbtree.h>
 17#include <linux/rcupdate.h>
 18
 19/*
 20 * Please note - only struct rb_augment_callbacks and the prototypes for
 21 * rb_insert_augmented() and rb_erase_augmented() are intended to be public.
 22 * The rest are implementation details you are not expected to depend on.
 23 *
 24 * See Documentation/core-api/rbtree.rst for documentation and samples.
 25 */
 26
 27struct rb_augment_callbacks {
 28	void (*propagate)(struct rb_node *node, struct rb_node *stop);
 29	void (*copy)(struct rb_node *old, struct rb_node *new);
 30	void (*rotate)(struct rb_node *old, struct rb_node *new);
 31};
 32
 33extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
 34	void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
 35
 36/*
 37 * Fixup the rbtree and update the augmented information when rebalancing.
 38 *
 39 * On insertion, the user must update the augmented information on the path
 40 * leading to the inserted node, then call rb_link_node() as usual and
 41 * rb_insert_augmented() instead of the usual rb_insert_color() call.
 42 * If rb_insert_augmented() rebalances the rbtree, it will callback into
 43 * a user provided function to update the augmented information on the
 44 * affected subtrees.
 45 */
 46static inline void
 47rb_insert_augmented(struct rb_node *node, struct rb_root *root,
 48		    const struct rb_augment_callbacks *augment)
 49{
 50	__rb_insert_augmented(node, root, augment->rotate);
 51}
 52
 53static inline void
 54rb_insert_augmented_cached(struct rb_node *node,
 55			   struct rb_root_cached *root, bool newleft,
 56			   const struct rb_augment_callbacks *augment)
 57{
 58	if (newleft)
 59		root->rb_leftmost = node;
 60	rb_insert_augmented(node, &root->rb_root, augment);
 61}
 62
 63/*
 64 * Template for declaring augmented rbtree callbacks (generic case)
 65 *
 66 * RBSTATIC:    'static' or empty
 67 * RBNAME:      name of the rb_augment_callbacks structure
 68 * RBSTRUCT:    struct type of the tree nodes
 69 * RBFIELD:     name of struct rb_node field within RBSTRUCT
 70 * RBAUGMENTED: name of field within RBSTRUCT holding data for subtree
 71 * RBCOMPUTE:   name of function that recomputes the RBAUGMENTED data
 72 */
 73
 74#define RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME,				\
 75			     RBSTRUCT, RBFIELD, RBAUGMENTED, RBCOMPUTE)	\
 76static inline void							\
 77RBNAME ## _propagate(struct rb_node *rb, struct rb_node *stop)		\
 78{									\
 79	while (rb != stop) {						\
 80		RBSTRUCT *node = rb_entry(rb, RBSTRUCT, RBFIELD);	\
 81		if (RBCOMPUTE(node, true))				\
 
 82			break;						\
 83		rb = rb_parent(&node->RBFIELD);				\
 
 84	}								\
 85}									\
 86static inline void							\
 87RBNAME ## _copy(struct rb_node *rb_old, struct rb_node *rb_new)		\
 88{									\
 89	RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD);		\
 90	RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD);		\
 91	new->RBAUGMENTED = old->RBAUGMENTED;				\
 92}									\
 93static void								\
 94RBNAME ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new)	\
 95{									\
 96	RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD);		\
 97	RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD);		\
 98	new->RBAUGMENTED = old->RBAUGMENTED;				\
 99	RBCOMPUTE(old, false);						\
100}									\
101RBSTATIC const struct rb_augment_callbacks RBNAME = {			\
102	.propagate = RBNAME ## _propagate,				\
103	.copy = RBNAME ## _copy,					\
104	.rotate = RBNAME ## _rotate					\
105};
106
107/*
108 * Template for declaring augmented rbtree callbacks,
109 * computing RBAUGMENTED scalar as max(RBCOMPUTE(node)) for all subtree nodes.
110 *
111 * RBSTATIC:    'static' or empty
112 * RBNAME:      name of the rb_augment_callbacks structure
113 * RBSTRUCT:    struct type of the tree nodes
114 * RBFIELD:     name of struct rb_node field within RBSTRUCT
115 * RBTYPE:      type of the RBAUGMENTED field
116 * RBAUGMENTED: name of RBTYPE field within RBSTRUCT holding data for subtree
117 * RBCOMPUTE:   name of function that returns the per-node RBTYPE scalar
118 */
119
120#define RB_DECLARE_CALLBACKS_MAX(RBSTATIC, RBNAME, RBSTRUCT, RBFIELD,	      \
121				 RBTYPE, RBAUGMENTED, RBCOMPUTE)	      \
122static inline bool RBNAME ## _compute_max(RBSTRUCT *node, bool exit)	      \
123{									      \
124	RBSTRUCT *child;						      \
125	RBTYPE max = RBCOMPUTE(node);					      \
126	if (node->RBFIELD.rb_left) {					      \
127		child = rb_entry(node->RBFIELD.rb_left, RBSTRUCT, RBFIELD);   \
128		if (child->RBAUGMENTED > max)				      \
129			max = child->RBAUGMENTED;			      \
130	}								      \
131	if (node->RBFIELD.rb_right) {					      \
132		child = rb_entry(node->RBFIELD.rb_right, RBSTRUCT, RBFIELD);  \
133		if (child->RBAUGMENTED > max)				      \
134			max = child->RBAUGMENTED;			      \
135	}								      \
136	if (exit && node->RBAUGMENTED == max)				      \
137		return true;						      \
138	node->RBAUGMENTED = max;					      \
139	return false;							      \
140}									      \
141RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME,					      \
142		     RBSTRUCT, RBFIELD, RBAUGMENTED, RBNAME ## _compute_max)
143
144
145#define	RB_RED		0
146#define	RB_BLACK	1
147
148#define __rb_parent(pc)    ((struct rb_node *)(pc & ~3))
149
150#define __rb_color(pc)     ((pc) & 1)
151#define __rb_is_black(pc)  __rb_color(pc)
152#define __rb_is_red(pc)    (!__rb_color(pc))
153#define rb_color(rb)       __rb_color((rb)->__rb_parent_color)
154#define rb_is_red(rb)      __rb_is_red((rb)->__rb_parent_color)
155#define rb_is_black(rb)    __rb_is_black((rb)->__rb_parent_color)
156
157static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
158{
159	rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
160}
161
162static inline void rb_set_parent_color(struct rb_node *rb,
163				       struct rb_node *p, int color)
164{
165	rb->__rb_parent_color = (unsigned long)p | color;
166}
167
168static inline void
169__rb_change_child(struct rb_node *old, struct rb_node *new,
170		  struct rb_node *parent, struct rb_root *root)
171{
172	if (parent) {
173		if (parent->rb_left == old)
174			WRITE_ONCE(parent->rb_left, new);
175		else
176			WRITE_ONCE(parent->rb_right, new);
177	} else
178		WRITE_ONCE(root->rb_node, new);
179}
180
181static inline void
182__rb_change_child_rcu(struct rb_node *old, struct rb_node *new,
183		      struct rb_node *parent, struct rb_root *root)
184{
185	if (parent) {
186		if (parent->rb_left == old)
187			rcu_assign_pointer(parent->rb_left, new);
188		else
189			rcu_assign_pointer(parent->rb_right, new);
190	} else
191		rcu_assign_pointer(root->rb_node, new);
192}
193
194extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
195	void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
196
197static __always_inline struct rb_node *
198__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
199		     const struct rb_augment_callbacks *augment)
200{
201	struct rb_node *child = node->rb_right;
202	struct rb_node *tmp = node->rb_left;
203	struct rb_node *parent, *rebalance;
204	unsigned long pc;
205
206	if (!tmp) {
207		/*
208		 * Case 1: node to erase has no more than 1 child (easy!)
209		 *
210		 * Note that if there is one child it must be red due to 5)
211		 * and node must be black due to 4). We adjust colors locally
212		 * so as to bypass __rb_erase_color() later on.
213		 */
214		pc = node->__rb_parent_color;
215		parent = __rb_parent(pc);
216		__rb_change_child(node, child, parent, root);
217		if (child) {
218			child->__rb_parent_color = pc;
219			rebalance = NULL;
220		} else
221			rebalance = __rb_is_black(pc) ? parent : NULL;
222		tmp = parent;
223	} else if (!child) {
224		/* Still case 1, but this time the child is node->rb_left */
225		tmp->__rb_parent_color = pc = node->__rb_parent_color;
226		parent = __rb_parent(pc);
227		__rb_change_child(node, tmp, parent, root);
228		rebalance = NULL;
229		tmp = parent;
230	} else {
231		struct rb_node *successor = child, *child2;
232
233		tmp = child->rb_left;
234		if (!tmp) {
235			/*
236			 * Case 2: node's successor is its right child
237			 *
238			 *    (n)          (s)
239			 *    / \          / \
240			 *  (x) (s)  ->  (x) (c)
241			 *        \
242			 *        (c)
243			 */
244			parent = successor;
245			child2 = successor->rb_right;
246
247			augment->copy(node, successor);
248		} else {
249			/*
250			 * Case 3: node's successor is leftmost under
251			 * node's right child subtree
252			 *
253			 *    (n)          (s)
254			 *    / \          / \
255			 *  (x) (y)  ->  (x) (y)
256			 *      /            /
257			 *    (p)          (p)
258			 *    /            /
259			 *  (s)          (c)
260			 *    \
261			 *    (c)
262			 */
263			do {
264				parent = successor;
265				successor = tmp;
266				tmp = tmp->rb_left;
267			} while (tmp);
268			child2 = successor->rb_right;
269			WRITE_ONCE(parent->rb_left, child2);
270			WRITE_ONCE(successor->rb_right, child);
271			rb_set_parent(child, successor);
272
273			augment->copy(node, successor);
274			augment->propagate(parent, successor);
275		}
276
277		tmp = node->rb_left;
278		WRITE_ONCE(successor->rb_left, tmp);
279		rb_set_parent(tmp, successor);
280
281		pc = node->__rb_parent_color;
282		tmp = __rb_parent(pc);
283		__rb_change_child(node, successor, tmp, root);
284
285		if (child2) {
 
286			rb_set_parent_color(child2, parent, RB_BLACK);
287			rebalance = NULL;
288		} else {
289			rebalance = rb_is_black(successor) ? parent : NULL;
 
 
290		}
291		successor->__rb_parent_color = pc;
292		tmp = successor;
293	}
294
295	augment->propagate(tmp, NULL);
296	return rebalance;
297}
298
299static __always_inline void
300rb_erase_augmented(struct rb_node *node, struct rb_root *root,
301		   const struct rb_augment_callbacks *augment)
302{
303	struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
304	if (rebalance)
305		__rb_erase_color(rebalance, root, augment->rotate);
306}
307
308static __always_inline void
309rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root,
310			  const struct rb_augment_callbacks *augment)
311{
312	if (root->rb_leftmost == node)
313		root->rb_leftmost = rb_next(node);
314	rb_erase_augmented(node, &root->rb_root, augment);
315}
316
317#endif	/* _LINUX_RBTREE_AUGMENTED_H */
v4.6
 
  1/*
  2  Red Black Trees
  3  (C) 1999  Andrea Arcangeli <andrea@suse.de>
  4  (C) 2002  David Woodhouse <dwmw2@infradead.org>
  5  (C) 2012  Michel Lespinasse <walken@google.com>
  6
  7  This program is free software; you can redistribute it and/or modify
  8  it under the terms of the GNU General Public License as published by
  9  the Free Software Foundation; either version 2 of the License, or
 10  (at your option) any later version.
 11
 12  This program is distributed in the hope that it will be useful,
 13  but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  GNU General Public License for more details.
 16
 17  You should have received a copy of the GNU General Public License
 18  along with this program; if not, write to the Free Software
 19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 20
 21  linux/include/linux/rbtree_augmented.h
 22*/
 23
 24#ifndef _LINUX_RBTREE_AUGMENTED_H
 25#define _LINUX_RBTREE_AUGMENTED_H
 26
 27#include <linux/compiler.h>
 28#include <linux/rbtree.h>
 
 29
 30/*
 31 * Please note - only struct rb_augment_callbacks and the prototypes for
 32 * rb_insert_augmented() and rb_erase_augmented() are intended to be public.
 33 * The rest are implementation details you are not expected to depend on.
 34 *
 35 * See Documentation/rbtree.txt for documentation and samples.
 36 */
 37
 38struct rb_augment_callbacks {
 39	void (*propagate)(struct rb_node *node, struct rb_node *stop);
 40	void (*copy)(struct rb_node *old, struct rb_node *new);
 41	void (*rotate)(struct rb_node *old, struct rb_node *new);
 42};
 43
 44extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
 45	void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
 
 46/*
 47 * Fixup the rbtree and update the augmented information when rebalancing.
 48 *
 49 * On insertion, the user must update the augmented information on the path
 50 * leading to the inserted node, then call rb_link_node() as usual and
 51 * rb_augment_inserted() instead of the usual rb_insert_color() call.
 52 * If rb_augment_inserted() rebalances the rbtree, it will callback into
 53 * a user provided function to update the augmented information on the
 54 * affected subtrees.
 55 */
 56static inline void
 57rb_insert_augmented(struct rb_node *node, struct rb_root *root,
 58		    const struct rb_augment_callbacks *augment)
 59{
 60	__rb_insert_augmented(node, root, augment->rotate);
 61}
 62
 63#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield,	\
 64			     rbtype, rbaugmented, rbcompute)		\
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 65static inline void							\
 66rbname ## _propagate(struct rb_node *rb, struct rb_node *stop)		\
 67{									\
 68	while (rb != stop) {						\
 69		rbstruct *node = rb_entry(rb, rbstruct, rbfield);	\
 70		rbtype augmented = rbcompute(node);			\
 71		if (node->rbaugmented == augmented)			\
 72			break;						\
 73		node->rbaugmented = augmented;				\
 74		rb = rb_parent(&node->rbfield);				\
 75	}								\
 76}									\
 77static inline void							\
 78rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new)		\
 79{									\
 80	rbstruct *old = rb_entry(rb_old, rbstruct, rbfield);		\
 81	rbstruct *new = rb_entry(rb_new, rbstruct, rbfield);		\
 82	new->rbaugmented = old->rbaugmented;				\
 83}									\
 84static void								\
 85rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new)	\
 86{									\
 87	rbstruct *old = rb_entry(rb_old, rbstruct, rbfield);		\
 88	rbstruct *new = rb_entry(rb_new, rbstruct, rbfield);		\
 89	new->rbaugmented = old->rbaugmented;				\
 90	old->rbaugmented = rbcompute(old);				\
 91}									\
 92rbstatic const struct rb_augment_callbacks rbname = {			\
 93	rbname ## _propagate, rbname ## _copy, rbname ## _rotate	\
 
 
 94};
 95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 96
 97#define	RB_RED		0
 98#define	RB_BLACK	1
 99
100#define __rb_parent(pc)    ((struct rb_node *)(pc & ~3))
101
102#define __rb_color(pc)     ((pc) & 1)
103#define __rb_is_black(pc)  __rb_color(pc)
104#define __rb_is_red(pc)    (!__rb_color(pc))
105#define rb_color(rb)       __rb_color((rb)->__rb_parent_color)
106#define rb_is_red(rb)      __rb_is_red((rb)->__rb_parent_color)
107#define rb_is_black(rb)    __rb_is_black((rb)->__rb_parent_color)
108
109static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
110{
111	rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
112}
113
114static inline void rb_set_parent_color(struct rb_node *rb,
115				       struct rb_node *p, int color)
116{
117	rb->__rb_parent_color = (unsigned long)p | color;
118}
119
120static inline void
121__rb_change_child(struct rb_node *old, struct rb_node *new,
122		  struct rb_node *parent, struct rb_root *root)
123{
124	if (parent) {
125		if (parent->rb_left == old)
126			WRITE_ONCE(parent->rb_left, new);
127		else
128			WRITE_ONCE(parent->rb_right, new);
129	} else
130		WRITE_ONCE(root->rb_node, new);
131}
132
 
 
 
 
 
 
 
 
 
 
 
 
 
133extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
134	void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
135
136static __always_inline struct rb_node *
137__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
138		     const struct rb_augment_callbacks *augment)
139{
140	struct rb_node *child = node->rb_right;
141	struct rb_node *tmp = node->rb_left;
142	struct rb_node *parent, *rebalance;
143	unsigned long pc;
144
145	if (!tmp) {
146		/*
147		 * Case 1: node to erase has no more than 1 child (easy!)
148		 *
149		 * Note that if there is one child it must be red due to 5)
150		 * and node must be black due to 4). We adjust colors locally
151		 * so as to bypass __rb_erase_color() later on.
152		 */
153		pc = node->__rb_parent_color;
154		parent = __rb_parent(pc);
155		__rb_change_child(node, child, parent, root);
156		if (child) {
157			child->__rb_parent_color = pc;
158			rebalance = NULL;
159		} else
160			rebalance = __rb_is_black(pc) ? parent : NULL;
161		tmp = parent;
162	} else if (!child) {
163		/* Still case 1, but this time the child is node->rb_left */
164		tmp->__rb_parent_color = pc = node->__rb_parent_color;
165		parent = __rb_parent(pc);
166		__rb_change_child(node, tmp, parent, root);
167		rebalance = NULL;
168		tmp = parent;
169	} else {
170		struct rb_node *successor = child, *child2;
171
172		tmp = child->rb_left;
173		if (!tmp) {
174			/*
175			 * Case 2: node's successor is its right child
176			 *
177			 *    (n)          (s)
178			 *    / \          / \
179			 *  (x) (s)  ->  (x) (c)
180			 *        \
181			 *        (c)
182			 */
183			parent = successor;
184			child2 = successor->rb_right;
185
186			augment->copy(node, successor);
187		} else {
188			/*
189			 * Case 3: node's successor is leftmost under
190			 * node's right child subtree
191			 *
192			 *    (n)          (s)
193			 *    / \          / \
194			 *  (x) (y)  ->  (x) (y)
195			 *      /            /
196			 *    (p)          (p)
197			 *    /            /
198			 *  (s)          (c)
199			 *    \
200			 *    (c)
201			 */
202			do {
203				parent = successor;
204				successor = tmp;
205				tmp = tmp->rb_left;
206			} while (tmp);
207			child2 = successor->rb_right;
208			WRITE_ONCE(parent->rb_left, child2);
209			WRITE_ONCE(successor->rb_right, child);
210			rb_set_parent(child, successor);
211
212			augment->copy(node, successor);
213			augment->propagate(parent, successor);
214		}
215
216		tmp = node->rb_left;
217		WRITE_ONCE(successor->rb_left, tmp);
218		rb_set_parent(tmp, successor);
219
220		pc = node->__rb_parent_color;
221		tmp = __rb_parent(pc);
222		__rb_change_child(node, successor, tmp, root);
223
224		if (child2) {
225			successor->__rb_parent_color = pc;
226			rb_set_parent_color(child2, parent, RB_BLACK);
227			rebalance = NULL;
228		} else {
229			unsigned long pc2 = successor->__rb_parent_color;
230			successor->__rb_parent_color = pc;
231			rebalance = __rb_is_black(pc2) ? parent : NULL;
232		}
 
233		tmp = successor;
234	}
235
236	augment->propagate(tmp, NULL);
237	return rebalance;
238}
239
240static __always_inline void
241rb_erase_augmented(struct rb_node *node, struct rb_root *root,
242		   const struct rb_augment_callbacks *augment)
243{
244	struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
245	if (rebalance)
246		__rb_erase_color(rebalance, root, augment->rotate);
 
 
 
 
 
 
 
 
 
247}
248
249#endif	/* _LINUX_RBTREE_AUGMENTED_H */