https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122078

--- Comment #3 from Federico Terraneo <fede.tft at miosix dot org> ---
(In reply to Richard Biener from comment #1)
> libatomic isn't a fallback for targets not having atomics at all.

That was my impression by reading the documentation:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_concurrency_impl.html

"Current releases use the newer __atomic intrinsics, which are implemented by
library calls if the hardware doesn't support them. Undefined references to
functions like __atomic_is_lock_free should be resolved by linking to
libatomic"

That to me looks like a fallback for hardware that does not have atomic
instructions.

> Note it
> still makes sense to have multi-byte "bools", so the set of functions make
> sense as well as not having __atomic_test_and_set_n.

My comment for multi-byte "bools" is related to the fact that a grep in the
entire GCC source code found no use of them. Who uses them?

> 
> Please provide a testcase that shows what you observe.

Ok. We are developing the Miosix free software RTOS for microcontrollers. We
already patch libatomic so our OS sycnhronization primitives are called on
architectures lacking atomic operations. The bug is not related to our patches
as libatomic has not even a chance to get involved, as it does not provide the
__atomic_test_and_set symbol. Moreover, other RTOS targets have independently
reported the same issue (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118977,
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118280).
The bug we are observing happens with the Raspberry Pi RP2040 SoC, it's a
dual-core ARM Cortex-M0+ microcontroller, that lacks atomic operations.


The simplest test case I could produce is the following:

#include <future>

int main()
{
    std::future<int> fut = std::async(std::launch::async, []{ return 0; });
    return fut.get();
}

This code inlines code from the following header file:
include/c++/14.2.0/bits/atomic_base.h:226
which indeed uses the __atomic_test_and_set intrinisic.

If the code is compiled with -mthumb -mcpu=cortex-m0plus (the CPU with no
atomic
instructions) the main function ends up containing the following call:

        bl      __atomic_test_and_set

which then fails at the linking stage as this symbol is not provided by
libatomic.

ld: main.o: in function `_ZNSt11atomic_flag12test_and_setESt12memory_order':
include/c++/14.2.0/bits/atomic_base.h:226:(.text.startup.main+0xc2): undefined
reference to `__atomic_test_and_set'
ld: (__atomic_test_and_set): Unknown destination type (ARM/Thumb) in main.o
include/c++/14.2.0/bits/atomic_base.h:226:(.text.startup.main+0xc2): dangerous
relocation: unsupported relocation
collect2: error: ld returned 1 exit status



If instead the code is compiled with -mthumb -mcpu=cortex-m3 (another CPU we
support with atomic instructions) the compiler does not generate any call to
__atomic_test_and_set and instead produces the following code:

.L602:
        ldrexb  r3, [r2]
        strexb  r0, r1, [r2]
        cmp     r0, #0
        bne     .L602



I'm attaching the full assembly files to have a look.

Our opinion on the matter is that either libatomic should provide the
__atomic_test_and_set symbol, or GCC should emit a call to
__atomic_test_and_set_1, a symbol libatomic already provides (the arguments
passed should also be checked for consistency in this case, we have not yet
done so).

Reply via email to