* [PATCH] rcu: avoid checking for constant
@ 2012-01-12 5:11 Jan Engelhardt
2012-01-12 7:14 ` Josh Triplett
0 siblings, 1 reply; 14+ messages in thread
From: Jan Engelhardt @ 2012-01-12 5:11 UTC (permalink / raw)
To: paulmck; +Cc: laijs, manfred, dhowells, josh, linux-kernel, jengelh
When compiling kernel or module code with -O0, "offset" is no longer
considered a constant, and therefore always triggers the build error
that BUILD_BUG_ON is defined to yield.
What is the rationale between the forced constant check,
introduced in 9ab1544eb4196ca8d05c433b2eb56f74496b1ee3?
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
include/linux/rcupdate.h | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 2cf4226..38c5ba5 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -805,8 +805,6 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
{
typedef void (*rcu_callback)(struct rcu_head *);
- BUILD_BUG_ON(!__builtin_constant_p(offset));
-
/* See the kfree_rcu() header comment. */
BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
--
1.7.7
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 5:11 [PATCH] rcu: avoid checking for constant Jan Engelhardt
@ 2012-01-12 7:14 ` Josh Triplett
2012-01-12 9:25 ` Jan Engelhardt
0 siblings, 1 reply; 14+ messages in thread
From: Josh Triplett @ 2012-01-12 7:14 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thu, Jan 12, 2012 at 06:11:44AM +0100, Jan Engelhardt wrote:
> When compiling kernel or module code with -O0, "offset" is no longer
> considered a constant, and therefore always triggers the build error
> that BUILD_BUG_ON is defined to yield.
>
> What is the rationale between the forced constant check,
> introduced in 9ab1544eb4196ca8d05c433b2eb56f74496b1ee3?
[...]
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -805,8 +805,6 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
> {
> typedef void (*rcu_callback)(struct rcu_head *);
>
> - BUILD_BUG_ON(!__builtin_constant_p(offset));
> -
> /* See the kfree_rcu() header comment. */
> BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
The very next check after the one you removed will break if the
compiler can't check the offset at compile time.
- Josh Triplett
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 7:14 ` Josh Triplett
@ 2012-01-12 9:25 ` Jan Engelhardt
2012-01-12 9:52 ` Josh Triplett
0 siblings, 1 reply; 14+ messages in thread
From: Jan Engelhardt @ 2012-01-12 9:25 UTC (permalink / raw)
To: Josh Triplett; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thursday 2012-01-12 08:14, Josh Triplett wrote:
>On Thu, Jan 12, 2012 at 06:11:44AM +0100, Jan Engelhardt wrote:
>> When compiling kernel or module code with -O0, "offset" is no longer
>> considered a constant, and therefore always triggers the build error
>> that BUILD_BUG_ON is defined to yield.
>[...]
>> --- a/include/linux/rcupdate.h
>> +++ b/include/linux/rcupdate.h
>> @@ -805,8 +805,6 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
>> {
>> typedef void (*rcu_callback)(struct rcu_head *);
>>
>> - BUILD_BUG_ON(!__builtin_constant_p(offset));
>> -
>> /* See the kfree_rcu() header comment. */
>> BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
>
>The very next check after the one you removed will break if the
>compiler can't check the offset at compile time.
Thanks for catching that. How about the following approach? :
parent f9fab10bbd768b0e5254e53a4a8477a94bfc4b96 (v3.2-rc7-86-gf9fab10)
commit a4145604f1e40ce93a25a053f0f49341324b0077
Author: Jan Engelhardt <jengelh@medozas.de>
Date: Wed Jan 11 10:05:00 2012 +0100
rcu: avoid checking for constant
When compiling kernel or module code with -O0, "offset" is no longer
considered a constant, and therefore always triggers the build error
that BUILD_BUG_ON is defined to yield.
What is the rationale between the forced constant check,
introduced in 9ab1544eb4196ca8d05c433b2eb56f74496b1ee3?
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
include/linux/rcupdate.h | 22 ++++------------------
1 files changed, 4 insertions(+), 18 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 2cf4226..5e7286d 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -795,24 +795,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define RCU_INIT_POINTER(p, v) \
p = (typeof(*v) __force __rcu *)(v)
-static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
-{
- return offset < 4096;
-}
-
-static __always_inline
-void __kfree_rcu(struct rcu_head *head, unsigned long offset)
-{
- typedef void (*rcu_callback)(struct rcu_head *);
-
- BUILD_BUG_ON(!__builtin_constant_p(offset));
-
- /* See the kfree_rcu() header comment. */
- BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
-
- call_rcu(head, (rcu_callback)offset);
-}
-
/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
@@ -836,6 +818,10 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
* Note that the allowable offset might decrease in the future, for example,
* to allow something like kmem_cache_free_rcu().
*/
+#define __kfree_rcu(head, offset) \
+ call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset) + \
+ BUILD_BUG_ON_ZERO((offset) >= 4096))
+
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
--
# Created with git-export-patch
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 9:25 ` Jan Engelhardt
@ 2012-01-12 9:52 ` Josh Triplett
2012-01-12 10:34 ` Jan Engelhardt
0 siblings, 1 reply; 14+ messages in thread
From: Josh Triplett @ 2012-01-12 9:52 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thu, Jan 12, 2012 at 10:25:23AM +0100, Jan Engelhardt wrote:
> rcu: avoid checking for constant
>
> When compiling kernel or module code with -O0, "offset" is no longer
> considered a constant, and therefore always triggers the build error
> that BUILD_BUG_ON is defined to yield.
>
> What is the rationale between the forced constant check,
> introduced in 9ab1544eb4196ca8d05c433b2eb56f74496b1ee3?
This question shouldn't live in the commit message. Please replace it
with an explanation of the change instead.
> Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
> ---
> include/linux/rcupdate.h | 22 ++++------------------
> 1 files changed, 4 insertions(+), 18 deletions(-)
>
> diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
> index 2cf4226..5e7286d 100644
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -795,24 +795,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> #define RCU_INIT_POINTER(p, v) \
> p = (typeof(*v) __force __rcu *)(v)
>
> -static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
> -{
> - return offset < 4096;
> -}
> -
> -static __always_inline
> -void __kfree_rcu(struct rcu_head *head, unsigned long offset)
> -{
> - typedef void (*rcu_callback)(struct rcu_head *);
> -
> - BUILD_BUG_ON(!__builtin_constant_p(offset));
> -
> - /* See the kfree_rcu() header comment. */
> - BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
> -
> - call_rcu(head, (rcu_callback)offset);
> -}
> -
> /**
> * kfree_rcu() - kfree an object after a grace period.
> * @ptr: pointer to kfree
> @@ -836,6 +818,10 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
> * Note that the allowable offset might decrease in the future, for example,
> * to allow something like kmem_cache_free_rcu().
> */
> +#define __kfree_rcu(head, offset) \
> + call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset) + \
> + BUILD_BUG_ON_ZERO((offset) >= 4096))
> +
I had to stare at this for a while, and look up the definition of
BUILD_BUG_ON_ZERO. Naturally I assumed that BUILD_BUG_ON_ZERO(arg)
meant BUILT_BUG_ON((arg) == 0), which would have made the logic
backwards here. However, per the definition it just provides a
zero-returning version of BUILD_BUG_ON. Ow.
In any case, __kfree_rcu has void return type, so how about just using
do { ... } while(0) and BUILD_BUG_ON instead? That seems significantly
clearer.
Apart from that, I can live with this, though it seems horribly
backwards to replace an inline with a macro rather than the other way
around.
- Josh Triplett
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 9:52 ` Josh Triplett
@ 2012-01-12 10:34 ` Jan Engelhardt
2012-01-12 10:54 ` Eric Dumazet
2012-01-12 11:58 ` Josh Triplett
0 siblings, 2 replies; 14+ messages in thread
From: Jan Engelhardt @ 2012-01-12 10:34 UTC (permalink / raw)
To: Josh Triplett; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thursday 2012-01-12 10:52, Josh Triplett wrote:
>> +#define __kfree_rcu(head, offset) \
>> + call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset) + \
>> + BUILD_BUG_ON_ZERO((offset) >= 4096))
>> +
>
>I had to stare at this for a while, and look up the definition of
>BUILD_BUG_ON_ZERO. Naturally I assumed that BUILD_BUG_ON_ZERO(arg)
>meant BUILT_BUG_ON((arg) == 0), which would have made the logic
>backwards here. However, per the definition it just provides a
>zero-returning version of BUILD_BUG_ON. Ow.
Same impression here. BUILD_BUG_ON_ZERO was introduced by
commit 4552d5dc08b79868829b4be8951b29b07284753f
Author: Jan Beulich <jbeulich@novell.com>
Date: Mon Jun 26 13:57:28 2006 +0200
while Rusty's CCAN archive calls it "BUILD_BUG_OR_ZERO" (since either
it's a bug, or returning neutral zero).
>In any case, __kfree_rcu has void return type, so how about just using
>do { ... } while(0) and BUILD_BUG_ON instead? That seems significantly
>clearer.
Ok. In that case, I'll allow myself to reintroduce the extra temporal
typedef line that was there previously:
>Apart from that, I can live with this, though it seems horribly
>backwards to replace an inline with a macro rather than the other way
>around.
parent f9fab10bbd768b0e5254e53a4a8477a94bfc4b96 (v3.2-rc7-86-gf9fab10)
commit 041ac1b39390b93d8db91075aefc56b585db75cd
Author: Jan Engelhardt <jengelh@medozas.de>
Date: Wed Jan 11 10:05:00 2012 +0100
rcu: avoid checking for constant
When compiling kernel or module code with -O0, "offset" is no longer
considered a constant, and therefore always triggers the build error
that BUILD_BUG_ON is defined to yield.
Therefore, change the innards of kfree_rcu so that the offset is not
tunneled through a function argument before checking it.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
include/linux/rcupdate.h | 31 +++++++++++++------------------
1 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 2cf4226..7395ab6 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -795,24 +795,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define RCU_INIT_POINTER(p, v) \
p = (typeof(*v) __force __rcu *)(v)
-static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
-{
- return offset < 4096;
-}
-
-static __always_inline
-void __kfree_rcu(struct rcu_head *head, unsigned long offset)
-{
- typedef void (*rcu_callback)(struct rcu_head *);
-
- BUILD_BUG_ON(!__builtin_constant_p(offset));
-
- /* See the kfree_rcu() header comment. */
- BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
-
- call_rcu(head, (rcu_callback)offset);
-}
-
/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
@@ -835,7 +817,20 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
*
* Note that the allowable offset might decrease in the future, for example,
* to allow something like kmem_cache_free_rcu().
+ *
+ * The BUILD_BUG_ON check must not involve any function calls, hence the
+ * checks are done in macros here. __is_kfree_rcu_offset is also used by
+ * kernel/rcu.h.
*/
+#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
+
+#define __kfree_rcu(head, offset) \
+ do { \
+ typedef void (*rcu_callback)(struct rcu_head *); \
+ BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
+ call_rcu(head, (rcu_callback)(unsigned long)(offset)); \
+ } while (0)
+
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
--
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 10:34 ` Jan Engelhardt
@ 2012-01-12 10:54 ` Eric Dumazet
2012-01-12 10:57 ` Jan Engelhardt
2012-01-12 11:58 ` Josh Triplett
1 sibling, 1 reply; 14+ messages in thread
From: Eric Dumazet @ 2012-01-12 10:54 UTC (permalink / raw)
To: Jan Engelhardt
Cc: Josh Triplett, paulmck, laijs, manfred, dhowells, linux-kernel
Le jeudi 12 janvier 2012 à 11:34 +0100, Jan Engelhardt a écrit :
> When compiling kernel or module code with -O0, "offset" is no longer
> considered a constant, and therefore always triggers the build error
> that BUILD_BUG_ON is defined to yield.
Why compiling kernel with -O0 is even considered ?
A lot of patches are needed because gcc -O0 is unable to understand some
code is dead code.
LD .tmp_vmlinux1
mm/built-in.o: In function `do_swap_page':
memory.c:(.text+0x44dbd): undefined reference to `ksm_does_need_to_copy'
net/built-in.o: In function `ieee80211_tx_status':
(.text+0x221ac1): undefined reference to `ieee80211s_update_metric'
net/built-in.o: In function `sta_info_insert_finish':
sta_info.c:(.text+0x224c62): undefined reference to
`mesh_accept_plinks_update'
net/built-in.o: In function `ieee80211_teardown_sdata':
iface.c:(.text+0x242773): undefined reference to `mesh_rmc_free'
net/built-in.o: In function `ieee80211_iface_work':
iface.c:(.text+0x242cfa): undefined reference to
`ieee80211_mesh_rx_queued_mgmt'
iface.c:(.text+0x242dc2): undefined reference to `ieee80211_mesh_work'
net/built-in.o: In function `ieee80211_setup_sdata':
iface.c:(.text+0x242ffc): undefined reference to
`ieee80211_mesh_init_sdata'
net/built-in.o: In function `ieee80211_if_remove':
(.text+0x243d1a): undefined reference to `mesh_path_flush_by_iface'
net/built-in.o: In function `ieee80211_remove_interfaces':
(.text+0x243df5): undefined reference to `mesh_path_flush_by_iface'
net/built-in.o: In function `ieee80211_rx_h_action':
rx.c:(.text+0x253ba6): undefined reference to `mesh_action_is_path_sel'
net/built-in.o: In function `ieee80211_xmit':
(.text+0x25a254): undefined reference to `mesh_nexthop_resolve'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c250): undefined reference to `mesh_add_ds_params_ie'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c28d): undefined reference to `mesh_add_rsn_ie'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c2a4): undefined reference to `mesh_add_ht_cap_ie'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c2bb): undefined reference to `mesh_add_ht_info_ie'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c2d2): undefined reference to `mesh_add_meshid_ie'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c2e9): undefined reference to `mesh_add_meshconf_ie'
net/built-in.o: In function `ieee80211_beacon_get_tim':
(.text+0x25c300): undefined reference to `mesh_add_vendor_ies'
make: *** [.tmp_vmlinux1] Erreur 1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 10:54 ` Eric Dumazet
@ 2012-01-12 10:57 ` Jan Engelhardt
2012-01-12 15:29 ` Paul E. McKenney
0 siblings, 1 reply; 14+ messages in thread
From: Jan Engelhardt @ 2012-01-12 10:57 UTC (permalink / raw)
To: Eric Dumazet
Cc: Josh Triplett, paulmck, laijs, manfred, dhowells, linux-kernel
On Thursday 2012-01-12 11:54, Eric Dumazet wrote:
>Le jeudi 12 janvier 2012 à 11:34 +0100, Jan Engelhardt a écrit :
>
>> When compiling kernel or module code with -O0, "offset" is no longer
>> considered a constant, and therefore always triggers the build error
>> that BUILD_BUG_ON is defined to yield.
>
>Why compiling kernel with -O0 is even considered ?
The compile error was observed when trying to compile an out-of-tree
module with -O0.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 10:34 ` Jan Engelhardt
2012-01-12 10:54 ` Eric Dumazet
@ 2012-01-12 11:58 ` Josh Triplett
2012-01-12 15:38 ` Jan Engelhardt
1 sibling, 1 reply; 14+ messages in thread
From: Josh Triplett @ 2012-01-12 11:58 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thu, Jan 12, 2012 at 11:34:23AM +0100, Jan Engelhardt wrote:
> On Thursday 2012-01-12 10:52, Josh Triplett wrote:
> >> +#define __kfree_rcu(head, offset) \
> >> + call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset) + \
> >> + BUILD_BUG_ON_ZERO((offset) >= 4096))
> >> +
> >
> >I had to stare at this for a while, and look up the definition of
> >BUILD_BUG_ON_ZERO. Naturally I assumed that BUILD_BUG_ON_ZERO(arg)
> >meant BUILT_BUG_ON((arg) == 0), which would have made the logic
> >backwards here. However, per the definition it just provides a
> >zero-returning version of BUILD_BUG_ON. Ow.
>
> Same impression here. BUILD_BUG_ON_ZERO was introduced by
>
> commit 4552d5dc08b79868829b4be8951b29b07284753f
> Author: Jan Beulich <jbeulich@novell.com>
> Date: Mon Jun 26 13:57:28 2006 +0200
>
> while Rusty's CCAN archive calls it "BUILD_BUG_OR_ZERO" (since either
> it's a bug, or returning neutral zero).
Sounds like a good target for a fix at some point.
> rcu: avoid checking for constant
>
> When compiling kernel or module code with -O0, "offset" is no longer
> considered a constant, and therefore always triggers the build error
> that BUILD_BUG_ON is defined to yield.
>
> Therefore, change the innards of kfree_rcu so that the offset is not
> tunneled through a function argument before checking it.
The commit message looks good now.
> @@ -835,7 +817,20 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
> *
> * Note that the allowable offset might decrease in the future, for example,
> * to allow something like kmem_cache_free_rcu().
> + *
> + * The BUILD_BUG_ON check must not involve any function calls, hence the
> + * checks are done in macros here. __is_kfree_rcu_offset is also used by
> + * kernel/rcu.h.
The first sentence of that paragraph seems like a worthwhile addition.
Please drop the second, though, since it'll inevitably become outdated.
> +#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
> +
> +#define __kfree_rcu(head, offset) \
> + do { \
> + typedef void (*rcu_callback)(struct rcu_head *); \
> + BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
> + call_rcu(head, (rcu_callback)(unsigned long)(offset)); \
> + } while (0)
No, you can't define that typedef here with that name. Unlike in the
inline function, in a macro you could introduce a name conflict.
- Josh Triplett
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 10:57 ` Jan Engelhardt
@ 2012-01-12 15:29 ` Paul E. McKenney
2012-01-12 16:08 ` Jan Engelhardt
0 siblings, 1 reply; 14+ messages in thread
From: Paul E. McKenney @ 2012-01-12 15:29 UTC (permalink / raw)
To: Jan Engelhardt
Cc: Eric Dumazet, Josh Triplett, laijs, manfred, dhowells,
linux-kernel
On Thu, Jan 12, 2012 at 11:57:10AM +0100, Jan Engelhardt wrote:
> On Thursday 2012-01-12 11:54, Eric Dumazet wrote:
>
> >Le jeudi 12 janvier 2012 à 11:34 +0100, Jan Engelhardt a écrit :
> >
> >> When compiling kernel or module code with -O0, "offset" is no longer
> >> considered a constant, and therefore always triggers the build error
> >> that BUILD_BUG_ON is defined to yield.
> >
> >Why compiling kernel with -O0 is even considered ?
>
> The compile error was observed when trying to compile an out-of-tree
> module with -O0.
Hmmm... Why not have a glue .c file in your out-of-tree module
that contains function like:
void kfree_rcu_foo(struct foo *fp)
{
kfree_rcu(fp, foo_rcu);
}
Compile this .c file normally, then apply -O0 only to the other
files in your module.
Thanx, Paul
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 11:58 ` Josh Triplett
@ 2012-01-12 15:38 ` Jan Engelhardt
2012-01-12 18:41 ` Josh Triplett
0 siblings, 1 reply; 14+ messages in thread
From: Jan Engelhardt @ 2012-01-12 15:38 UTC (permalink / raw)
To: Josh Triplett; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thursday 2012-01-12 12:58, Josh Triplett wrote:
>> Same impression here. BUILD_BUG_ON_ZERO was introduced by
>>
>> commit 4552d5dc08b79868829b4be8951b29b07284753f
>> Author: Jan Beulich <jbeulich@novell.com>
>> Date: Mon Jun 26 13:57:28 2006 +0200
>>
>> while Rusty's CCAN archive calls it "BUILD_BUG_OR_ZERO" (since either
>> it's a bug, or returning neutral zero).
>
>Sounds like a good target for a fix at some point.
What names do you propose? I have BUILD_BUG_ON_EXPR for some of my code,
though in the kernel, it has both _ON_ZERO and _ON_NULL.
>> Therefore, change the innards of kfree_rcu so that the offset is not
>> tunneled through a function argument before checking it.
>
>The commit message looks good now.
>
>> + * The BUILD_BUG_ON check must not involve any function calls, hence the
>> + * checks are done in macros here. __is_kfree_rcu_offset is also used by
>> + * kernel/rcu.h.
>
>The first sentence of that paragraph seems like a worthwhile addition.
>Please drop the second, though, since it'll inevitably become outdated.
>
>> + typedef void (*rcu_callback)(struct rcu_head *); \
>
>No, you can't define that typedef here with that name. Unlike in the
>inline function, in a macro you could introduce a name conflict.
parent f9fab10bbd768b0e5254e53a4a8477a94bfc4b96 (v3.2-rc7-86-gf9fab10)
commit 2d6e2f3244513ec05953383886ef0556f64038b1
Author: Jan Engelhardt <jengelh@medozas.de>
Date: Wed Jan 11 10:05:00 2012 +0100
rcu: avoid checking for constant
When compiling kernel or module code with -O0, "offset" is no longer
considered a constant, and therefore always triggers the build error
that BUILD_BUG_ON is defined to yield.
Therefore, change the innards of kfree_rcu so that the offset is not
tunneled through a function argument before checking it.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
---
include/linux/rcupdate.h | 29 +++++++++++------------------
1 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 2cf4226..c693e4a 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -795,24 +795,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define RCU_INIT_POINTER(p, v) \
p = (typeof(*v) __force __rcu *)(v)
-static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
-{
- return offset < 4096;
-}
-
-static __always_inline
-void __kfree_rcu(struct rcu_head *head, unsigned long offset)
-{
- typedef void (*rcu_callback)(struct rcu_head *);
-
- BUILD_BUG_ON(!__builtin_constant_p(offset));
-
- /* See the kfree_rcu() header comment. */
- BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
-
- call_rcu(head, (rcu_callback)offset);
-}
-
/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
@@ -835,7 +817,18 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
*
* Note that the allowable offset might decrease in the future, for example,
* to allow something like kmem_cache_free_rcu().
+ *
+ * The BUILD_BUG_ON check must not involve any function calls, hence the
+ * checks are done in macros here.
*/
+#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
+
+#define __kfree_rcu(head, offset) \
+ do { \
+ BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
+ call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
+ } while (0)
+
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
--
# Created with git-export-patch
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 15:29 ` Paul E. McKenney
@ 2012-01-12 16:08 ` Jan Engelhardt
2012-01-12 16:14 ` Eric Dumazet
0 siblings, 1 reply; 14+ messages in thread
From: Jan Engelhardt @ 2012-01-12 16:08 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Eric Dumazet, Josh Triplett, laijs, manfred, dhowells,
linux-kernel
On Thursday 2012-01-12 16:29, Paul E. McKenney wrote:
>On Thu, Jan 12, 2012 at 11:57:10AM +0100, Jan Engelhardt wrote:
>> On Thursday 2012-01-12 11:54, Eric Dumazet wrote:
>>
>> >Le jeudi 12 janvier 2012 à 11:34 +0100, Jan Engelhardt a écrit :
>> >
>> >> When compiling kernel or module code with -O0, "offset" is no longer
>> >> considered a constant, and therefore always triggers the build error
>> >> that BUILD_BUG_ON is defined to yield.
>> >
>> >Why compiling kernel with -O0 is even considered ?
>>
>> The compile error was observed when trying to compile an out-of-tree
>> module with -O0.
>
>Hmmm... Why not have a glue .c file in your out-of-tree module
>that contains function like[...]
Maybe, maybe naah. The kernel relying on gcc's -O2 mode to do constant
value analysis through and into inline functions does not sound too
great. The compiler could change on the next moonphase. In fact, one
can't use clang -O2 because of this. With my patch, one can again use
clang -O2 [with respect to kfree_rcu].
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 16:08 ` Jan Engelhardt
@ 2012-01-12 16:14 ` Eric Dumazet
0 siblings, 0 replies; 14+ messages in thread
From: Eric Dumazet @ 2012-01-12 16:14 UTC (permalink / raw)
To: Jan Engelhardt
Cc: Paul E. McKenney, Josh Triplett, laijs, manfred, dhowells,
linux-kernel
Le jeudi 12 janvier 2012 à 17:08 +0100, Jan Engelhardt a écrit :
> Maybe, maybe naah. The kernel relying on gcc's -O2 mode to do constant
> value analysis through and into inline functions does not sound too
> great. The compiler could change on the next moonphase. In fact, one
> can't use clang -O2 because of this. With my patch, one can again use
> clang -O2 [with respect to kfree_rcu].
Unless whole kernel can be compiled with -O0, its really some noise.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 15:38 ` Jan Engelhardt
@ 2012-01-12 18:41 ` Josh Triplett
2012-04-19 18:57 ` Paul E. McKenney
0 siblings, 1 reply; 14+ messages in thread
From: Josh Triplett @ 2012-01-12 18:41 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: paulmck, laijs, manfred, dhowells, linux-kernel
On Thu, Jan 12, 2012 at 04:38:52PM +0100, Jan Engelhardt wrote:
> On Thursday 2012-01-12 12:58, Josh Triplett wrote:
> >> Same impression here. BUILD_BUG_ON_ZERO was introduced by
> >>
> >> commit 4552d5dc08b79868829b4be8951b29b07284753f
> >> Author: Jan Beulich <jbeulich@novell.com>
> >> Date: Mon Jun 26 13:57:28 2006 +0200
> >>
> >> while Rusty's CCAN archive calls it "BUILD_BUG_OR_ZERO" (since either
> >> it's a bug, or returning neutral zero).
> >
> >Sounds like a good target for a fix at some point.
>
> What names do you propose? I have BUILD_BUG_ON_EXPR for some of my code,
> though in the kernel, it has both _ON_ZERO and _ON_NULL.
BUILD_BUG_OR_ZERO (and BUILD_BUG_OR_NULL) seem like improvements over
_ON_ZERO and _ON_NULL; that would remove the ambiguity we both tripped
over.
> rcu: avoid checking for constant
>
> When compiling kernel or module code with -O0, "offset" is no longer
> considered a constant, and therefore always triggers the build error
> that BUILD_BUG_ON is defined to yield.
>
> Therefore, change the innards of kfree_rcu so that the offset is not
> tunneled through a function argument before checking it.
>
> Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
> --- a/include/linux/rcupdate.h
> +++ b/include/linux/rcupdate.h
> @@ -795,24 +795,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
> #define RCU_INIT_POINTER(p, v) \
> p = (typeof(*v) __force __rcu *)(v)
>
> -static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
> -{
> - return offset < 4096;
> -}
> -
> -static __always_inline
> -void __kfree_rcu(struct rcu_head *head, unsigned long offset)
> -{
> - typedef void (*rcu_callback)(struct rcu_head *);
> -
> - BUILD_BUG_ON(!__builtin_constant_p(offset));
> -
> - /* See the kfree_rcu() header comment. */
> - BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
> -
> - call_rcu(head, (rcu_callback)offset);
> -}
> -
> /**
> * kfree_rcu() - kfree an object after a grace period.
> * @ptr: pointer to kfree
> @@ -835,7 +817,18 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
> *
> * Note that the allowable offset might decrease in the future, for example,
> * to allow something like kmem_cache_free_rcu().
> + *
> + * The BUILD_BUG_ON check must not involve any function calls, hence the
> + * checks are done in macros here.
> */
> +#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
> +
> +#define __kfree_rcu(head, offset) \
> + do { \
> + BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
> + call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
> + } while (0)
> +
> #define kfree_rcu(ptr, rcu_head) \
> __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
- Josh Triplett
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] rcu: avoid checking for constant
2012-01-12 18:41 ` Josh Triplett
@ 2012-04-19 18:57 ` Paul E. McKenney
0 siblings, 0 replies; 14+ messages in thread
From: Paul E. McKenney @ 2012-04-19 18:57 UTC (permalink / raw)
To: Josh Triplett; +Cc: Jan Engelhardt, laijs, manfred, dhowells, linux-kernel
On Thu, Jan 12, 2012 at 10:41:50AM -0800, Josh Triplett wrote:
> On Thu, Jan 12, 2012 at 04:38:52PM +0100, Jan Engelhardt wrote:
> > On Thursday 2012-01-12 12:58, Josh Triplett wrote:
> > >> Same impression here. BUILD_BUG_ON_ZERO was introduced by
> > >>
> > >> commit 4552d5dc08b79868829b4be8951b29b07284753f
> > >> Author: Jan Beulich <jbeulich@novell.com>
> > >> Date: Mon Jun 26 13:57:28 2006 +0200
> > >>
> > >> while Rusty's CCAN archive calls it "BUILD_BUG_OR_ZERO" (since either
> > >> it's a bug, or returning neutral zero).
> > >
> > >Sounds like a good target for a fix at some point.
> >
> > What names do you propose? I have BUILD_BUG_ON_EXPR for some of my code,
> > though in the kernel, it has both _ON_ZERO and _ON_NULL.
>
> BUILD_BUG_OR_ZERO (and BUILD_BUG_OR_NULL) seem like improvements over
> _ON_ZERO and _ON_NULL; that would remove the ambiguity we both tripped
> over.
>
> > rcu: avoid checking for constant
> >
> > When compiling kernel or module code with -O0, "offset" is no longer
> > considered a constant, and therefore always triggers the build error
> > that BUILD_BUG_ON is defined to yield.
> >
> > Therefore, change the innards of kfree_rcu so that the offset is not
> > tunneled through a function argument before checking it.
> >
> > Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
>
> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
OK, a similar run-in with copy_from_user() convince me that we need
this. (And I was even using default optimization levels!)
Queue for 3.5, with reworked comments and commit log.
Thanx, Paul
------------------------------------------------------------------------
rcu: Make __kfree_rcu() less dependent on compiler choices
Currently, __kfree_rcu() is implemented as an inline function, and
contains a BUILD_BUG_ON() that malfunctions if __kfree_rcu() is compiled
as an out-of-line function. Unfortunately, there are compiler settings
(e.g., -O0) that can result in __kfree_rcu() being compiled out of line,
resulting in annoying build breakage. This commit therefore converts
both __kfree_rcu() and __is_kfree_rcu_offset() from inline functions to
macros to prevent such misbehavior on the part of the compiler.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 20fb776..d5dfb10 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -922,6 +922,21 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
kfree_call_rcu(head, (rcu_callback)offset);
}
+/*
+ * Does the specified offset indicate that the corresponding rcu_head
+ * structure can be handled by kfree_rcu()?
+ */
+#define __is_kfree_rcu_offset(offset) ((offset) < 4096)
+
+/*
+ * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.
+ */
+#define __kfree_rcu(head, offset) \
+ do { \
+ BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
+ call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
+ } while (0)
+
/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
@@ -944,6 +959,9 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
*
* Note that the allowable offset might decrease in the future, for example,
* to allow something like kmem_cache_free_rcu().
+ *
+ * The BUILD_BUG_ON check must not involve any function calls, hence the
+ * checks are done in macros here.
*/
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2012-04-19 18:57 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-12 5:11 [PATCH] rcu: avoid checking for constant Jan Engelhardt
2012-01-12 7:14 ` Josh Triplett
2012-01-12 9:25 ` Jan Engelhardt
2012-01-12 9:52 ` Josh Triplett
2012-01-12 10:34 ` Jan Engelhardt
2012-01-12 10:54 ` Eric Dumazet
2012-01-12 10:57 ` Jan Engelhardt
2012-01-12 15:29 ` Paul E. McKenney
2012-01-12 16:08 ` Jan Engelhardt
2012-01-12 16:14 ` Eric Dumazet
2012-01-12 11:58 ` Josh Triplett
2012-01-12 15:38 ` Jan Engelhardt
2012-01-12 18:41 ` Josh Triplett
2012-04-19 18:57 ` Paul E. McKenney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox