Formally speaking, either implementation satisfies C11 because the standard 
allows much leeway in the interpretation here. But, of course, it is kind of 
annoying that double-width types (and that also includes potentially 64-bit on 
some 32-bit processors, e.g. i586 also has cmpxchg8b and no official way to 
read atomically otherwise) need special handling and compiler extensions which 
basically means that in a number of cases I cannot write portable code, I need 
to put a bunch of architecture-dependent ifdefs, for say, 64 bit atomics even. 
(And all this mess to accommodate almost non-existent case when someone wants 
to use atomic_load on read-only memory for wide types, in which no good 
solution exists anyway.)

Particularly, imagine when someones writes some lock-free code for different 
types (in templates, macros, etc). It basically uses same C11 atomic primitives 
but for various integer sizes. Now I need special handling for larger types 
because whatever libatomic provides does not guarantee lock-freedom (i.e., 
useless) which otherwise I do not need. True that wider types may not be 
available across all architectures, but I would prefer to have generic and 
standard-conformant code at least for those that have them.



> That's a valid goal, but it does not imply that we should mess with how
> atomics are implemented by default, nor should we mess with the default
> use cases.  This goal wants something special, and that is exposing the
> fact that *only* a CAS is available to synchronize atomically on a
>particular type.  That is an extension of the existing atomics design.

See above

> The standard doesn't specify read-only memory, so it also doesn't forbid
> the concept.  The implementation takes it into account though, and thus
> it's defined in that context.
But my point is that a programmer cannot rely on this feature anyway unless 
she/he wants to write code which compiles only with gcc. It is unspecified by 
the standard and implementations that use read-modify-write for atomic_load are 
perfectly valid. The whole point to have this standard in the first place is to 
allow code be compiled by different compilers, otherwise people can just rely 
on gcc-specific extensions.


> The topic we're currently discussing does not significantly affect when
> we can remove __sync builtins, IMO.

They are the only builtins that directly expose double-width operations. Short 
of using assembly fall-backs, they are the only option right now.

> They do care about whether atomic operations are natively supported on
> that particular type -- and that should include a load.
I think, the whole point to have atomic operations is ability to provide 
lock-free operations whenever possible. Even though standard does not guarantee 
it, that is almost the only sane use case. Otherwise, there is no point -- you 
can always use locks. If they do not care about lock-freedom, they should just 
use locks.


> Nobody is proposing to mark things as lock-free if they aren't.  Thus, I
> don't see any change to what's usable in signal handlers.
It is not obvious to anyone that atomic_load will block. It will *not* for 
single-width types. So, again we see differences for single- and double-width 
types. Even though you do not have problems with read-only memory, you have 
another problem for double-width types which may be even more subtle and much 
harder to debug in a number of cases. Of course, no one can make an assumption 
that it will not block, but the same can be said about read-only memory.
Anyway, I do not have a horse in the race... I just proposed to consider this 
change for a number of legitimate use cases, but it is eventually up to the gcc 
developers to decide.
-- Ruslan
   

Reply via email to