aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2013-01-11 17:32:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-01-11 17:54:56 -0500
commit3cb7a56344ca45ee56d71c5f8fe9f922306bff1f (patch)
treeda6fd5aa462e9e7c117063740c15fd95241c72d3
parenta8906b0b673a8a64ae1446a7847def62388f6e46 (diff)
lib/rbtree.c: avoid the use of non-static __always_inline
lib/rbtree.c declared __rb_erase_color() as __always_inline void, and then exported it with EXPORT_SYMBOL. This was because __rb_erase_color() must be exported for augmented rbtree users, but it must also be inlined into rb_erase() so that the dummy callback can get optimized out of that call site. (Actually with a modern compiler, none of the dummy callback functions should even be generated as separate text functions). The above usage is legal C, but it was unusual enough for some compilers to warn about it. This change makes things more explicit, with a static __always_inline ____rb_erase_color function for use in rb_erase(), and a separate non-inline __rb_erase_color function for use in rb_erase_augmented call sites. Signed-off-by: Michel Lespinasse <walken@google.com> Reported-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/rbtree_augmented.h14
-rw-r--r--lib/rbtree.c20
2 files changed, 28 insertions, 6 deletions
diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h
index 2ac60c9cf644..fea49b5da12a 100644
--- a/include/linux/rbtree_augmented.h
+++ b/include/linux/rbtree_augmented.h
@@ -123,9 +123,9 @@ __rb_change_child(struct rb_node *old, struct rb_node *new,
123extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 123extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
124 void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); 124 void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
125 125
126static __always_inline void 126static __always_inline struct rb_node *
127rb_erase_augmented(struct rb_node *node, struct rb_root *root, 127__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
128 const struct rb_augment_callbacks *augment) 128 const struct rb_augment_callbacks *augment)
129{ 129{
130 struct rb_node *child = node->rb_right, *tmp = node->rb_left; 130 struct rb_node *child = node->rb_right, *tmp = node->rb_left;
131 struct rb_node *parent, *rebalance; 131 struct rb_node *parent, *rebalance;
@@ -217,6 +217,14 @@ rb_erase_augmented(struct rb_node *node, struct rb_root *root,
217 } 217 }
218 218
219 augment->propagate(tmp, NULL); 219 augment->propagate(tmp, NULL);
220 return rebalance;
221}
222
223static __always_inline void
224rb_erase_augmented(struct rb_node *node, struct rb_root *root,
225 const struct rb_augment_callbacks *augment)
226{
227 struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
220 if (rebalance) 228 if (rebalance)
221 __rb_erase_color(rebalance, root, augment->rotate); 229 __rb_erase_color(rebalance, root, augment->rotate);
222} 230}
diff --git a/lib/rbtree.c b/lib/rbtree.c
index 4f56a11d67fa..c0e31fe2fabf 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -194,8 +194,12 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
194 } 194 }
195} 195}
196 196
197__always_inline void 197/*
198__rb_erase_color(struct rb_node *parent, struct rb_root *root, 198 * Inline version for rb_erase() use - we want to be able to inline
199 * and eliminate the dummy_rotate callback there
200 */
201static __always_inline void
202____rb_erase_color(struct rb_node *parent, struct rb_root *root,
199 void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 203 void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
200{ 204{
201 struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; 205 struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
@@ -355,6 +359,13 @@ __rb_erase_color(struct rb_node *parent, struct rb_root *root,
355 } 359 }
356 } 360 }
357} 361}
362
363/* Non-inline version for rb_erase_augmented() use */
364void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
365 void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
366{
367 ____rb_erase_color(parent, root, augment_rotate);
368}
358EXPORT_SYMBOL(__rb_erase_color); 369EXPORT_SYMBOL(__rb_erase_color);
359 370
360/* 371/*
@@ -380,7 +391,10 @@ EXPORT_SYMBOL(rb_insert_color);
380 391
381void rb_erase(struct rb_node *node, struct rb_root *root) 392void rb_erase(struct rb_node *node, struct rb_root *root)
382{ 393{
383 rb_erase_augmented(node, root, &dummy_callbacks); 394 struct rb_node *rebalance;
395 rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
396 if (rebalance)
397 ____rb_erase_color(rebalance, root, dummy_rotate);
384} 398}
385EXPORT_SYMBOL(rb_erase); 399EXPORT_SYMBOL(rb_erase);
386 400