4 ms·
That doesn't show anything incorrect though! You're just stating a requirement that the dereference to x[] happen after the load through p, which is something
by ajross 3y ago
That doesn't show anything incorrect though! You're just stating a requirement that the dereference to x[] happen after the load through p, which is something that can be trivially expressed using 1980's syntax by marking *p volatile. You don't need consume for that. Show me something that explains why the standard needs consume. It doesn't need consume, and I think you agree but you won't admit it.
You keep saying that somehow this isn't about alpha, but it's clear this is about alpha, because alpha needs a barrier there and volatile can't do barriers. You just... won't admit it. And per my point WAY upthread, I contend you won't admit it because you view the "standard" as the important thing and not the hardware.
- reitzensteinm 3y agoThey did, elsewhere: https://news.ycombinator.com/item?id=36068685 https://news.ycombinator.com/item?id=36068685 Even if volatile was absolutely all you needed, why would the committee build a memory model with a nice API and then force you to sprinkle in volatile? It makes absolutely no sense.
- kazinator 3y agoVolatile is what you would use when you don't care about the DEC Alpha, and ignore the API. When using the API, you wouldn't require volatile. You can build yourself an access API if you have volatile. E.g. #define volatile_lvalue(TYPE, LOC) (*(volatile TYPE *) &(LOC)) With typeof or _Generic, we can eliminate the TYPE argument. Then you can do: if (volatile_lvalue(int, i) == 3) { y = x[i]; // don't care if i replaced with 3 here } The user of volatile_lvalue doesn't have to declare anything volatile.
- gpderetta 3y agoThat's the crux of the matter: if i is replaced with 3 on the second line, what do you think prevents an ARM CPU from hoisting the x[3] above the i load first line? In practice the volatile cast might prevent current GCCs from performing constant propagation, so this exact code sequence might work, but it is extremely fragile and can break for some variations: if (int i2 = volatile_lvalue(int, i); i2 == 3) { y = x[i2]; // i2 is replaced, no data dependency } or if (volatile_lvalue(int, i)) { y = x[i-i]; // data dependency becomes a control dependency } You also have to be careful to what you do with y and with any value derived form it. As currently there is no way to efficiently implement consume you have to do with what you have, so for example the Linux kernel does use volatile casts and compilation barriers to implement LOAD_ONCE, but then has a large manual that documents what operations are currently considered safe and what are known to break. That's hardly a specification that can be put in a standard and you can't really can reason about the semantics of it. Linus himself has considered multiple time if it is worth the hassle and whether the kernel should just switch to acquire everywhere now that arm and power have relevant cheap barriers.
- kazinator 3y agoAh, for that problem, I'd prefer to have read_barrier() and write_barrier() type primitives that take no arguments.