diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2011-11-22 13:55:12 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2011-12-11 13:31:58 -0500 |
commit | 182dd4b277177e8465ad11cd9f85f282946b5578 (patch) | |
tree | 3fa8d555651b04ba39b871c8ffb7cb9cb2c6f512 /Documentation/atomic_ops.txt | |
parent | 1268fbc746ea1cd279886a740dcbad4ba5232225 (diff) |
doc: Add load/store guarantees to Documentation/atomic-ops.txt
An IRC discussion uncovered many conflicting opinions on what types
of data may be atomically loaded and stored. This commit therefore
calls this out the official set: pointers, longs, ints, and chars (but
not shorts). This commit also gives some examples of compiler mischief
that can thwart atomicity.
Please note that this discussion is relevant to !SMP kernels if
CONFIG_PREEMPT=y: preemption can cause almost as much trouble as can SMP.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Mikael Starvik <starvik@axis.com>
Cc: Jesper Nilsson <jesper.nilsson@axis.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Richard Kuo <rkuo@codeaurora.org>
Cc: Jes Sorensen <jes@sgi.com>
Cc: Hirokazu Takata <takata@linux-m32r.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Helge Deller <deller@gmx.de>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Chen Liqin <liqin.chen@sunplusct.com>
Cc: Lennox Wu <lennox.wu@gmail.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'Documentation/atomic_ops.txt')
-rw-r--r-- | Documentation/atomic_ops.txt | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt index 3bd585b44927..27f2b21a9d5c 100644 --- a/Documentation/atomic_ops.txt +++ b/Documentation/atomic_ops.txt | |||
@@ -84,6 +84,93 @@ compiler optimizes the section accessing atomic_t variables. | |||
84 | 84 | ||
85 | *** YOU HAVE BEEN WARNED! *** | 85 | *** YOU HAVE BEEN WARNED! *** |
86 | 86 | ||
87 | Properly aligned pointers, longs, ints, and chars (and unsigned | ||
88 | equivalents) may be atomically loaded from and stored to in the same | ||
89 | sense as described for atomic_read() and atomic_set(). The ACCESS_ONCE() | ||
90 | macro should be used to prevent the compiler from using optimizations | ||
91 | that might otherwise optimize accesses out of existence on the one hand, | ||
92 | or that might create unsolicited accesses on the other. | ||
93 | |||
94 | For example consider the following code: | ||
95 | |||
96 | while (a > 0) | ||
97 | do_something(); | ||
98 | |||
99 | If the compiler can prove that do_something() does not store to the | ||
100 | variable a, then the compiler is within its rights transforming this to | ||
101 | the following: | ||
102 | |||
103 | tmp = a; | ||
104 | if (a > 0) | ||
105 | for (;;) | ||
106 | do_something(); | ||
107 | |||
108 | If you don't want the compiler to do this (and you probably don't), then | ||
109 | you should use something like the following: | ||
110 | |||
111 | while (ACCESS_ONCE(a) < 0) | ||
112 | do_something(); | ||
113 | |||
114 | Alternatively, you could place a barrier() call in the loop. | ||
115 | |||
116 | For another example, consider the following code: | ||
117 | |||
118 | tmp_a = a; | ||
119 | do_something_with(tmp_a); | ||
120 | do_something_else_with(tmp_a); | ||
121 | |||
122 | If the compiler can prove that do_something_with() does not store to the | ||
123 | variable a, then the compiler is within its rights to manufacture an | ||
124 | additional load as follows: | ||
125 | |||
126 | tmp_a = a; | ||
127 | do_something_with(tmp_a); | ||
128 | tmp_a = a; | ||
129 | do_something_else_with(tmp_a); | ||
130 | |||
131 | This could fatally confuse your code if it expected the same value | ||
132 | to be passed to do_something_with() and do_something_else_with(). | ||
133 | |||
134 | The compiler would be likely to manufacture this additional load if | ||
135 | do_something_with() was an inline function that made very heavy use | ||
136 | of registers: reloading from variable a could save a flush to the | ||
137 | stack and later reload. To prevent the compiler from attacking your | ||
138 | code in this manner, write the following: | ||
139 | |||
140 | tmp_a = ACCESS_ONCE(a); | ||
141 | do_something_with(tmp_a); | ||
142 | do_something_else_with(tmp_a); | ||
143 | |||
144 | For a final example, consider the following code, assuming that the | ||
145 | variable a is set at boot time before the second CPU is brought online | ||
146 | and never changed later, so that memory barriers are not needed: | ||
147 | |||
148 | if (a) | ||
149 | b = 9; | ||
150 | else | ||
151 | b = 42; | ||
152 | |||
153 | The compiler is within its rights to manufacture an additional store | ||
154 | by transforming the above code into the following: | ||
155 | |||
156 | b = 42; | ||
157 | if (a) | ||
158 | b = 9; | ||
159 | |||
160 | This could come as a fatal surprise to other code running concurrently | ||
161 | that expected b to never have the value 42 if a was zero. To prevent | ||
162 | the compiler from doing this, write something like: | ||
163 | |||
164 | if (a) | ||
165 | ACCESS_ONCE(b) = 9; | ||
166 | else | ||
167 | ACCESS_ONCE(b) = 42; | ||
168 | |||
169 | Don't even -think- about doing this without proper use of memory barriers, | ||
170 | locks, or atomic operations if variable a can change at runtime! | ||
171 | |||
172 | *** WARNING: ACCESS_ONCE() DOES NOT IMPLY A BARRIER! *** | ||
173 | |||
87 | Now, we move onto the atomic operation interfaces typically implemented with | 174 | Now, we move onto the atomic operation interfaces typically implemented with |
88 | the help of assembly code. | 175 | the help of assembly code. |
89 | 176 | ||