Live data from Hacker News

Ways to break your systems code using volatile (2010)

blog.regehr.org

61–70 of 77 posts

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

#61
post #8

volatile should only be used for accessing MMIO registers in device drivers; that's it.

There's definitely more uses. For example, shared memory between processes: you should mark it volatile. C++ atomics are no good here, because they are not guaranteed to be lock free or address free.

> C++ atomics are no good here, because they are not guaranteed to be lock free or address free.

That's not right; you can still use std::memory_order to get the memory barriers generated that are required. These are going to obviously be lock free, they deal with memory ordering—what you tried to deal with volatile, but in general case.

See: https://en.cppreference.com/w/cpp/atomic/atomic/store

Effectively std::atomic stores and loads generate volatile accesses plus the required memory barriers to get the desired behavior.

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

#62
The entire section on declarations can also be fixed by always binding type modifiers and quantifiers to the left. Rewriting the examples:

    int* p;                              // pointer to int  
    int volatile* p_to_vol;              // pointer to volatile int  
    int* volatile vol_p;                 // volatile pointer to int  
    int volatile* volatile vol_p_to_vol; // volatile pointer to volatile int
This method always starts with the most basic type, then adds modifiers sequentially. The modifier binds to everything left of it.

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

#63
post #8

volatile should only be used for accessing MMIO registers in device drivers; that's it.

That is a reasonable heuristic but your statement is not technically correct. E.g. you need volatile around setjmp/longjmp and that has nothing to do with IO.

Technically for sig_atomic_t as well. Both are... messier parts of the C abstract machine.

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

#64
post #31

This should say 2010. I believe much of it is out of date, as C11 does have a memory model, and does provide both atomics and barriers. Many, if not most, uses of volatile should probably be replaced by atomics. https://en.cppreference.com/w/c/atomic

You're not wrong, but C is a language where plenty of apps are still using older versions, so while as per site etiquette this should have the date, it's still interesting, especially for the embedded space.

There's using an outdated version, and then there's C.

The more commonly used language specs, IME, are C99 and C89!

That's 20 and 30 years of 'stability'.

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

#65
post #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...

Neat how inline assembly is one of the valid use cases. I'm given to understand that essential parts of the Linux kernel can't actually be implemented in pure C and that some assembly is required.

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

#66

You really should just use volatile for device drivers when accessing IO space with side-effects. Do not use volatile to build your own synchronization primitives.

What do you think about signal handlers? Atomics may be implemented with locks, which makes them unsuitable for signal handlers. The only guaranteed lock-free type is `std::atomic_flag` which is not very useful. `volatile sig_atomic_t` still seems like the better choice for signals.

If the architecture is so broken that atomic load and stores need to use locks, I can't see how would sig_atomic_t would ever be implementable.

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

#67
post #8

volatile should only be used for accessing MMIO registers in device drivers; that's it.

That is a reasonable heuristic but your statement is not technically correct. E.g. you need volatile around setjmp/longjmp and that has nothing to do with IO.

And if your GC doesn't dump the registers. Only with volatile you can keep all locals on the stack.

And yes, that's not stupid. It's actually faster than all the register "optimizations" for practical use cases in fast VM's. Register saving across calls and at the GC is much more expensive. mem2reg is an antipattern mostly

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

#68

Earlier quoted context omitted.

> You can use a lock but held in a regular CPU register. They're just regular variables for the most part. I don't understand this. If your lock variable is in a CPU register how do other CPUs acquire the lock? > Lock free in Java is usually worse that what the JVM can pull off with lock elision I don't understand this either. Java's lock elision is only going to make a concurrent object 'lock-free' in the case where…

JVM is very smart about locking. My knowledge is limited but this is a great article. https://shipilev.net/jvm/anatomy-quarks/19-lock-elision/

I work with the JVM at Oracle and I’ve given talks about the lock elision algorithm. It doesn’t do what you think it does and what it does do is not related to lock-free like you think it is.

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

#70

This should say 2010. I believe much of it is out of date, as C11 does have a memory model, and does provide both atomics and barriers. Many, if not most, uses of volatile should probably be replaced by atomics. https://en.cppreference.com/w/c/atomic

Many projects are stuck in C99, or even C89...

Many compilers are stuck in C99 or C89 or even earlier. There are other worlds besides gcc, clang and msvc.
Post reply on HN