[dmd-internals] Regarding deprecation of volatile statements

Walter Bright walter at digitalmars.com
Tue Jul 31 17:55:48 PDT 2012


On 7/31/2012 10:02 AM, Alex Rønne Petersen wrote:
> On Wed, Jul 25, 2012 at 1:20 AM, Walter Bright <walter at digitalmars.com> wrote:
>> On 7/24/2012 3:18 PM, Alex Rønne Petersen wrote:
>>> On Wed, Jul 25, 2012 at 12:11 AM, Walter Bright <walter at digitalmars.com>
>>> wrote:
>>>> On 7/24/2012 2:53 PM, Alex Rønne Petersen wrote:
>>>>> But shared can't replace volatile in kernel space. shared means
>>>>> atomics/memory fences which is not what I want - that would just give me
>>>>> unnecessary overhead. I want the proper, standard C semantics of
>>>>> volatile,
>>>>
>>>> C does not have Standard semantics for volatile. It's a giant mess.
>>> Right, it leaves the exact definition of a volatile access to the
>>> compiler.
>>
>> Right, that's why it is incorrect to refer to it as "standard" behavior.
>> Behaviors I've seen include various combinations of:
>>
>> 1. disallowing enregistering
>> 2. preventing folding multiple loads/stores together
>> 3. preventing reordering across expressions with volatiles
>> 4. inserting memory load/store fences
> As Martin already said, 1 and 2 are exactly what I need,

Why do you need something not to be enregistered? It's usually loaded into a 
register before use, anyway. Also, why would you need 2?


>   maybe with
> the added clarification that volatile operations cannot be reordered
> with respect to each other as David pointed out is the LLVM (and
> therefore GCC, as LLVM is GCC-compatible) behavior.

The only reason you'd need reordering prevention is if you had shared variables.

>
>>
>>
>>
>>>    But most relevant C compilers have a fairly sane definition
>>> of this. For example, GCC:
>>> http://gcc.gnu.org/onlinedocs/gcc/Volatiles.html
>>>
>>>>> not the atomicity that people seem to associate with it.
>>>>
>>>> Exactly what semantics are you looking for?
>>> GCC's volatile semantics, pretty much. I want to be able to interact
>>> with volatile memory without the compiler thinking it can optimize or
>>> reorder (or whatever) my memory accesses. In other words, tell the
>>> compiler to back off and leave volatile code alone.
>>
>> Unfortunately, this is rather vague. For example, how many read/write
>> operations are there in v++? Optimizing is a terminally nebulous concept.
> How many reads/writes there are is actually irrelevant from my
> perspective. The semantics that I'm after will simply guarantee that,
> no matter how many, it'll stay at that number and in the defined order
> of the v++ operation in the language.

At that number? At what number? And why do you need a defined order, unless 
you're doing shared memory?

>
>>
>>
>> D volatile isn't implemented, either.
> It is in LDC and GDC.
>
>>
>>> It doesn't insert a compiler reordering fence? Martin Nowak seemed to
>>> think that it does, and a lot of old druntime code assumed that it
>>> did...
>>
>> dmd, all on its own, does not reorder loads and stores across accesses to
>> globals or pointer dereferences. This behavior is inherited from dmc, and
>> was very successful. dmc generated code simply did not suffer from all kinds
>> of heisenbugs common with other compilers because of that. I've always
>> considered reordering stores to globals as a bad thing to rely on, and not a
>> significant source of performance improvements, so deliberately disabled
>> them.
>>
>> However, I do understand that the D spec does allow a compiler to do this.
> Right. What you just described is an undocumented implementation
> detail of one particular D compiler that I simply cannot rely on.
>
>> Even though shared is not implemented at the low level, I suggest using it
>> anyway as it currently does work (with or without shared). You should
>> anyway, as the only way there'd be trouble is for multithreaded access to
>> that memory anyway.
> ... with DMD.
>
> And even if we ignore the fact that this will only work with DMD,
> shared will eventually imply either memory fences or atomic
> operations, which means unnecessary pipeline slowdown. In a kernel.
> Not acceptable.



>
>> As for exact control over read and write cycles, the only reliable way to do
>> that is with inline assembler.
> Yes, that would perhaps work if I targeted only x86. But once a kernel
> expands beyond one architecture, you want to keep the assembly down to
> an absolute minimum because it makes maintenance and porting a
> nightmare. I specifically want to target ARM once I'm done with the
> x86 parts.

It's not a nightmare to write an asm function that takes a pointer as an 
argument and returns what it points to. You're porting a 2 line function between 
systems.


>
> I don't see why implementing volatile in D with the semantics we've
> discussed here would be so problematic. Especially considering GCC and
> LLVM already do the right thing, and it sounds like DMD's back end
> will too (?).

I'd rather work on "what problem are you trying to solve" rather than starting 
with a solution and then trying to infer the problem.

>
>> Use these two techniques, and your code should be future proofed.
> Not so. It would make it worse (read: less portable and less
> performant) than writing C.
>
>
>
> I think you're a bit too focused on what DMD does. I need well-defined
> semantics that I can rely on, not implementation details of one
> compiler's code generator and optimizer.
>
> In fact, if you're willing to recognize this need, I'm willing to
> write up a DIP with well-defined volatile semantics - provided that it
> won't be ignored (other DIPs are stagnating). This will of course mean
> undeprecating volatile, but this time, defining its semantics
> precisely.
>
> Regards,
> Alex
>



More information about the dmd-internals mailing list