1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#include <rtthread.h>
/*
* spi_common.c claims a bus with
* atomic_compare_exchange_strong(&spi_periph_claimed[host], &expected, value)
* on an _Atomic bool, and an ESP32-C6 core can only reserve a whole word, so
* this gcc emits a call to the out-of-line helper instead of an lr/sc sequence.
* The install has no __atomic_compare_exchange_1:
* riscv32-esp-elf/bin/../lib/gcc/riscv32-esp-elf/11.2.0/libgcc.a -> 0 hits
* and there is no libatomic.a next to it, so the name stays undefined at link
* time. The prototype below is the one the compiler itself declares -- it
* rejects any other spelling with -Wbuiltin-declaration-mismatch -- and it
* matches what the call site really passes: the address of the object, the
* address of the expected byte, the desired byte, and two memory orders. The
* `weak` argument is not passed in a register at all (an atomic_compare_exchange
* weak/strong pair compiles to the same five loads), which is why it is ignored
* here; the helper's answer is always the strong one, so a weak CAS merely gets
* one it did not ask for.
*
* Masking interrupts is enough for this SoC: it has one core, so the only other
* writer of these bytes is an interrupt handler.
*/
_Bool __atomic_compare_exchange_1(volatile void *object,
void *expected,
unsigned char desired,
_Bool weak,
int success,
int failure)
{
volatile unsigned char *addr = (volatile unsigned char *)object;
unsigned char *compare = (unsigned char *)expected;
rt_base_t level;
_Bool exchanged;
(void)weak;
(void)success;
(void)failure;
level = rt_hw_interrupt_disable();
if (*addr == *compare)
{
*addr = desired;
exchanged = 1;
}
else
{
*compare = *addr;
exchanged = 0;
}
rt_hw_interrupt_enable(level);
return exchanged;
}
|