TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Ways to break your systems code using volatile (2010)

132 pointsby leafario2almost 6 years ago

13 comments

raphlinusalmost 6 years ago
This should say 2010. I believe much of it is out of date, as C11 <i>does</i> have a memory model, and <i>does</i> provide both atomics and barriers. Many, if not most, uses of volatile should probably be replaced by atomics.<p><a href="https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;c&#x2F;atomic" rel="nofollow">https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;c&#x2F;atomic</a>
评论 #20017934 未加载
评论 #20018065 未加载
评论 #20018340 未加载
aidenn0almost 6 years ago
In terms of &quot;Using volatile too much&quot; I found a comment along the lines of &quot;Not sure why this has to be volatile, but it doesn&#x27;t work without it&quot; and the answer was &quot;There is a race condition and volatile slows down one path enough to make it go away.&quot;<p>Yuck.
alain94040almost 6 years ago
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.
评论 #20017792 未加载
评论 #20018118 未加载
评论 #20017868 未加载
dahfizzalmost 6 years ago
I think the title and parts of the article are misleading. Using volatile will <i>never</i> make a correct program incorrect. It cannot &quot;break&quot; a correct implementation.<p>It should not be overused, because as the article mentions it makes for slower and more confusing code, but it&#x27;s not quite something to be afraid of either.<p>It is slower to use volatile, and bad form
burfogalmost 6 years ago
That note at the end about Linux is missing a link to the Documentation&#x2F;volatile-considered-harmful.txt document. Basically, don&#x27;t use volatile. Here, with your choice of formatting:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;torvalds&#x2F;linux&#x2F;blob&#x2F;master&#x2F;Documentation&#x2F;process&#x2F;volatile-considered-harmful.rst" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;torvalds&#x2F;linux&#x2F;blob&#x2F;master&#x2F;Documentation&#x2F;...</a><p><a href="https:&#x2F;&#x2F;www.mjmwired.net&#x2F;kernel&#x2F;Documentation&#x2F;volatile-considered-harmful.txt" rel="nofollow">https:&#x2F;&#x2F;www.mjmwired.net&#x2F;kernel&#x2F;Documentation&#x2F;volatile-consi...</a><p><a href="https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;html&#x2F;latest&#x2F;process&#x2F;volatile-considered-harmful.html" rel="nofollow">https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;html&#x2F;latest&#x2F;process&#x2F;volatile-cons...</a>
评论 #20020270 未加载
SAI_Peregrinusalmost 6 years ago
The entire section on declarations can also be fixed by always binding type modifiers and quantifiers to the left. Rewriting the examples:<p><pre><code> int* p; &#x2F;&#x2F; pointer to int int volatile* p_to_vol; &#x2F;&#x2F; pointer to volatile int int* volatile vol_p; &#x2F;&#x2F; volatile pointer to int int volatile* volatile vol_p_to_vol; &#x2F;&#x2F; volatile pointer to volatile int </code></pre> This method always starts with the most basic type, then adds modifiers sequentially. The modifier binds to everything left of it.
klingonoperaalmost 6 years ago
<p><pre><code> &gt; &quot;Side note: although at first glance this code looks like it fails to account for the case where TCNT1 overflows from 65535 to 0 during the timing run, it actually works properly for all durations between 0 and 65535 ticks.&quot; </code></pre> From example 1, ignoring device and setup-specifics what to do when TCNT1 overflows, it actually works properly for <i>all</i> ticks, both &quot;first&quot; and &quot;second&quot; are unsigned (therefore behaviour is defined), and the delta between them both is always between 0 and 65535, no matter what values they may have, and also correct in all cases.<p>E.g.:<p><pre><code> timeDelta = timeStampNow - timeStampLast = 0 - 65535 = 1</code></pre>
评论 #20018383 未加载
评论 #20018249 未加载
legoheadalmost 6 years ago
I&#x27;ve never had to use volatile in code. This was all very interesting!<p>For issue #5, a possible solution not mentioned could be to write inline assembly, no? It would keep the array non-volatile and should be portable.
评论 #20026874 未加载
loegalmost 6 years ago
volatile should only be used for accessing MMIO registers in device drivers; that&#x27;s it.
评论 #20018241 未加载
评论 #20019423 未加载
评论 #20019298 未加载
kaetemialmost 6 years ago
Volatile seems quite sufficient for a PleaseExitThread boolean.
flafla2almost 6 years ago
Edit: Looks like the slides had an inaccuracy (see replies). Huh, looks like I learned something today :)<p>I think a good way of summarizing volatile is this slide from my parallel architectures class [1]:<p><pre><code> &gt; Class exercise: describe everything that might occur during the &gt; execution of this statement &gt; volatile int x = 10 &gt; &gt; 1. Write to memory &gt; &gt; Now describe everything that might occur during the execution of &gt; this statement &gt; int x = 10 &gt; &gt; 1. Virtual address to physical address conversion (TLB lookup) &gt; 2. TLB miss &gt; 3. TLB update (might involve OS) &gt; 4. OS may need to swap in page to get the appropriate page &gt; table (load from disk to physical address) &gt; 5. Cache lookup (tag check) &gt; 6. Determine line not in cache (need to generate BusRdX) &gt; 7. Arbitrate for bus &gt; 8. Win bus, place address, command on bus &gt; 9. All caches perform snoop (e.g., invalidate their local &gt; copies of the relevant line) &gt; 10. Another cache or memory decides it must respond (let’s &gt; assume it’s memory) &gt; 11. Memory request sent to memory controller &gt; 12. Memory controller is itself a scheduler &gt; 13. Memory controller checks active row in DRAM row buffer. &gt; (May &gt; need to activate new DRAM row. Let’s assume it does.) &gt; 14. DRAM reads values into row buffer &gt; 15. Memory arbitrates for data bus &gt; 16. Memory wins bus &gt; 17. Memory puts data on bus &gt; 18. Requesting cache grabs data, updates cache line and tags, &gt; moves line into exclusive state &gt; 19. Processor is notified data exists &gt; 20. Instruction proceeds &gt; * This list is certainly not complete, it’s just &gt; what I came up with off the top of my head. </code></pre> It&#x27;s also worth mentioning that this assumes a uniprocessor model, so out-of-order execution is still possible which leads to complications in any sort of multithreaded or networked system (See #5, 6, 7, 8 in the OP article).<p>I think a lot of the confusion stems from the illusion that a uniprocessor + in-order execution model implies to programmers who have never dealt with system-level code. I think in the future, performant software will require a bit more understanding of the underlying hardware on the part of your average software developer -- especially when you care about any sort of parallelism. It doesn&#x27;t help that almost all common CS curriculum ignores parallelism until the 3rd year or more.<p>[1] <a href="http:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;~418&#x2F;lectures&#x2F;12_snoopimpl.pdf" rel="nofollow">http:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;~418&#x2F;lectures&#x2F;12_snoopimpl.pdf</a> - the last 2 slides
评论 #20018075 未加载
评论 #20017897 未加载
评论 #20018022 未加载
评论 #20018073 未加载
评论 #20017931 未加载
nullwasamistakealmost 6 years ago
Ironically volatile is just as bad in Java for different reasons. Frequently used for &quot;lock free&quot; synchronization, its usually actually worse than using locks because it can&#x27;t be cached between cores. The variable is always loaded from main memory, which is usually much worse than holding a lock mutex in registers.
评论 #20017765 未加载
评论 #20017951 未加载
tus87almost 6 years ago
Err...volatile just tells the compiler not to cache the value in a register, that&#x27;s it. If you don&#x27;t understand volatile you really, really are not the kind of programmer who should even think about using it.
评论 #20017974 未加载
评论 #20018179 未加载