[dmd-internals] Regarding deprecation of volatile statements

Alex Rønne Petersen xtzgzorex at gmail.com
Tue Jul 31 10:02:33 PDT 2012


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, 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.

>
>
>
>
>>   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.

>
>
>
> 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.

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 (?).

>
> 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