Blame view

lib/rbtree.c 16.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
    Red Black Trees
    (C) 1999  Andrea Arcangeli <andrea@suse.de>
    (C) 2002  David Woodhouse <dwmw2@infradead.org>
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
5
    (C) 2012  Michel Lespinasse <walken@google.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
    linux/lib/rbtree.c
  */
9c079add0   Michel Lespinasse   rbtree: move augm...
22
  #include <linux/rbtree_augmented.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
23
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

5bc9188aa   Michel Lespinasse   rbtree: low level...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  /*
   * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree
   *
   *  1) A node is either red or black
   *  2) The root is black
   *  3) All leaves (NULL) are black
   *  4) Both children of every red node are black
   *  5) Every simple path from root to leaves contains the same number
   *     of black nodes.
   *
   *  4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two
   *  consecutive red nodes in a path and every red node is therefore followed by
   *  a black. So if B is the number of black nodes on every simple path (as per
   *  5), then the longest possible path due to 4 is 2B.
   *
   *  We shall indicate color with case, where black nodes are uppercase and red
6280d2356   Michel Lespinasse   rbtree: low level...
41
42
   *  nodes will be lowercase. Unknown color nodes shall be drawn as red within
   *  parentheses and have some accompanying text comment.
5bc9188aa   Michel Lespinasse   rbtree: low level...
43
   */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  /*
   * Notes on lockless lookups:
   *
   * All stores to the tree structure (rb_left and rb_right) must be done using
   * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the
   * tree structure as seen in program order.
   *
   * These two requirements will allow lockless iteration of the tree -- not
   * correct iteration mind you, tree rotations are not atomic so a lookup might
   * miss entire subtrees.
   *
   * But they do guarantee that any such traversal will only see valid elements
   * and that it will indeed complete -- does not get stuck in a loop.
   *
   * It also guarantees that if the lookup returns an element it is the 'correct'
   * one. But not returning an element does _NOT_ mean it's not present.
   *
   * NOTE:
   *
   * Stores to __rb_parent_color are not important for simple lookups so those
   * are left undone as of now. Nor did I check for loops involving parent
   * pointers.
   */
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
67
68
69
70
  static inline void rb_set_black(struct rb_node *rb)
  {
  	rb->__rb_parent_color |= RB_BLACK;
  }
5bc9188aa   Michel Lespinasse   rbtree: low level...
71
72
73
74
  static inline struct rb_node *rb_red_parent(struct rb_node *red)
  {
  	return (struct rb_node *)red->__rb_parent_color;
  }
5bc9188aa   Michel Lespinasse   rbtree: low level...
75
76
77
78
79
80
81
82
83
84
85
86
  /*
   * Helper function for rotations:
   * - old's parent and color get assigned to new
   * - old gets assigned new as a parent and 'color' as a color.
   */
  static inline void
  __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
  			struct rb_root *root, int color)
  {
  	struct rb_node *parent = rb_parent(old);
  	new->__rb_parent_color = old->__rb_parent_color;
  	rb_set_parent_color(old, new, color);
7abc704ae   Michel Lespinasse   rbtree: add __rb_...
87
  	__rb_change_child(old, new, parent, root);
5bc9188aa   Michel Lespinasse   rbtree: low level...
88
  }
