kernel: events: core: Replace rcu_assign_pointer() with RCU_INIT_POINTER()
Subsystems (2)
PATCH 1/1 kernel: events: core: Replace rcu_assign_pointer() with RCU_INIT_POINTER()
The use of "rcu_assign_pointer()" is NULLing out the pointer. According to RCU_INIT_POINTER()'s block comment:
"1. This use of RCU_INIT_POINTER() is NULLing out the pointer"
it is better to use it instead of rcu_assign_pointer() because it has a smaller overhead.
The following Coccinelle semantic patch was used:
@@
@@
- rcu_assign_pointer
+ RCU_INIT_POINTER
(..., NULL)
--- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/events/core.c +1 -1
@@ -5744,7 +5744,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)if (!hlist)return ; -rcu_assign_pointer (swhash->swevent_hlist,NULL ); +RCU_INIT_POINTER (swhash->swevent_hlist,NULL );kfree_rcu (hlist, rcu_head); }
Signature · 1 line
1.9.1
Peter Zijlstra
maintainerQuoted 24 lines · Andreea-Cristina Bernat
The use of "
rcu_assign_pointer()" is NULLing out the pointer. According to RCU_INIT_POINTER()'s block comment:
"1. This use ofRCU_INIT_POINTER()is NULLing out the pointer"
it is better to use it instead ofrcu_assign_pointer()because it has a smaller overhead.The following Coccinelle semantic patch was used:
@@
@@-
rcu_assign_pointer
+RCU_INIT_POINTER
(..., NULL)Signed-off-by Andreea-Cristina Bernat <[email protected]>--- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/events/core.c +0
-0
kernel/events/core.c static void swevent_hlist_release(struct swevent_htable *swhash) · line 5749
Quoted 7 lines
kernel/events/core.c +1
-1@@ -5744,7 +5744,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)if (!hlist)return ; -rcu_assign_pointer (swhash->swevent_hlist,NULL ); +RCU_INIT_POINTER (swhash->swevent_hlist,NULL );kfree_rcu (hlist, rcu_head); }
Paul, why not do something like the below and do away with all this nonsense?
--- include/linux/rcupdate.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
include/linux/rcupdate.h +7 -1
@@ -623,7 +623,13 @@ static inline void rcu_preempt_sleep_check(void)* please be careful when making changes to rcu_assign_pointer() and the * other macros that it invokes. */ -#define rcu_assign_pointer (p, v) smp_store_release(&p, RCU_INITIALIZER(v)) +#define rcu_assign_pointer (p, v) \ +do { \ + if (__builtin_constant_p(v) && v == NULL) \ + p = RCU_INITIALIZER(v); \ + else \ + smp_store_release(&p, RCU_INITIALIZER(v)); \ +} while (0)/** * rcu_access_pointer() - fetch RCU pointer with no dereferencing
Quoted 28 lines · Peter Zijlstra
Quoted 27 lines · Andreea-Cristina Bernat
The use of "
rcu_assign_pointer()" is NULLing out the pointer. According to RCU_INIT_POINTER()'s block comment:
"1. This use ofRCU_INIT_POINTER()is NULLing out the pointer"
it is better to use it instead ofrcu_assign_pointer()because it has a smaller overhead.The following Coccinelle semantic patch was used:
@@
@@-
rcu_assign_pointer
+RCU_INIT_POINTER
(..., NULL)Signed-off-by Andreea-Cristina Bernat <[email protected]>--- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/events/core.c +0
-0@@ -5744,7 +5744,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)if (!hlist)return ;
Quoted 7 lines
kernel/events/core.c static void swevent_hlist_release(struct swevent_htable *swhash) · line 5749
Quoted 4 lines
kernel/events/core.c +1
-1-rcu_assign_pointer (swhash->swevent_hlist,NULL ); +RCU_INIT_POINTER (swhash->swevent_hlist,NULL );kfree_rcu (hlist, rcu_head); }Paul, why not do something like the below and do away with all this nonsense?
We used to do that, but the compilers became uncooperative, despite Stephen Hemminger's best efforts.
Thanx, Paul
Quoted 23 lines
--- include/linux/rcupdate.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)include/linux/rcupdate.h +7
-1@@ -623,7 +623,13 @@ static inline void rcu_preempt_sleep_check(void)* please be careful when making changes to rcu_assign_pointer() and the * other macros that it invokes. */ -#define rcu_assign_pointer (p, v) smp_store_release(&p, RCU_INITIALIZER(v)) +#define rcu_assign_pointer (p, v) \ +do { \ + if (__builtin_constant_p(v) && v == NULL) \ + p = RCU_INITIALIZER(v); \ + else \ + smp_store_release(&p, RCU_INITIALIZER(v)); \ +} while (0)/** * rcu_access_pointer() - fetch RCU pointer with no dereferencing
Peter Zijlstra
maintainerQuoted 7 lines · Paul E. McKenney
Quoted 2 lines · Peter Zijlstra
Paul, why not do something like the below and do away with all this nonsense?
We used to do that, but the compilers became uncooperative, despite Stephen Hemminger's best efforts.
Happen to have a link handy to that thread so I can educate myself?
Quoted 10 lines · Peter Zijlstra
Quoted 7 lines · Paul E. McKenney
Quoted 2 lines · Peter Zijlstra
Paul, why not do something like the below and do away with all this nonsense?
We used to do that, but the compilers became uncooperative, despite Stephen Hemminger's best efforts.
Happen to have a link handy to that thread so I can educate myself?
After a bit of software archeology, here you go...
Commit d322f45ceed52 (rcu: Make rcu_assign_pointer() unconditionally insert a memory barrier) made this change. According to the commit log:
Recent changes to gcc give warning messages on rcu_assign_pointers()'s checks that allow it to determine when it is OK to omit the memory barrier. Stephen Hemminger tried a number of gcc tricks to silence this warning, but #pragmas and CPP macros do not work together in the way that would be required to make this work.
This was applied in 2011, and searching LKML during that time gives the following: https://lkml.org/lkml/2011/7/29/305
And in this LKML post, Stephen Hemminger wrote:
Gcc now generates warnings from rcu_assign_pointer when passed the address of something for example:
rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
This warning is harmless and should be surpressed but there maybe other cases where we want that Gcc warning.
I tried various combinations of in rcu_assign_pointer macro
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
...
#pragma GCC diagnostic pop
but macro's and pragma's don't nest with the correct scope for this.
Maybe some one with more Gcc foo and time to waste could take a crack at it.
Adding Stephen on CC in case he remembers more.
Thanx, Paul
Peter Zijlstra
maintainerQuoted 43 lines · Paul E. McKenney
Quoted 10 lines · Peter Zijlstra
Quoted 7 lines · Paul E. McKenney
Quoted 2 lines · Peter Zijlstra
Paul, why not do something like the below and do away with all this nonsense?
We used to do that, but the compilers became uncooperative, despite Stephen Hemminger's best efforts.
Happen to have a link handy to that thread so I can educate myself?
After a bit of software archeology, here you go...
Commit
d322f45ceed52(rcu: Makercu_assign_pointer()unconditionally insert a memory barrier) made this change. According to the commit log:Recent changes to gcc give warning messages on rcu_assign_pointers()'s checks that allow it to determine when it is OK to omit the memory barrier. Stephen Hemminger tried a number of gcc tricks to silence this warning, but #pragmas and CPP macros do not work together in the way that would be required to make this work.
This was applied in 2011, and searching LKML during that time gives the following: https://lkml.org/lkml/2011/7/29/305
And in this LKML post, Stephen Hemminger wrote:
Gcc now generates warnings from
rcu_assign_pointerwhen passed the address of something for example:
rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
This warning is harmless and should be surpressed but there maybe other cases where we want that Gcc warning.I tried various combinations of in
rcu_assign_pointermacro
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
...
#pragma GCC diagnostic pop
but macro's and pragma's don't nest with the correct scope for this.
Quoted 4 lines
Maybe some one with more Gcc foo and time to waste could take a crack at it.
Adding Stephen on CC in case he remembers more.
So I read all that and am still left wondering WTF the problem was :/
I googled a bit and found this thread:
https://lkml.org/lkml/2014/3/24/39
Where Michael actually has two 'fixes' to the problem. Instead we continue clutter the API with this silly RCU_INIT_POINTER stuff, totally sad.
But nowhere have I found the actual warning GCC gives, I suppose I can go change my local tree and compile some code to obtain it, but that seems backwards. The patch 'working' around that should have mentioned it and explained why the warning is bogus or not.
Quoted 51 lines · Peter Zijlstra
Quoted 43 lines · Paul E. McKenney
Quoted 10 lines · Peter Zijlstra
Quoted 7 lines · Paul E. McKenney
Quoted 2 lines · Peter Zijlstra
Paul, why not do something like the below and do away with all this nonsense?
We used to do that, but the compilers became uncooperative, despite Stephen Hemminger's best efforts.
Happen to have a link handy to that thread so I can educate myself?
After a bit of software archeology, here you go...
Commit
d322f45ceed52(rcu: Makercu_assign_pointer()unconditionally insert a memory barrier) made this change. According to the commit log:Recent changes to gcc give warning messages on rcu_assign_pointers()'s checks that allow it to determine when it is OK to omit the memory barrier. Stephen Hemminger tried a number of gcc tricks to silence this warning, but #pragmas and CPP macros do not work together in the way that would be required to make this work.
This was applied in 2011, and searching LKML during that time gives the following: https://lkml.org/lkml/2011/7/29/305
And in this LKML post, Stephen Hemminger wrote:
Gcc now generates warnings from
rcu_assign_pointerwhen passed the address of something for example:
rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
This warning is harmless and should be surpressed but there maybe other cases where we want that Gcc warning.I tried various combinations of in
rcu_assign_pointermacro
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
...
#pragma GCC diagnostic pop
but macro's and pragma's don't nest with the correct scope for this.Quoted 4 lines
Maybe some one with more Gcc foo and time to waste could take a crack at it.
Adding Stephen on CC in case he remembers more.
So I read all that and am still left wondering WTF the problem was :/
Quoted 7 lines
I googled a bit and found this thread:
https://lkml.org/lkml/2014/3/24/39
Where Michael actually has two 'fixes' to the problem. Instead we continue clutter the API with this silly
RCU_INIT_POINTERstuff, totally sad.
Well, there are the other two use cases for RCU_INIT_POINTER().
But yes, most of the actual uses assign NULL.
Quoted 4 lines
But nowhere have I found the actual warning GCC gives, I suppose I can go change my local tree and compile some code to obtain it, but that seems backwards. The patch 'working' around that should have mentioned it and explained why the warning is bogus or not.
Indeed, I should have had a better commit log on the original change.
Thanx, Paul
tip-bot for Andreea-Cristina Bernat
merge bot[tip:perf/core] perf/core: Replace rcu_assign_pointer() with RCU_INIT_POINTER()
In reply to Andreea-Cristina Bernatperf/core: Replace rcu_assign_pointer() with RCU_INIT_POINTER()
Commit-ID: 70691d4a0bf7c871559d4ef1b0056edefbca123b Gitweb: http://git.kernel.org/tip/70691d4a0bf7c871559d4ef1b0056edefbca123b Author: Andreea-Cristina Bernat <[email protected]> AuthorDate: Fri, 22 Aug 2014 16:26:05 +0300 Committer: Ingo Molnar <[email protected]> CommitDate: Tue, 9 Sep 2014 06:53:05 +0200
perf/core: Replace rcu_assign_pointer() with RCU_INIT_POINTER()
The use of "rcu_assign_pointer()" is NULLing out the pointer. According to RCU_INIT_POINTER()'s block comment:
"1. This use of RCU_INIT_POINTER() is NULLing out the pointer"
it is better to use it instead of rcu_assign_pointer() because it has a smaller overhead.
The following Coccinelle semantic patch was used:
@@
@@
- rcu_assign_pointer
+ RCU_INIT_POINTER
(..., NULL)
--- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/events/core.c +1 -1
@@ -5908,7 +5908,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)if (!hlist)return ; -rcu_assign_pointer (swhash->swevent_hlist,NULL ); +RCU_INIT_POINTER (swhash->swevent_hlist,NULL );kfree_rcu (hlist, rcu_head); }