* why are some atomic_t's not volatile, while most are? @ 2007-07-01 12:49 Robert P. J. Day 2007-08-06 4:35 ` Jerry Jiang 0 siblings, 1 reply; 25+ messages in thread From: Robert P. J. Day @ 2007-07-01 12:49 UTC (permalink / raw) To: Linux Kernel Mailing List prompted by the earlier post on "volatile"s, is there a reason that most atomic_t typedefs use volatile int's, while the rest don't? $ grep "typedef.*struct" $(find . -name atomic.h) ./include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; ./include/asm-mips/atomic.h:typedef struct { volatile int counter; } atomic_t; ./include/asm-mips/atomic.h:typedef struct { volatile long counter; } atomic64_t; ... etc, etc. just curious. rday -- ======================================================================== Robert P. J. Day Linux Consulting, Training and Annoying Kernel Pedantry Waterloo, Ontario, CANADA http://fsdev.net/wiki/index.php?title=Main_Page ======================================================================== ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-07-01 12:49 why are some atomic_t's not volatile, while most are? Robert P. J. Day @ 2007-08-06 4:35 ` Jerry Jiang 2007-08-06 14:12 ` Chris Snook 0 siblings, 1 reply; 25+ messages in thread From: Jerry Jiang @ 2007-08-06 4:35 UTC (permalink / raw) To: Robert P. J. Day; +Cc: Linux Kernel Mailing List Is there some feedback on this point ? Thank you ./Jerry On Sun, 1 Jul 2007 08:49:37 -0400 (EDT) "Robert P. J. Day" <rpjday@mindspring.com> wrote: > > prompted by the earlier post on "volatile"s, is there a reason that > most atomic_t typedefs use volatile int's, while the rest don't? > > $ grep "typedef.*struct" $(find . -name atomic.h) > ./include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; > ./include/asm-mips/atomic.h:typedef struct { volatile int counter; } atomic_t; > ./include/asm-mips/atomic.h:typedef struct { volatile long counter; } atomic64_t; > ... > > etc, etc. just curious. > > rday > -- > ======================================================================== > Robert P. J. Day > Linux Consulting, Training and Annoying Kernel Pedantry > Waterloo, Ontario, CANADA > > http://fsdev.net/wiki/index.php?title=Main_Page > ======================================================================== > - > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > > ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-06 4:35 ` Jerry Jiang @ 2007-08-06 14:12 ` Chris Snook 2007-08-07 15:51 ` Chris Friesen 0 siblings, 1 reply; 25+ messages in thread From: Chris Snook @ 2007-08-06 14:12 UTC (permalink / raw) To: Jerry Jiang; +Cc: Robert P. J. Day, Linux Kernel Mailing List Jerry Jiang wrote: > Is there some feedback on this point ? > > Thank you > ./Jerry > > On Sun, 1 Jul 2007 08:49:37 -0400 (EDT) > "Robert P. J. Day" <rpjday@mindspring.com> wrote: > >> prompted by the earlier post on "volatile"s, is there a reason that >> most atomic_t typedefs use volatile int's, while the rest don't? >> >> $ grep "typedef.*struct" $(find . -name atomic.h) >> ./include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; >> ./include/asm-mips/atomic.h:typedef struct { volatile int counter; } atomic_t; >> ./include/asm-mips/atomic.h:typedef struct { volatile long counter; } atomic64_t; >> ... >> >> etc, etc. just curious. If your architecture doesn't support SMP, the volatile keyword doesn't do anything except add a useless memory fetch. Also, some SMP architectures (i386, x86_64, s390) provide sufficiently strong guarantees about memory access ordering that it's not necessary as long as you're using the appropriate locked/atomic instructions in the atomic operations. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-06 14:12 ` Chris Snook @ 2007-08-07 15:51 ` Chris Friesen 2007-08-07 20:32 ` Chris Snook 0 siblings, 1 reply; 25+ messages in thread From: Chris Friesen @ 2007-08-07 15:51 UTC (permalink / raw) To: Chris Snook; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Snook wrote: > If your architecture doesn't support SMP, the volatile keyword doesn't > do anything except add a useless memory fetch. I was under the impression that there were other cases as well (interrupt handlers, for instance) where the value could be modified "behind the back" of the current code. It seems like this would fall more into the case of the arch providing guarantees when using locked/atomic access rather than anything SMP-related, no?. Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 15:51 ` Chris Friesen @ 2007-08-07 20:32 ` Chris Snook 2007-08-07 21:02 ` Chris Friesen 2007-08-08 2:27 ` Jerry Jiang 0 siblings, 2 replies; 25+ messages in thread From: Chris Snook @ 2007-08-07 20:32 UTC (permalink / raw) To: Chris Friesen; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Friesen wrote: > Chris Snook wrote: > >> If your architecture doesn't support SMP, the volatile keyword doesn't >> do anything except add a useless memory fetch. > > I was under the impression that there were other cases as well > (interrupt handlers, for instance) where the value could be modified > "behind the back" of the current code. When you're accessing data that could be modified by an interrupt handler, you generally use a function that calls arch-specific inline assembler to explicitly fetch it from memory. > It seems like this would fall more into the case of the arch providing > guarantees when using locked/atomic access rather than anything > SMP-related, no?. But if you're not using SMP, the only way you get a race condition is if your compiler is reordering instructions that have side effects which are invisible to the compiler. This can happen with MMIO registers, but it's not an issue with an atomic_t we're declaring in real memory. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 20:32 ` Chris Snook @ 2007-08-07 21:02 ` Chris Friesen 2007-08-07 21:19 ` Chris Snook 2007-08-08 2:27 ` Jerry Jiang 1 sibling, 1 reply; 25+ messages in thread From: Chris Friesen @ 2007-08-07 21:02 UTC (permalink / raw) To: Chris Snook; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Snook wrote: > But if you're not using SMP, the only way you get a race condition is if > your compiler is reordering instructions that have side effects which > are invisible to the compiler. This can happen with MMIO registers, but > it's not an issue with an atomic_t we're declaring in real memory. I refer back to the interrupt handler case. Suppose we have: while(!atomic_read(flag)) continue; where flag is an atomic_t that is set in an interrupt handler, the volatile may be necessary on some architectures to force the compiler to re-read "flag" each time through the loop. Without the "volatile", the compiler could be perfectly within its rights to evaluate "flag" once and create an infinite loop. Now I'm not trying to say that we should explictly use "volatile" in common code, but that it is possible that it is required within the arch-specific atomic_t accessors even on uniprocessor systems. Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 21:02 ` Chris Friesen @ 2007-08-07 21:19 ` Chris Snook 2007-08-07 21:38 ` Chris Friesen 0 siblings, 1 reply; 25+ messages in thread From: Chris Snook @ 2007-08-07 21:19 UTC (permalink / raw) To: Chris Friesen; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Friesen wrote: > Chris Snook wrote: > >> But if you're not using SMP, the only way you get a race condition is >> if your compiler is reordering instructions that have side effects >> which are invisible to the compiler. This can happen with MMIO >> registers, but it's not an issue with an atomic_t we're declaring in >> real memory. > > I refer back to the interrupt handler case. Suppose we have: > > while(!atomic_read(flag)) > continue; > > where flag is an atomic_t that is set in an interrupt handler, the > volatile may be necessary on some architectures to force the compiler to > re-read "flag" each time through the loop. > > Without the "volatile", the compiler could be perfectly within its > rights to evaluate "flag" once and create an infinite loop. > > Now I'm not trying to say that we should explictly use "volatile" in > common code, but that it is possible that it is required within the > arch-specific atomic_t accessors even on uniprocessor systems. > > Chris That's why we define atomic_read like so: #define atomic_read(v) ((v)->counter) This avoids the aliasing problem, because the compiler must de-reference the pointer every time, which requires a memory fetch. This is usually fast thanks to caching, and hardware cache invalidation enforces correctness when it does change. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 21:19 ` Chris Snook @ 2007-08-07 21:38 ` Chris Friesen 2007-08-07 22:02 ` Chris Snook ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: Chris Friesen @ 2007-08-07 21:38 UTC (permalink / raw) To: Chris Snook; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Snook wrote: > That's why we define atomic_read like so: > > #define atomic_read(v) ((v)->counter) > > This avoids the aliasing problem, because the compiler must de-reference > the pointer every time, which requires a memory fetch. Can you guarantee that the pointer dereference cannot be optimised away on any architecture? Without other restrictions, a suficiently intelligent optimiser could notice that the address of v doesn't change in the loop and the destination is never written within the loop, so the read could be hoisted out of the loop. Even now, powerpc (as an example) defines atomic_t as: typedef struct { volatile int counter; } atomic_t That volatile is there precisely to force the compiler to dereference it every single time. Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 21:38 ` Chris Friesen @ 2007-08-07 22:02 ` Chris Snook 2007-08-07 22:46 ` Chris Friesen 2007-08-07 22:06 ` Jan Engelhardt 2007-08-07 22:32 ` Zan Lynx 2 siblings, 1 reply; 25+ messages in thread From: Chris Snook @ 2007-08-07 22:02 UTC (permalink / raw) To: Chris Friesen; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Friesen wrote: > Chris Snook wrote: > >> That's why we define atomic_read like so: >> >> #define atomic_read(v) ((v)->counter) >> >> This avoids the aliasing problem, because the compiler must >> de-reference the pointer every time, which requires a memory fetch. > > Can you guarantee that the pointer dereference cannot be optimised away > on any architecture? Without other restrictions, a suficiently > intelligent optimiser could notice that the address of v doesn't change > in the loop and the destination is never written within the loop, so the > read could be hoisted out of the loop. That would be a compiler bug. > Even now, powerpc (as an example) defines atomic_t as: > > typedef struct { volatile int counter; } atomic_t > > > That volatile is there precisely to force the compiler to dereference it > every single time. On most superscalar architectures, including powerpc, multiple instructions can be in flight simultaneously, potentially even reading and writing the same data. When the compiler detects data dependencies within a thread of execution, it will do the right thing. Putting the volatile keyword in here instructs the compiler to serialize accesses to this data even if it does not detect dependencies. It's worth noting that all of the SMP architectures which lack the volatile keyword in their atomic_t definition inherit memory access semantics from ISAs that predate the advent of heavily-pipelined superscalar design. i386 and x86_64 get theirs from at least as far back as the 8086. I believe s390(x) inherits this from the s/370 ISA. These ISAs assume strictly serialized memory access, and anything binary-compatible with them must enforce this in hardware, even at the expense of performance. Modern ISAs that lack legacy baggage do away with this guarantee, putting the burden on the compiler to enforce serialization. When the compiler can't detect that it's needed, we use volatile to inform it explicitly. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 22:02 ` Chris Snook @ 2007-08-07 22:46 ` Chris Friesen 0 siblings, 0 replies; 25+ messages in thread From: Chris Friesen @ 2007-08-07 22:46 UTC (permalink / raw) To: Chris Snook; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Snook wrote: > Chris Friesen wrote: >> Without other restrictions, a suficiently >> intelligent optimiser could notice that the address of v doesn't >> change in the loop and the destination is never written within the >> loop, so the read could be hoisted out of the loop. > That would be a compiler bug. Could you elaborate? From the point of view of the compiler, it "knows" that the variable doesn't change inside the loop. In the "volatile considered evil" discussion in May of this year, Alan Cox explicitly mentioned the implementation of atomic primitives as a case where "volatile" might be required. > On most superscalar architectures, including powerpc, multiple > instructions can be in flight simultaneously, potentially even reading > and writing the same data. When the compiler detects data dependencies > within a thread of execution, it will do the right thing. In the example I gave, as far as the compiler can detect there are no dependencies. The code that changes the value is in a different compilation unit. > Modern ISAs that lack legacy baggage do away > with this guarantee, putting the burden on the compiler to enforce > serialization. When the compiler can't detect that it's needed, we use > volatile to inform it explicitly. I certainly agree with this statement. This leads logically to the question of whether there are cases where the compiler cannot detect that serialization is needed when implementing atomic_t accessor functions. Previously in this thread you've said that there are not, while I've attempted to show that it is possible. Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 21:38 ` Chris Friesen 2007-08-07 22:02 ` Chris Snook @ 2007-08-07 22:06 ` Jan Engelhardt 2007-08-07 22:49 ` Chris Friesen 2007-08-07 22:32 ` Zan Lynx 2 siblings, 1 reply; 25+ messages in thread From: Jan Engelhardt @ 2007-08-07 22:06 UTC (permalink / raw) To: Chris Friesen Cc: Chris Snook, Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List On Aug 7 2007 15:38, Chris Friesen wrote: > Even now, powerpc (as an example) defines atomic_t as: > > typedef struct { volatile int counter; } atomic_t > > > That volatile is there precisely to force the compiler to dereference it every > single time. Actually, the dereference will be done once (or more often if registers are short or the compiler does not feel like keeping it around), and the read from memory will be done on every iteration ;-) Jan -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 22:06 ` Jan Engelhardt @ 2007-08-07 22:49 ` Chris Friesen 0 siblings, 0 replies; 25+ messages in thread From: Chris Friesen @ 2007-08-07 22:49 UTC (permalink / raw) To: Jan Engelhardt Cc: Chris Snook, Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Jan Engelhardt wrote: > On Aug 7 2007 15:38, Chris Friesen wrote: >>That volatile is there precisely to force the compiler to dereference it every >>single time. > Actually, the dereference will be done once (or more often if registers > are short or the compiler does not feel like keeping it around), > and the read from memory will be done on every iteration ;-) My bad. You are, of course, correct. :) Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 21:38 ` Chris Friesen 2007-08-07 22:02 ` Chris Snook 2007-08-07 22:06 ` Jan Engelhardt @ 2007-08-07 22:32 ` Zan Lynx 2007-08-08 1:31 ` Chris Snook 2 siblings, 1 reply; 25+ messages in thread From: Zan Lynx @ 2007-08-07 22:32 UTC (permalink / raw) To: Chris Friesen; +Cc: Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 1713 bytes --] On Tue, 2007-08-07 at 15:38 -0600, Chris Friesen wrote: > Chris Snook wrote: > > > That's why we define atomic_read like so: > > > > #define atomic_read(v) ((v)->counter) > > > > This avoids the aliasing problem, because the compiler must de-reference > > the pointer every time, which requires a memory fetch. > > Can you guarantee that the pointer dereference cannot be optimised away > on any architecture? Without other restrictions, a suficiently > intelligent optimiser could notice that the address of v doesn't change > in the loop and the destination is never written within the loop, so the > read could be hoisted out of the loop. > > Even now, powerpc (as an example) defines atomic_t as: > > typedef struct { volatile int counter; } atomic_t > > > That volatile is there precisely to force the compiler to dereference it > every single time. I just tried this with GCC 4.2 on x86_64 because I was curious. struct counter_t { volatile int counter; } test; struct counter_t *tptr = &test; int main() { int i; tptr->counter = 0; i = 0; while(tptr->counter < 100) { i++; } return 0; } $ gcc -O3 -S t.c a snippet of t.s: main: .LFB2: movq tptr(%rip), %rdx movl $0, (%rdx) .p2align 4,,7 .L2: movl (%rdx), %eax cmpl $99, %eax jle .L2 Now with the volatile removed: main: .LFB2: movq tptr(%rip), %rax movl $0, (%rax) .L2: jmp .L2 If the compiler can see it clearly, it will optimize out the load without the volatile. -- Zan Lynx <zlynx@acm.org> [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 22:32 ` Zan Lynx @ 2007-08-08 1:31 ` Chris Snook 2007-08-08 4:50 ` Chris Friesen 0 siblings, 1 reply; 25+ messages in thread From: Chris Snook @ 2007-08-08 1:31 UTC (permalink / raw) To: Zan Lynx Cc: Chris Friesen, Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Zan Lynx wrote: > On Tue, 2007-08-07 at 15:38 -0600, Chris Friesen wrote: >> Chris Snook wrote: >> >>> That's why we define atomic_read like so: >>> >>> #define atomic_read(v) ((v)->counter) >>> >>> This avoids the aliasing problem, because the compiler must de-reference >>> the pointer every time, which requires a memory fetch. >> Can you guarantee that the pointer dereference cannot be optimised away >> on any architecture? Without other restrictions, a suficiently >> intelligent optimiser could notice that the address of v doesn't change >> in the loop and the destination is never written within the loop, so the >> read could be hoisted out of the loop. >> >> Even now, powerpc (as an example) defines atomic_t as: >> >> typedef struct { volatile int counter; } atomic_t >> >> >> That volatile is there precisely to force the compiler to dereference it >> every single time. > > I just tried this with GCC 4.2 on x86_64 because I was curious. > > struct counter_t { volatile int counter; } test; > struct counter_t *tptr = &test; > > int main() { > int i; > > tptr->counter = 0; > i = 0; > while(tptr->counter < 100) { > i++; > } > return 0; > } > > $ gcc -O3 -S t.c > > a snippet of t.s: > main: > .LFB2: > movq tptr(%rip), %rdx > movl $0, (%rdx) > .p2align 4,,7 > .L2: > movl (%rdx), %eax > cmpl $99, %eax > jle .L2 > > > Now with the volatile removed: > main: > .LFB2: > movq tptr(%rip), %rax > movl $0, (%rax) > .L2: > jmp .L2 > > If the compiler can see it clearly, it will optimize out the load > without the volatile. This is not a problem, since indirect references will cause the CPU to fetch the data from memory/cache anyway. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 1:31 ` Chris Snook @ 2007-08-08 4:50 ` Chris Friesen 2007-08-08 6:47 ` Chris Snook 0 siblings, 1 reply; 25+ messages in thread From: Chris Friesen @ 2007-08-08 4:50 UTC (permalink / raw) To: Chris Snook Cc: Zan Lynx, Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Snook wrote: > This is not a problem, since indirect references will cause the CPU to > fetch the data from memory/cache anyway. Isn't Zan's sample code (that shows the problem) already using indirect references? Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 4:50 ` Chris Friesen @ 2007-08-08 6:47 ` Chris Snook 2007-08-08 8:16 ` Jerry Jiang 2007-08-08 8:27 ` Jerry Jiang 0 siblings, 2 replies; 25+ messages in thread From: Chris Snook @ 2007-08-08 6:47 UTC (permalink / raw) To: Chris Friesen Cc: Zan Lynx, Jerry Jiang, Robert P. J. Day, Linux Kernel Mailing List Chris Friesen wrote: > Chris Snook wrote: > >> This is not a problem, since indirect references will cause the CPU to >> fetch the data from memory/cache anyway. > > Isn't Zan's sample code (that shows the problem) already using indirect > references? Yeah, I misinterpreted his conclusion. I thought about this for a while, and realized that it's perfectly legal for the compiler to re-use a value obtained from atomic_read. All that matters is that the read itself was atomic. The use (or non-use) of the volatile keyword is really more relevant to the other atomic operations. If you want to guarantee a re-read from memory, use barrier(). This, incidentally, uses volatile under the hood. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 6:47 ` Chris Snook @ 2007-08-08 8:16 ` Jerry Jiang 2007-08-08 8:27 ` Jerry Jiang 1 sibling, 0 replies; 25+ messages in thread From: Jerry Jiang @ 2007-08-08 8:16 UTC (permalink / raw) To: Chris Snook Cc: Chris Friesen, Zan Lynx, Robert P. J. Day, Linux Kernel Mailing List On Wed, 08 Aug 2007 02:47:53 -0400 Chris Snook <csnook@redhat.com> wrote: > Chris Friesen wrote: > > Chris Snook wrote: > > > >> This is not a problem, since indirect references will cause the CPU to > >> fetch the data from memory/cache anyway. > > > > Isn't Zan's sample code (that shows the problem) already using indirect > > references? > > Yeah, I misinterpreted his conclusion. I thought about this for a > while, and realized that it's perfectly legal for the compiler to re-use > a value obtained from atomic_read. All that matters is that the read > itself was atomic. The use (or non-use) of the volatile keyword is Sorry, I can't understand it a bit .., Could you do in detail? -- Jerry > really more relevant to the other atomic operations. If you want to > guarantee a re-read from memory, use barrier(). This, incidentally, > uses volatile under the hood. > > -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 6:47 ` Chris Snook 2007-08-08 8:16 ` Jerry Jiang @ 2007-08-08 8:27 ` Jerry Jiang 2007-08-08 20:54 ` Chris Snook 1 sibling, 1 reply; 25+ messages in thread From: Jerry Jiang @ 2007-08-08 8:27 UTC (permalink / raw) To: Chris Snook Cc: Chris Friesen, Zan Lynx, Robert P. J. Day, Linux Kernel Mailing List On Wed, 08 Aug 2007 02:47:53 -0400 Chris Snook <csnook@redhat.com> wrote: > Chris Friesen wrote: > > Chris Snook wrote: > > > >> This is not a problem, since indirect references will cause the CPU to > >> fetch the data from memory/cache anyway. > > > > Isn't Zan's sample code (that shows the problem) already using indirect > > references? > > Yeah, I misinterpreted his conclusion. I thought about this for a > while, and realized that it's perfectly legal for the compiler to re-use > a value obtained from atomic_read. All that matters is that the read > itself was atomic. The use (or non-use) of the volatile keyword is > really more relevant to the other atomic operations. If you want to > guarantee a re-read from memory, use barrier(). This, incidentally, > uses volatile under the hood. > So for example, without volatile int a = read_atomic(v); int b = read_atomic(v); the compiler will optimize it as b = a, But with volatile, it will be forced to fetch v's value from memory again. So, come back our initial question, include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; Why is it right without volatile? -- Jerry > -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 8:27 ` Jerry Jiang @ 2007-08-08 20:54 ` Chris Snook 2007-08-09 12:37 ` Robert P. J. Day 0 siblings, 1 reply; 25+ messages in thread From: Chris Snook @ 2007-08-08 20:54 UTC (permalink / raw) To: Jerry Jiang Cc: Chris Friesen, Zan Lynx, Robert P. J. Day, Linux Kernel Mailing List Jerry Jiang wrote: > On Wed, 08 Aug 2007 02:47:53 -0400 > Chris Snook <csnook@redhat.com> wrote: > >> Chris Friesen wrote: >>> Chris Snook wrote: >>> >>>> This is not a problem, since indirect references will cause the CPU to >>>> fetch the data from memory/cache anyway. >>> Isn't Zan's sample code (that shows the problem) already using indirect >>> references? >> Yeah, I misinterpreted his conclusion. I thought about this for a >> while, and realized that it's perfectly legal for the compiler to re-use >> a value obtained from atomic_read. All that matters is that the read >> itself was atomic. The use (or non-use) of the volatile keyword is >> really more relevant to the other atomic operations. If you want to >> guarantee a re-read from memory, use barrier(). This, incidentally, >> uses volatile under the hood. >> > > > So for example, without volatile > > int a = read_atomic(v); > int b = read_atomic(v); > > the compiler will optimize it as b = a, > But with volatile, it will be forced to fetch v's value from memory > again. > > So, come back our initial question, > > include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; > > Why is it right without volatile? Because atomic_t doesn't promise a memory fetch every time. It merely promises that any atomic_* operations will, in fact, be atomic. For example, posted today: http://lkml.org/lkml/2007/8/8/122 -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 20:54 ` Chris Snook @ 2007-08-09 12:37 ` Robert P. J. Day 2007-08-09 12:52 ` Chris Snook 0 siblings, 1 reply; 25+ messages in thread From: Robert P. J. Day @ 2007-08-09 12:37 UTC (permalink / raw) To: Chris Snook Cc: Jerry Jiang, Chris Friesen, Zan Lynx, Linux Kernel Mailing List On Wed, 8 Aug 2007, Chris Snook wrote: > Jerry Jiang wrote: > > On Wed, 08 Aug 2007 02:47:53 -0400 > > Chris Snook <csnook@redhat.com> wrote: > > > > > Chris Friesen wrote: > > > > Chris Snook wrote: > > > > > > > > > This is not a problem, since indirect references will cause the CPU to > > > > > fetch the data from memory/cache anyway. > > > > Isn't Zan's sample code (that shows the problem) already using indirect > > > > references? > > > Yeah, I misinterpreted his conclusion. I thought about this for a while, > > > and realized that it's perfectly legal for the compiler to re-use a value > > > obtained from atomic_read. All that matters is that the read itself was > > > atomic. The use (or non-use) of the volatile keyword is really more > > > relevant to the other atomic operations. If you want to guarantee a > > > re-read from memory, use barrier(). This, incidentally, uses volatile > > > under the hood. > > > > > > > > > So for example, without volatile > > > > int a = read_atomic(v); > > int b = read_atomic(v); > > > > the compiler will optimize it as b = a, But with volatile, it will be forced > > to fetch v's value from memory > > again. > > > > So, come back our initial question, > > include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; > > > > Why is it right without volatile? > > Because atomic_t doesn't promise a memory fetch every time. It merely > promises that any atomic_* operations will, in fact, be atomic. For example, > posted today: > > http://lkml.org/lkml/2007/8/8/122 i'm sure that, when this is all done, i'll finally have an answer to my original question, "why are some atomic_t's not volatile, while most are?" i'm almost scared to ask any more questions. :-) rday -- ======================================================================== Robert P. J. Day Linux Consulting, Training and Annoying Kernel Pedantry Waterloo, Ontario, CANADA http://fsdev.net/wiki/index.php?title=Main_Page ======================================================================== ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-09 12:37 ` Robert P. J. Day @ 2007-08-09 12:52 ` Chris Snook 2007-08-09 18:02 ` Robert P. J. Day 0 siblings, 1 reply; 25+ messages in thread From: Chris Snook @ 2007-08-09 12:52 UTC (permalink / raw) To: Robert P. J. Day Cc: Jerry Jiang, Chris Friesen, Zan Lynx, Linux Kernel Mailing List Robert P. J. Day wrote: > On Wed, 8 Aug 2007, Chris Snook wrote: > >> Jerry Jiang wrote: >>> On Wed, 08 Aug 2007 02:47:53 -0400 >>> Chris Snook <csnook@redhat.com> wrote: >>> >>>> Chris Friesen wrote: >>>>> Chris Snook wrote: >>>>> >>>>>> This is not a problem, since indirect references will cause the CPU to >>>>>> fetch the data from memory/cache anyway. >>>>> Isn't Zan's sample code (that shows the problem) already using indirect >>>>> references? >>>> Yeah, I misinterpreted his conclusion. I thought about this for a while, >>>> and realized that it's perfectly legal for the compiler to re-use a value >>>> obtained from atomic_read. All that matters is that the read itself was >>>> atomic. The use (or non-use) of the volatile keyword is really more >>>> relevant to the other atomic operations. If you want to guarantee a >>>> re-read from memory, use barrier(). This, incidentally, uses volatile >>>> under the hood. >>>> >>> >>> So for example, without volatile >>> >>> int a = read_atomic(v); >>> int b = read_atomic(v); >>> >>> the compiler will optimize it as b = a, But with volatile, it will be forced >>> to fetch v's value from memory >>> again. >>> >>> So, come back our initial question, >>> include/asm-v850/atomic.h:typedef struct { int counter; } atomic_t; >>> >>> Why is it right without volatile? >> Because atomic_t doesn't promise a memory fetch every time. It merely >> promises that any atomic_* operations will, in fact, be atomic. For example, >> posted today: >> >> http://lkml.org/lkml/2007/8/8/122 > > i'm sure that, when this is all done, i'll finally have an answer to > my original question, "why are some atomic_t's not volatile, while > most are?" > > i'm almost scared to ask any more questions. :-) > > rday Momentarily I'll be posting a patchset that makes all atomic_t and atomic64_t declarations non-volatile, and casts them to volatile inside of atomic[64]_read. This will ensure consistent behavior across all architectures, and is in keeping with the philosophy that memory reads should be enforced in running code, not declarations. I hope you don't mind that we're mooting the question by making the code more sensible. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-09 12:52 ` Chris Snook @ 2007-08-09 18:02 ` Robert P. J. Day 2007-08-09 18:04 ` Robert P. J. Day 0 siblings, 1 reply; 25+ messages in thread From: Robert P. J. Day @ 2007-08-09 18:02 UTC (permalink / raw) To: Chris Snook Cc: Jerry Jiang, Chris Friesen, Zan Lynx, Linux Kernel Mailing List On Thu, 9 Aug 2007, Chris Snook wrote: > Robert P. J. Day wrote: > > i'm almost scared to ask any more questions. :-) > > > > rday > > Momentarily I'll be posting a patchset that makes all atomic_t and > atomic64_t declarations non-volatile, and casts them to volatile > inside of atomic[64]_read. This will ensure consistent behavior > across all architectures, and is in keeping with the philosophy that > memory reads should be enforced in running code, not declarations. > > I hope you don't mind that we're mooting the question by making the > code more sensible. not at all, but it does bring up the obvious next question -- once all these definitions are made consistent, is there any reason some of that content can't be centralized in a single atomic.h header file, rather than duplicating it across a couple dozen architectures? surely, after this process, there's going to be some content that's identical across all arches, no? rday ======================================================================== Robert P. J. Day Linux Consulting, Training and Annoying Kernel Pedantry Waterloo, Ontario, CANADA http://fsdev.net/wiki/index.php?title=Main_Page ======================================================================== ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-09 18:02 ` Robert P. J. Day @ 2007-08-09 18:04 ` Robert P. J. Day 0 siblings, 0 replies; 25+ messages in thread From: Robert P. J. Day @ 2007-08-09 18:04 UTC (permalink / raw) To: Chris Snook Cc: Jerry Jiang, Chris Friesen, Zan Lynx, Linux Kernel Mailing List On Thu, 9 Aug 2007, Robert P. J. Day wrote: > On Thu, 9 Aug 2007, Chris Snook wrote: > > > Robert P. J. Day wrote: > > > > i'm almost scared to ask any more questions. :-) > > > > > > rday > > > > Momentarily I'll be posting a patchset that makes all atomic_t and > > atomic64_t declarations non-volatile, and casts them to volatile > > inside of atomic[64]_read. This will ensure consistent behavior > > across all architectures, and is in keeping with the philosophy that > > memory reads should be enforced in running code, not declarations. > > > > I hope you don't mind that we're mooting the question by making the > > code more sensible. > > not at all, but it does bring up the obvious next question -- once all > these definitions are made consistent, is there any reason some of > that content can't be centralized in a single atomic.h header file, > rather than duplicating it across a couple dozen architectures? > > surely, after this process, there's going to be some content that's > identical across all arches, no? > > rday whoops, never mind, i just saw that earlier posting on this very subject. rday -- ======================================================================== Robert P. J. Day Linux Consulting, Training and Annoying Kernel Pedantry Waterloo, Ontario, CANADA http://fsdev.net/wiki/index.php?title=Main_Page ======================================================================== ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-07 20:32 ` Chris Snook 2007-08-07 21:02 ` Chris Friesen @ 2007-08-08 2:27 ` Jerry Jiang 2007-08-08 5:39 ` Chris Snook 1 sibling, 1 reply; 25+ messages in thread From: Jerry Jiang @ 2007-08-08 2:27 UTC (permalink / raw) To: Chris Snook; +Cc: Chris Friesen, Robert P. J. Day, Linux Kernel Mailing List On Tue, 07 Aug 2007 16:32:23 -0400 Chris Snook <csnook@redhat.com> wrote: > > It seems like this would fall more into the case of the arch providing > > guarantees when using locked/atomic access rather than anything > > SMP-related, no?. > > But if you're not using SMP, the only way you get a race condition is if your > compiler is reordering instructions that have side effects which are invisible > to the compiler. This can happen with MMIO registers, but it's not an issue > with an atomic_t we're declaring in real memory. > Under non-SMP, some compilers would reordering instructions as they think and C standard informally guarantees all operations on volatile data are executed in the sequence in which they appear in the source code, right? So no reordering happens with volatile, right? -- Jerry > -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: why are some atomic_t's not volatile, while most are? 2007-08-08 2:27 ` Jerry Jiang @ 2007-08-08 5:39 ` Chris Snook 0 siblings, 0 replies; 25+ messages in thread From: Chris Snook @ 2007-08-08 5:39 UTC (permalink / raw) To: Jerry Jiang; +Cc: Chris Friesen, Robert P. J. Day, Linux Kernel Mailing List Jerry Jiang wrote: > On Tue, 07 Aug 2007 16:32:23 -0400 > Chris Snook <csnook@redhat.com> wrote: > >>> It seems like this would fall more into the case of the arch providing >>> guarantees when using locked/atomic access rather than anything >>> SMP-related, no?. >> But if you're not using SMP, the only way you get a race condition is if your >> compiler is reordering instructions that have side effects which are invisible >> to the compiler. This can happen with MMIO registers, but it's not an issue >> with an atomic_t we're declaring in real memory. >> > > Under non-SMP, some compilers would reordering instructions as they think > and C standard informally guarantees all operations on volatile data > are executed in the sequence in which they appear in the source code, > right? > > So no reordering happens with volatile, right? Plenty of reordering happens with volatile, but on VLIW, EPIC, and similar architectures, it ensures that accesses to the variable in question will not be compiled into instruction slots that can execute simultaneously. -- Chris ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2007-08-09 18:10 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2007-07-01 12:49 why are some atomic_t's not volatile, while most are? Robert P. J. Day 2007-08-06 4:35 ` Jerry Jiang 2007-08-06 14:12 ` Chris Snook 2007-08-07 15:51 ` Chris Friesen 2007-08-07 20:32 ` Chris Snook 2007-08-07 21:02 ` Chris Friesen 2007-08-07 21:19 ` Chris Snook 2007-08-07 21:38 ` Chris Friesen 2007-08-07 22:02 ` Chris Snook 2007-08-07 22:46 ` Chris Friesen 2007-08-07 22:06 ` Jan Engelhardt 2007-08-07 22:49 ` Chris Friesen 2007-08-07 22:32 ` Zan Lynx 2007-08-08 1:31 ` Chris Snook 2007-08-08 4:50 ` Chris Friesen 2007-08-08 6:47 ` Chris Snook 2007-08-08 8:16 ` Jerry Jiang 2007-08-08 8:27 ` Jerry Jiang 2007-08-08 20:54 ` Chris Snook 2007-08-09 12:37 ` Robert P. J. Day 2007-08-09 12:52 ` Chris Snook 2007-08-09 18:02 ` Robert P. J. Day 2007-08-09 18:04 ` Robert P. J. Day 2007-08-08 2:27 ` Jerry Jiang 2007-08-08 5:39 ` Chris Snook
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).