mirror of
git://git.musl-libc.org/musl
synced 2025-01-10 08:39:56 +00:00
397f0a6a7d
switch to ll/sc model so that new atomic.h can provide optimized versions of all the atomic primitives without needing an ll/sc loop written in asm for each one. all isa levels which use ldrex/strex now use the inline ll/sc model even if the type of barrier to use is not known until runtime (v6). the cas model is only used for arm v5 and earlier, and it has been optimized to make the call via inline asm with custom constraints rather than as a C function call.
65 lines
1.3 KiB
C
65 lines
1.3 KiB
C
__attribute__((__visibility__("hidden")))
|
|
extern const void *__arm_atomics[3]; /* gettp, cas, barrier */
|
|
|
|
#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \
|
|
|| __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
|
|
|
|
#define a_ll a_ll
|
|
static inline int a_ll(volatile int *p)
|
|
{
|
|
int v;
|
|
__asm__ __volatile__ ("ldrex %0, %1" : "=r"(v) : "Q"(*p));
|
|
return v;
|
|
}
|
|
|
|
#define a_sc a_sc
|
|
static inline int a_sc(volatile int *p, int v)
|
|
{
|
|
int r;
|
|
__asm__ __volatile__ ("strex %0,%1,%2" : "=&r"(r) : "r"(v), "Q"(*p) : "memory");
|
|
return !r;
|
|
}
|
|
|
|
#if __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
|
|
|
|
#define a_barrier a_barrier
|
|
static inline void a_barrier()
|
|
{
|
|
__asm__ __volatile__ ("dmb ish" : : : "memory");
|
|
}
|
|
|
|
#endif
|
|
|
|
#define a_pre_llsc a_barrier
|
|
#define a_post_llsc a_barrier
|
|
|
|
#else
|
|
|
|
#define a_cas a_cas
|
|
static inline int a_cas(volatile int *p, int t, int s)
|
|
{
|
|
for (;;) {
|
|
register int r0 __asm__("r0") = t;
|
|
register int r1 __asm__("r1") = s;
|
|
register volatile int *r2 __asm__("r2") = p;
|
|
int old;
|
|
__asm__ __volatile__ (
|
|
"bl __a_cas"
|
|
: "+r"(r0) : "r"(r1), "r"(r2)
|
|
: "memory", "r3", "lr", "ip", "cc" );
|
|
if (!r0) return t;
|
|
if ((old=*p)!=t) return old;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef a_barrier
|
|
#define a_barrier a_barrier
|
|
static inline void a_barrier()
|
|
{
|
|
__asm__ __volatile__("bl __a_barrier"
|
|
: : : "memory", "cc", "ip", "lr" );
|
|
}
|
|
#endif
|