* [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: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 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 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 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: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