Live data from Hacker News

Ways to break your systems code using volatile (2010)

blog.regehr.org

21–30 of 77 posts

Re: Ways to break your systems code using volatile (2010)

#22
post #20

Earlier quoted context omitted.

> I think the implication is that the TLB is not consulted at all This is not true.

Could you clarify? I am merely a student of that class and we didn't discuss TLBs in detail so I'm all ears for details.

On an architecture with virtual protected memory (the one being described in the slides) there is no compiler control over the TLB. There is no mechanism for the compiler to bypass it. It isn't the semantics in theory or in practice for volatile to bypass almost anything on that list you have for the non-volatile case. It just isn't true. There must be some misunderstanding somewhere that is only clarified viva voce.

If you are still in the class I'd love to hear a clarification - maybe I'm wrong!

Re: Ways to break your systems code using volatile (2010)

#23
That note at the end about Linux is missing a link to the Documentation/volatile-considered-harmful.txt document. Basically, don't use volatile. Here, with your choice of formatting:

https://github.com/torvalds/linux/blob/master/Documentation/...

https://www.mjmwired.net/kernel/Documentation/volatile-consi...

https://www.kernel.org/doc/html/latest/process/volatile-cons...

Re: Ways to break your systems code using volatile (2010)

#24
post #19

Earlier quoted context omitted.

I don't understand these slides. The volatile keyword does not magically bypass the mechanism by which modern CPUs write to main memory. Am I missing something, or are they somehow meant to be ironic?

It (in theory) should bypass any caches in between physical memory and the CPU. Of course this is compiler/arch/OS dependent so YMMV... The slide is admittedly a bit vague, the point is mostly to convey "lots of complicated things that you probably haven't considered are going on in the background to speed up memory accesses in a uniprocessor model." Keep in mind the class is exploring parallel architectures, and tha…

The volatile keyword will certainly lead to implications for cache coherency, but it cannot bypass the TLB or somehow magically avoid the need to involve the memory controller. Unless I'm grossly misunderstanding something, a majority of the points on the second slide should also be on the first.

Re: Ways to break your systems code using volatile (2010)

#25
post #19

Earlier quoted context omitted.

I don't understand these slides. The volatile keyword does not magically bypass the mechanism by which modern CPUs write to main memory. Am I missing something, or are they somehow meant to be ironic?

It (in theory) should bypass any caches in between physical memory and the CPU. Of course this is compiler/arch/OS dependent so YMMV... The slide is admittedly a bit vague, the point is mostly to convey "lots of complicated things that you probably haven't considered are going on in the background to speed up memory accesses in a uniprocessor model." Keep in mind the class is exploring parallel architectures, and tha…

Check for yourself - look at the compiler output using https://godbolt.org for volatile on a variety of architectures. Ask yourself 'where is the logic to bypass the cache or virtual memory?' You won't find it.

Re: Ways to break your systems code using volatile (2010)

#26
post #14
post #6

Earlier quoted context omitted.

Don't forget about memory barriers. Otherwise your driver will fail on other CPU architectures. Just because it works on x86, doesn't mean it works on ARM, MIPS, POWER or RISC-V. CPUs other than x86 can reorder stores with other stores and loads with other loads. It can cause the CPU to do the store that starts DMA before the stores that set up length and address are done! Or just use C11 or C++11 memory model. Altho…

Even on x86, even with the C11 memory model, you can still get burned by transaction reordering as the MMIO passes through bridges. Plain old PCI can do this.

I thought x86 wasn't allowed to do write-write reordering? Does that rule not apply to peripherals? Is an `mfence` guaranteed to fix it, or are there just no rules at all at that point?

Re: Ways to break your systems code using volatile (2010)

#27
post #7

Edit: Looks like the slides had an inaccuracy (see replies). Huh, looks like I learned something today :) I think a good way of summarizing volatile is this slide from my parallel architectures class [1]: > Class exercise: describe everything that might occur during the > execution of this statement > volatile int x = 10 > > 1. Write to memory > > Now describe everything that might occur during the execution of > thi…

I don't get this, most likely due to my ignorance, but I thought volatile doesn't necessarily force anything to RAM, it can just push it out so cache coherence handles the rest, between cores (and perhaps peripherals). MESI can do the work without actually hitting memory.

if you want to force actually to ram then perhaps you'd need a memory barrier.

This is not my area though. Wrong? Right?

Re: Ways to break your systems code using volatile (2010)

#28
post #19

Earlier quoted context omitted.

It (in theory) should bypass any caches in between physical memory and the CPU. Of course this is compiler/arch/OS dependent so YMMV... The slide is admittedly a bit vague, the point is mostly to convey "lots of complicated things that you probably haven't considered are going on in the background to speed up memory accesses in a uniprocessor model." Keep in mind the class is exploring parallel architectures, and tha…

The volatile keyword will certainly lead to implications for cache coherency, but it cannot bypass the TLB or somehow magically avoid the need to involve the memory controller. Unless I'm grossly misunderstanding something, a majority of the points on the second slide should also be on the first.

Yep. The slide is completely wrong. It is showing low-level architecture details that would be 100% identical between the two cases. Volatile changes nothing on that list.

Volatile just makes sure the compiler bothers. Otherwise, a pair of writes to the same memory location could be optimized by eliminating the first write. Volatile makes the compiler do that. Of course, the CPU itself may then do this optimization, so volatile is thus not good enough for IO.

Re: Ways to break your systems code using volatile (2010)

#29
post #14

Earlier quoted context omitted.

Even on x86, even with the C11 memory model, you can still get burned by transaction reordering as the MMIO passes through bridges. Plain old PCI can do this.

I thought x86 wasn't allowed to do write-write reordering? Does that rule not apply to peripherals? Is an `mfence` guaranteed to fix it, or are there just no rules at all at that point?

PCI isn't x86, and x86 isn't PCI. PCI itself, for example in a PCI-to-PCI bridge chip, can do store buffering and read prefetches. The PCI specification lays out what you must to to suppress this.

There are at least 5 different sets of rules for ordering on x86, due to memory types. It's in the Intel manual, along with a table that shows how they interact with each other.

Re: Ways to break your systems code using volatile (2010)

#30
post #28

Earlier quoted context omitted.

The volatile keyword will certainly lead to implications for cache coherency, but it cannot bypass the TLB or somehow magically avoid the need to involve the memory controller. Unless I'm grossly misunderstanding something, a majority of the points on the second slide should also be on the first.

Yep. The slide is completely wrong. It is showing low-level architecture details that would be 100% identical between the two cases. Volatile changes nothing on that list. Volatile just makes sure the compiler bothers. Otherwise, a pair of writes to the same memory location could be optimized by eliminating the first write. Volatile makes the compiler do that. Of course, the CPU itself may then do this optimization,…

> It is showing low-level architecture details that would be 100% identical between the two cases.

To be as charitable as I can possibly be, the only part that could theoretically make sense is that the compiler could emit non-temporal store instructions to bypass the cache. I know compilers currently don't do that for volatile, but I don't know why.

Post reply on HN