What | Removed | Added |
---|---|---|
CC | code@dawg.eu |
My answer to the topic from a mail exchange with Michael. On 06/11/2014 12:45 PM, Mike Franklin wrote: > Martin, > > If you are interested in this low level programming in D, you might also be interested in DIP62 (http://wiki.dlang.org/DIP62). > > If you remember from my presentation, there was a glaring problem with my implementation: using 'shared' for 'volatile' semantics. This is fundamentally incorrect. There is a discussion about it here (http://forum.dlang.org/post/mailman.1081.1400818840.2907.d.gnu@puremagic.com). > > There aren't many people in the D community doing such low-level work, so I fear that this issue will be marginalized. I would like to see more discussion about it, and hopefully some action. Your input would be quite valuable. > > Mike > Didn't knew about this proposal, but it's flawed IMO, because read-modify-write operations might get interrupted. So you do need atomic updates for volatile data that is accessed from an interrupt handler. Adding a type qualifier for memory mapped I/O is overkill IMO. The simple solution is to use shared+core.atomic for interrupt sensitive data and a few functions for volatile. void volatileSet(T)(ref shared(T) t, HeadUnshared!T val) if (T.sizeof == 4) { asm { naked; str r1, [r0]; bx lr; } } HeadUnshared!T volatileGet(T)(ref shared(T) t) if (T.sizeof == 4) { asm { naked; ldr r0, [r0]; bx lr; } } And because it's very difficult to ensure that certain memory-mapped I/O (which is essentially shared global state) isn't affected by an interrupt routine, it's safer to use core.atomic all the time. I don't think that atomic ops (using MemoryOrder.raw) will a big performance penalty, because memory-mapped I/O is rare. If it is, the volatile workaround is simple enough to be implemented in a library.