14b94af0b   Michel Lespinasse   rbtree: faster au...
89
90
91
  static __always_inline void
  __rb_insert(struct rb_node *node, struct rb_root *root,
  	    void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  {
5bc9188aa   Michel Lespinasse   rbtree: low level...
93
  	struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94

6d58452dc   Michel Lespinasse   rbtree: adjust ro...
95
96
97
98
99
100
101
102
  	while (true) {
  		/*
  		 * Loop invariant: node is red
  		 *
  		 * If there is a black parent, we are done.
  		 * Otherwise, take some corrective action as we don't
  		 * want a red root or two consecutive red nodes.
  		 */
6d58452dc   Michel Lespinasse   rbtree: adjust ro...
103
  		if (!parent) {
5bc9188aa   Michel Lespinasse   rbtree: low level...
104
  			rb_set_parent_color(node, NULL, RB_BLACK);
6d58452dc   Michel Lespinasse   rbtree: adjust ro...
105
106
107
  			break;
  		} else if (rb_is_black(parent))
  			break;
5bc9188aa   Michel Lespinasse   rbtree: low level...
108
  		gparent = rb_red_parent(parent);
59633abf3   Michel Lespinasse   rbtree: optimize ...
109
110
  		tmp = gparent->rb_right;
  		if (parent != tmp) {	/* parent == gparent->rb_left */
5bc9188aa   Michel Lespinasse   rbtree: low level...
111
112
113
114
115
116
117
118
  			if (tmp && rb_is_red(tmp)) {
  				/*
  				 * Case 1 - color flips
  				 *
  				 *       G            g
  				 *      / \          / \
  				 *     p   u  -->   P   U
  				 *    /            /
1b9c53e84   Wei Yang   lib/rbtree.c: fix...
119
  				 *   n            n
5bc9188aa   Michel Lespinasse   rbtree: low level...
120
121
122
123
124
125
126
127
128
129
130
  				 *
  				 * However, since g's parent might be red, and
  				 * 4) does not allow this, we need to recurse
  				 * at g.
  				 */
  				rb_set_parent_color(tmp, gparent, RB_BLACK);
  				rb_set_parent_color(parent, gparent, RB_BLACK);
  				node = gparent;
  				parent = rb_parent(node);
  				rb_set_parent_color(node, parent, RB_RED);
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  			}
59633abf3   Michel Lespinasse   rbtree: optimize ...
132
133
  			tmp = parent->rb_right;
  			if (node == tmp) {
5bc9188aa   Michel Lespinasse   rbtree: low level...
134
135
136
137
138
139
140
141
142
143
144
145
  				/*
  				 * Case 2 - left rotate at parent
  				 *
  				 *      G             G
  				 *     / \           / \
  				 *    p   U  -->    n   U
  				 *     \           /
  				 *      n         p
  				 *
  				 * This still leaves us in violation of 4), the
  				 * continuation into Case 3 will fix that.
  				 */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
146
147
148
  				tmp = node->rb_left;
  				WRITE_ONCE(parent->rb_right, tmp);
  				WRITE_ONCE(node->rb_left, parent);
5bc9188aa   Michel Lespinasse   rbtree: low level...
149
150
151
152
  				if (tmp)
  					rb_set_parent_color(tmp, parent,
  							    RB_BLACK);
  				rb_set_parent_color(parent, node, RB_RED);
14b94af0b   Michel Lespinasse   rbtree: faster au...
153
  				augment_rotate(parent, node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  				parent = node;
59633abf3   Michel Lespinasse   rbtree: optimize ...
155
  				tmp = node->rb_right;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  			}
5bc9188aa   Michel Lespinasse   rbtree: low level...
157
158
159
160
161
162
163
164
165
  			/*
  			 * Case 3 - right rotate at gparent
  			 *
  			 *        G           P
  			 *       / \         / \
  			 *      p   U  -->  n   g
  			 *     /                 \
  			 *    n                   U
  			 */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
166
167
  			WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */
  			WRITE_ONCE(parent->rb_right, gparent);
5bc9188aa   Michel Lespinasse   rbtree: low level...
168
169
170
  			if (tmp)
  				rb_set_parent_color(tmp, gparent, RB_BLACK);
  			__rb_rotate_set_parents(gparent, parent, root, RB_RED);
14b94af0b   Michel Lespinasse   rbtree: faster au...
171
  			augment_rotate(gparent, parent);
1f0528653   Michel Lespinasse   rbtree: break out...
172
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  		} else {
5bc9188aa   Michel Lespinasse   rbtree: low level...
174
175
176
177
178
179
180
181
182
  			tmp = gparent->rb_left;
  			if (tmp && rb_is_red(tmp)) {
  				/* Case 1 - color flips */
  				rb_set_parent_color(tmp, gparent, RB_BLACK);
  				rb_set_parent_color(parent, gparent, RB_BLACK);
  				node = gparent;
  				parent = rb_parent(node);
  				rb_set_parent_color(node, parent, RB_RED);
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  			}
59633abf3   Michel Lespinasse   rbtree: optimize ...
184
185
  			tmp = parent->rb_left;
  			if (node == tmp) {
5bc9188aa   Michel Lespinasse   rbtree: low level...
186
  				/* Case 2 - right rotate at parent */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
187
188
189
  				tmp = node->rb_right;
  				WRITE_ONCE(parent->rb_left, tmp);
  				WRITE_ONCE(node->rb_right, parent);
5bc9188aa   Michel Lespinasse   rbtree: low level...
190
191
192
193
  				if (tmp)
  					rb_set_parent_color(tmp, parent,
  							    RB_BLACK);
  				rb_set_parent_color(parent, node, RB_RED);
14b94af0b   Michel Lespinasse   rbtree: faster au...
194
  				augment_rotate(parent, node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  				parent = node;
59633abf3   Michel Lespinasse   rbtree: optimize ...
196
  				tmp = node->rb_left;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  			}
5bc9188aa   Michel Lespinasse   rbtree: low level...
198
  			/* Case 3 - left rotate at gparent */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
199
200
  			WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */
  			WRITE_ONCE(parent->rb_left, gparent);
5bc9188aa   Michel Lespinasse   rbtree: low level...
201
202
203
  			if (tmp)
  				rb_set_parent_color(tmp, gparent, RB_BLACK);
  			__rb_rotate_set_parents(gparent, parent, root, RB_RED);
14b94af0b   Michel Lespinasse   rbtree: faster au...
204
  			augment_rotate(gparent, parent);
1f0528653   Michel Lespinasse   rbtree: break out...
205
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209

3cb7a5634   Michel Lespinasse   lib/rbtree.c: avo...
210
211
212
213
214
215
  /*
   * Inline version for rb_erase() use - we want to be able to inline
   * and eliminate the dummy_rotate callback there
   */
  static __always_inline void
  ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
9c079add0   Michel Lespinasse   rbtree: move augm...
216
  	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  {
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
218
  	struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

d6ff12739   Michel Lespinasse   rbtree: adjust no...
220
221
  	while (true) {
  		/*
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
222
223
224
225
226
  		 * Loop invariants:
  		 * - node is black (or NULL on first iteration)
  		 * - node is not the root (parent is not NULL)
  		 * - All leaf paths going through parent and node have a
  		 *   black node count that is 1 lower than other leaf paths.
d6ff12739   Michel Lespinasse   rbtree: adjust no...
227
  		 */
59633abf3   Michel Lespinasse   rbtree: optimize ...
228
229
  		sibling = parent->rb_right;
  		if (node != sibling) {	/* node == parent->rb_left */
6280d2356   Michel Lespinasse   rbtree: low level...
230
231
232
233
234
235
236
237
238
239
  			if (rb_is_red(sibling)) {
  				/*
  				 * Case 1 - left rotate at parent
  				 *
  				 *     P               S
  				 *    / \             / \
  				 *   N   s    -->    p   Sr
  				 *      / \         / \
  				 *     Sl  Sr      N   Sl
  				 */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
240
241
242
  				tmp1 = sibling->rb_left;
  				WRITE_ONCE(parent->rb_right, tmp1);
  				WRITE_ONCE(sibling->rb_left, parent);
6280d2356   Michel Lespinasse   rbtree: low level...
243
244
245
  				rb_set_parent_color(tmp1, parent, RB_BLACK);
  				__rb_rotate_set_parents(parent, sibling, root,
  							RB_RED);
9c079add0   Michel Lespinasse   rbtree: move augm...
246
  				augment_rotate(parent, sibling);
6280d2356   Michel Lespinasse   rbtree: low level...
247
  				sibling = tmp1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  			}
6280d2356   Michel Lespinasse   rbtree: low level...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  			tmp1 = sibling->rb_right;
  			if (!tmp1 || rb_is_black(tmp1)) {
  				tmp2 = sibling->rb_left;
  				if (!tmp2 || rb_is_black(tmp2)) {
  					/*
  					 * Case 2 - sibling color flip
  					 * (p could be either color here)
  					 *
  					 *    (p)           (p)
  					 *    / \           / \
  					 *   N   S    -->  N   s
  					 *      / \           / \
  					 *     Sl  Sr        Sl  Sr
  					 *
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
263
264
265
266
  					 * This leaves us violating 5) which
  					 * can be fixed by flipping p to black
  					 * if it was red, or by recursing at p.
  					 * p is red when coming from Case 1.
6280d2356   Michel Lespinasse   rbtree: low level...
267
268
269
  					 */
  					rb_set_parent_color(sibling, parent,
  							    RB_RED);
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
270
271
272
273
274
275
276
277
278
  					if (rb_is_red(parent))
  						rb_set_black(parent);
  					else {
  						node = parent;
  						parent = rb_parent(node);
  						if (parent)
  							continue;
  					}
  					break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  				}
6280d2356   Michel Lespinasse   rbtree: low level...
280
281
282
283
284
285
286
287
288
289
290
291
  				/*
  				 * Case 3 - right rotate at sibling
  				 * (p could be either color here)
  				 *
  				 *   (p)           (p)
  				 *   / \           / \
  				 *  N   S    -->  N   Sl
  				 *     / \             \
  				 *    sl  Sr            s
  				 *                       \
  				 *                        Sr
  				 */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
292
293
294
295
  				tmp1 = tmp2->rb_right;
  				WRITE_ONCE(sibling->rb_left, tmp1);
  				WRITE_ONCE(tmp2->rb_right, sibling);
  				WRITE_ONCE(parent->rb_right, tmp2);
6280d2356   Michel Lespinasse   rbtree: low level...
296
297
298
  				if (tmp1)
  					rb_set_parent_color(tmp1, sibling,
  							    RB_BLACK);
9c079add0   Michel Lespinasse   rbtree: move augm...
299
  				augment_rotate(sibling, tmp2);
6280d2356   Michel Lespinasse   rbtree: low level...
300
301
  				tmp1 = sibling;
  				sibling = tmp2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  			}
6280d2356   Michel Lespinasse   rbtree: low level...
303
304
305
306
307
308
309
310
311
312
313
314
  			/*
  			 * Case 4 - left rotate at parent + color flips
  			 * (p and sl could be either color here.
  			 *  After rotation, p becomes black, s acquires
  			 *  p's color, and sl keeps its color)
  			 *
  			 *      (p)             (s)
  			 *      / \             / \
  			 *     N   S     -->   P   Sr
  			 *        / \         / \
  			 *      (sl) sr      N  (sl)
  			 */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
315
316
317
  			tmp2 = sibling->rb_left;
  			WRITE_ONCE(parent->rb_right, tmp2);
  			WRITE_ONCE(sibling->rb_left, parent);
6280d2356   Michel Lespinasse   rbtree: low level...
318
319
320
321
322
  			rb_set_parent_color(tmp1, sibling, RB_BLACK);
  			if (tmp2)
  				rb_set_parent(tmp2, parent);
  			__rb_rotate_set_parents(parent, sibling, root,
  						RB_BLACK);
9c079add0   Michel Lespinasse   rbtree: move augm...
323
  			augment_rotate(parent, sibling);
e125d1471   Michel Lespinasse   rbtree: optimize ...
324
  			break;
d6ff12739   Michel Lespinasse   rbtree: adjust no...
325
  		} else {
6280d2356   Michel Lespinasse   rbtree: low level...
326
327
328
  			sibling = parent->rb_left;
  			if (rb_is_red(sibling)) {
  				/* Case 1 - right rotate at parent */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
329
330
331
  				tmp1 = sibling->rb_right;
  				WRITE_ONCE(parent->rb_left, tmp1);
  				WRITE_ONCE(sibling->rb_right, parent);
6280d2356   Michel Lespinasse   rbtree: low level...
332
333
334
  				rb_set_parent_color(tmp1, parent, RB_BLACK);
  				__rb_rotate_set_parents(parent, sibling, root,
  							RB_RED);
9c079add0   Michel Lespinasse   rbtree: move augm...
335
  				augment_rotate(parent, sibling);
6280d2356   Michel Lespinasse   rbtree: low level...
336
  				sibling = tmp1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  			}
6280d2356   Michel Lespinasse   rbtree: low level...
338
339
340
341
342
343
344
  			tmp1 = sibling->rb_left;
  			if (!tmp1 || rb_is_black(tmp1)) {
  				tmp2 = sibling->rb_right;
  				if (!tmp2 || rb_is_black(tmp2)) {
  					/* Case 2 - sibling color flip */
  					rb_set_parent_color(sibling, parent,
  							    RB_RED);
46b6135a7   Michel Lespinasse   rbtree: handle 1-...
345
346
347
348
349
350
351
352
353
  					if (rb_is_red(parent))
  						rb_set_black(parent);
  					else {
  						node = parent;
  						parent = rb_parent(node);
  						if (parent)
  							continue;
  					}
  					break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
  				}
6280d2356   Michel Lespinasse   rbtree: low level...
355
  				/* Case 3 - right rotate at sibling */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
356
357
358
359
  				tmp1 = tmp2->rb_left;
  				WRITE_ONCE(sibling->rb_right, tmp1);
  				WRITE_ONCE(tmp2->rb_left, sibling);
  				WRITE_ONCE(parent->rb_left, tmp2);
6280d2356   Michel Lespinasse   rbtree: low level...
360
361
362
  				if (tmp1)
  					rb_set_parent_color(tmp1, sibling,
  							    RB_BLACK);
9c079add0   Michel Lespinasse   rbtree: move augm...
363
  				augment_rotate(sibling, tmp2);
6280d2356   Michel Lespinasse   rbtree: low level...
364
365
  				tmp1 = sibling;
  				sibling = tmp2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  			}
6280d2356   Michel Lespinasse   rbtree: low level...
367
  			/* Case 4 - left rotate at parent + color flips */
d72da4a4d   Peter Zijlstra   rbtree: Make lock...
368
369
370
  			tmp2 = sibling->rb_right;
  			WRITE_ONCE(parent->rb_left, tmp2);
  			WRITE_ONCE(sibling->rb_right, parent);
6280d2356   Michel Lespinasse   rbtree: low level...
371
372
373
374
375
  			rb_set_parent_color(tmp1, sibling, RB_BLACK);
  			if (tmp2)
  				rb_set_parent(tmp2, parent);
  			__rb_rotate_set_parents(parent, sibling, root,
  						RB_BLACK);
9c079add0   Michel Lespinasse   rbtree: move augm...
376
  			augment_rotate(parent, sibling);
e125d1471   Michel Lespinasse   rbtree: optimize ...
377
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
  }
3cb7a5634   Michel Lespinasse   lib/rbtree.c: avo...
381
382
383
384
385
386
387
  
  /* Non-inline version for rb_erase_augmented() use */
  void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
  	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
  {
  	____rb_erase_color(parent, root, augment_rotate);
  }
9c079add0   Michel Lespinasse   rbtree: move augm...
388
  EXPORT_SYMBOL(__rb_erase_color);
14b94af0b   Michel Lespinasse   rbtree: faster au...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  
  /*
   * Non-augmented rbtree manipulation functions.
   *
   * We use dummy augmented callbacks here, and have the compiler optimize them
   * out of the rb_insert_color() and rb_erase() function definitions.
   */
  
  static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {}
  static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}
  static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
  
  static const struct rb_augment_callbacks dummy_callbacks = {
  	dummy_propagate, dummy_copy, dummy_rotate
  };
  
  void rb_insert_color(struct rb_node *node, struct rb_root *root)
  {
  	__rb_insert(node, root, dummy_rotate);
  }
  EXPORT_SYMBOL(rb_insert_color);
  
  void rb_erase(struct rb_node *node, struct rb_root *root)
  {
3cb7a5634   Michel Lespinasse   lib/rbtree.c: avo...
413
414
415
416
  	struct rb_node *rebalance;
  	rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
  	if (rebalance)
  		____rb_erase_color(rebalance, root, dummy_rotate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
  }
  EXPORT_SYMBOL(rb_erase);
14b94af0b   Michel Lespinasse   rbtree: faster au...
419
420
421
422
423
424
425
426
427
428
429
430
431
  /*
   * Augmented rbtree manipulation functions.
   *
   * This instantiates the same __always_inline functions as in the non-augmented
   * case, but this time with user-defined callbacks.
   */
  
  void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
  	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
  {
  	__rb_insert(node, root, augment_rotate);
  }
  EXPORT_SYMBOL(__rb_insert_augmented);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
  /*
   * This function returns the first node (in sort order) of the tree.
   */
f4b477c47   Artem Bityutskiy   rbtree: add const...
435
  struct rb_node *rb_first(const struct rb_root *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
438
439
440
441
442
443
444
445
446
  {
  	struct rb_node	*n;
  
  	n = root->rb_node;
  	if (!n)
  		return NULL;
  	while (n->rb_left)
  		n = n->rb_left;
  	return n;
  }
  EXPORT_SYMBOL(rb_first);
f4b477c47   Artem Bityutskiy   rbtree: add const...
447
  struct rb_node *rb_last(const struct rb_root *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
455
456
457
458
  {
  	struct rb_node	*n;
  
  	n = root->rb_node;
  	if (!n)
  		return NULL;
  	while (n->rb_right)
  		n = n->rb_right;
  	return n;
  }
  EXPORT_SYMBOL(rb_last);
f4b477c47   Artem Bityutskiy   rbtree: add const...
459
  struct rb_node *rb_next(const struct rb_node *node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  {
55a981027   David Woodhouse   [RBTREE] Merge co...
461
  	struct rb_node *parent;
4c199a93a   Michel Lespinasse   rbtree: empty nod...
462
  	if (RB_EMPTY_NODE(node))
10fd48f23   Jens Axboe   [PATCH] rbtree: f...
463
  		return NULL;
7ce6ff9e5   Michel Lespinasse   rbtree: coding st...
464
465
466
467
  	/*
  	 * If we have a right-hand child, go down and then left as far
  	 * as we can.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
  	if (node->rb_right) {
  		node = node->rb_right; 
  		while (node->rb_left)
  			node=node->rb_left;
f4b477c47   Artem Bityutskiy   rbtree: add const...
472
  		return (struct rb_node *)node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  	}
7ce6ff9e5   Michel Lespinasse   rbtree: coding st...
474
475
476
477
478
479
480
  	/*
  	 * No right-hand children. Everything down and left is smaller than us,
  	 * so any 'next' node must be in the general direction of our parent.
  	 * Go up the tree; any time the ancestor is a right-hand child of its
  	 * parent, keep going up. First time it's a left-hand child of its
  	 * parent, said parent is our 'next' node.
  	 */
55a981027   David Woodhouse   [RBTREE] Merge co...
481
482
  	while ((parent = rb_parent(node)) && node == parent->rb_right)
  		node = parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483

55a981027   David Woodhouse   [RBTREE] Merge co...
484
  	return parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
  }
  EXPORT_SYMBOL(rb_next);
f4b477c47   Artem Bityutskiy   rbtree: add const...
487
  struct rb_node *rb_prev(const struct rb_node *node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  {
55a981027   David Woodhouse   [RBTREE] Merge co...
489
  	struct rb_node *parent;
4c199a93a   Michel Lespinasse   rbtree: empty nod...
490
  	if (RB_EMPTY_NODE(node))
10fd48f23   Jens Axboe   [PATCH] rbtree: f...
491
  		return NULL;
7ce6ff9e5   Michel Lespinasse   rbtree: coding st...
492
493
494
495
  	/*
  	 * If we have a left-hand child, go down and then right as far
  	 * as we can.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
  	if (node->rb_left) {
  		node = node->rb_left; 
  		while (node->rb_right)
  			node=node->rb_right;
f4b477c47   Artem Bityutskiy   rbtree: add const...
500
  		return (struct rb_node *)node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  	}
7ce6ff9e5   Michel Lespinasse   rbtree: coding st...
502
503
504
505
  	/*
  	 * No left-hand children. Go up till we find an ancestor which
  	 * is a right-hand child of its parent.
  	 */
55a981027   David Woodhouse   [RBTREE] Merge co...
506
507
  	while ((parent = rb_parent(node)) && node == parent->rb_left)
  		node = parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508

55a981027   David Woodhouse   [RBTREE] Merge co...
509
  	return parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
514
515
  }
  EXPORT_SYMBOL(rb_prev);
  
  void rb_replace_node(struct rb_node *victim, struct rb_node *new,
  		     struct rb_root *root)
  {
55a981027   David Woodhouse   [RBTREE] Merge co...
516
  	struct rb_node *parent = rb_parent(victim);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517

c1adf2005   David Howells   Introduce rb_repl...
518
519
  	/* Copy the pointers/colour from the victim to the replacement */
  	*new = *victim;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  	/* Set the surrounding nodes to point to the replacement */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  	if (victim->rb_left)
55a981027   David Woodhouse   [RBTREE] Merge co...
522
  		rb_set_parent(victim->rb_left, new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  	if (victim->rb_right)
55a981027   David Woodhouse   [RBTREE] Merge co...
524
  		rb_set_parent(victim->rb_right, new);
c1adf2005   David Howells   Introduce rb_repl...
525
526
527
528
529
530
531
532
  	__rb_change_child(victim, new, parent, root);
  }
  EXPORT_SYMBOL(rb_replace_node);
  
  void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new,
  			 struct rb_root *root)
  {
  	struct rb_node *parent = rb_parent(victim);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
  
  	/* Copy the pointers/colour from the victim to the replacement */
  	*new = *victim;
c1adf2005   David Howells   Introduce rb_repl...
536
537
538
539
540
541
542
543
544
545
546
547
  
  	/* Set the surrounding nodes to point to the replacement */
  	if (victim->rb_left)
  		rb_set_parent(victim->rb_left, new);
  	if (victim->rb_right)
  		rb_set_parent(victim->rb_right, new);
  
  	/* Set the parent's pointer to the new node last after an RCU barrier
  	 * so that the pointers onwards are seen to be set correctly when doing
  	 * an RCU walk over the tree.
  	 */
  	__rb_change_child_rcu(victim, new, parent, root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
  }
c1adf2005   David Howells   Introduce rb_repl...
549
  EXPORT_SYMBOL(rb_replace_node_rcu);
9dee5c515   Cody P Schafer   rbtree: add posto...
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  
  static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
  {
  	for (;;) {
  		if (node->rb_left)
  			node = node->rb_left;
  		else if (node->rb_right)
  			node = node->rb_right;
  		else
  			return (struct rb_node *)node;
  	}
  }
  
  struct rb_node *rb_next_postorder(const struct rb_node *node)
  {
  	const struct rb_node *parent;
  	if (!node)
  		return NULL;
  	parent = rb_parent(node);
  
  	/* If we're sitting on node, we've already seen our children */
  	if (parent && node == parent->rb_left && parent->rb_right) {
  		/* If we are the parent's left node, go to the parent's right
  		 * node then all the way down to the left */
  		return rb_left_deepest_node(parent->rb_right);
  	} else
  		/* Otherwise we are the parent's right node, and the parent
  		 * should be next */
  		return (struct rb_node *)parent;
  }
  EXPORT_SYMBOL(rb_next_postorder);
  
  struct rb_node *rb_first_postorder(const struct rb_root *root)
  {
  	if (!root->rb_node)
  		return NULL;
  
  	return rb_left_deepest_node(root->rb_node);
  }
  EXPORT_SYMBOL(rb_first_postorder);