This is the mail archive of the
mailing list for the glibc project.
Re: Implementing C++1x and C1x atomics
I am quoting from several different messages.
On 8/17/09, Joseph S. Myers <firstname.lastname@example.org> wrote:
> (A) Code compiled against headers from libc version X must be run
> with libc version X or later.
What is the symptom of failing to meet this constraint?
> (B) Code compiled against headers from libc version X must be linked
> into an executable or shared library against a binary of libc version X
Note, however, that gcc is used on some systems that do not have the
> > So, suppose I compile my program A, using libc version X, on
> > a processor of type D, which permits me to inline the atomic
> > operations. Then suppose that I execute A on a processor of
> > type E, which has libc version X, but which supports fewer
> > atomic operations and thus requires a locking implementation.
> > I have met all the versioning requirements. What happens?
> You get SIGILL when the atomic instruction that is present on D
> but not E is executed. That a program built for one processor
> (D) but executed on another (E), whose features are not a superset
> of those of D, will get SIGILL, or execute incorrectly if E does
> something else on encountering that instruction, is not in any way
> specific to atomic instructions; it applies to every architecture
> with more than one supported variant.
There is a very similar scenario, that is problematic. Suppose that
the application A uses only instructions from E. It will execute every
instruction correctly, but because the application uses a non-locking
implementation and the library uses a locking implementation, there
will be synchronization failure.
Such failures will be very difficult to detect. The problem is stronger
than running an instruction on an earlier processor.
I suppose that atomic types and any linker warnings could be developed
separately for quite some time.
> > > Ways for the kernel or dynamic linker to detect such
> > > incompatibilities may be useful, but would apply to this issue
> > > in general, not specifically to atomic operations.
> > The difference with the atomics is that if an application uses the
> > D instructions, we also need the dynamic library to also use the
> > D instructions (on a D or later processor). How do we ensure that?
> I have suggested that the library inform the compiler, via its headers
> (whatever the details - pragmas, macros, etc. - and whether or not
> the header in question is implicitly preincluded) of whether the
> library will be using these instructions, with the compiler making
> safe assumptions if the library does not give it this information.
> (The information passed from the library to the compiler would be an
> assertion that that library version, and all later versions, when
> used on a D or later processor, will always use the D instructions
> or later instructions that safely interoperate with them.)
Is this header provided with the compiler or the operating system?
In part, I am concerned about gcc on non-Linux systems.
The information from the library header could be as simple as which
level of architecture that the library uses to implement atomics.
This requires a fairly strong mapping between the architecture and
which types are implemented in a lock-free manner.
> > If we cannot, then I am concerned that we would be able to inline
> > no atomic operations without dropping support for the 80386 as
> > a subset of the later processors. The same situation applies to
> > other processor families.
> 80386 support is already dropped (effectively) in glibc, and has been
> for quite some time; you have to use -march=i486 or later to build
> glibc for IA32, or it will fail to link with missing atomic operations.
The problem is that gcc does support 80386. It also supports other
processors that have less-than-complete support for concurrency. Just in
the x86 line, we get some additional capability in many new layers.
8086 LOCK XCHG
80486 CMPXCHG XADD
late AMD64 CMPXCHG16B
So, we do not get to ignore the problem as a relic of 80386.
Hm. We also need that mapping between architecture and type, which
probably needs to indicate a lock-free implementation for each operation.
Alexander Terekhov did a large chunk of that.