Add atomic functions for arm/arm64/riscv
Make code more compatible with gcc. Change __atomic_store __atomic_load __atomic_exchange __atomic_compare_exchange Also add (include/stdatomic.h, lib/stdatomic.c): atomic_thread_fence atomic_signal_fence atomic_is_lock_free And gcc extensions (tcctok.h, tccgen.c, lib/stdatomic.c): __atomic_fetch_nand __atomic_and_fetch __atomic_sub_fetch __atomic_or_fetch __atomic_xor_fetch __atomic_and_fetch __atomic_nand_fetch Add new file lib/atomic.S with assembly code for __atomic_compare_exchange_n for arm/arm64/riscv. Also update lib/Makefile. Update testcode in 124_atomic_counter and 125_atomic_misc to test new functions. Also update tests/tests2/Makefile to run tests on arm/arm64/riscv.
This commit is contained in:
parent
bb80cbe0d9
commit
79a8229fb5
11 changed files with 1078 additions and 130 deletions
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define __ATOMIC_RELAXED 0
|
#define __ATOMIC_RELAXED 0
|
||||||
#define __ATOMIC_CONSUME 1
|
#define __ATOMIC_CONSUME 1
|
||||||
|
@ -78,41 +79,68 @@ typedef struct {
|
||||||
|
|
||||||
#define ATOMIC_FLAG_INIT {0}
|
#define ATOMIC_FLAG_INIT {0}
|
||||||
|
|
||||||
#define atomic_flag_test_and_set(object) \
|
#define atomic_flag_test_and_set_explicit(object, order) \
|
||||||
__atomic_exchange(&(object)->value, 1, __ATOMIC_SEQ_CST)
|
({ bool ret, value = 1; \
|
||||||
#define atomic_flag_test_and_set_explicit(object, order) \
|
__atomic_exchange(&(object)->value, &value, &ret, order); \
|
||||||
__atomic_exchange(&(object)->value, 1, order)
|
ret; \
|
||||||
|
})
|
||||||
|
#define atomic_flag_test_and_set(object) \
|
||||||
|
atomic_flag_test_and_set_explicit(object, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
#define atomic_flag_clear_explicit(object, order) \
|
||||||
|
({ bool value = 0; \
|
||||||
|
__atomic_store(&(object)->value, &value, order); \
|
||||||
|
})
|
||||||
#define atomic_flag_clear(object) \
|
#define atomic_flag_clear(object) \
|
||||||
__atomic_store(&(object)->value, 0, __ATOMIC_SEQ_CST)
|
atomic_flag_clear_explicit(object, __ATOMIC_SEQ_CST)
|
||||||
#define atomic_flag_clear_explicit(object, order) \
|
|
||||||
__atomic_store(&(object)->value, 0, order)
|
|
||||||
|
|
||||||
/* Generic routines */
|
/* Generic routines */
|
||||||
#define atomic_init(object, desired) \
|
#define atomic_init(object, desired) \
|
||||||
__atomic_store(object, desired, __ATOMIC_RELAXED)
|
atomic_store_explicit(object, desired, __ATOMIC_RELAXED)
|
||||||
|
|
||||||
#define atomic_store(object, desired) \
|
#define atomic_store_explicit(object, desired, order) \
|
||||||
__atomic_store(object, desired, __ATOMIC_SEQ_CST)
|
({ __typeof__ (object) ptr = (object); \
|
||||||
#define atomic_store_explicit __atomic_store
|
__typeof__ (*ptr) tmp = (desired); \
|
||||||
|
__atomic_store (ptr, &tmp, (order)); \
|
||||||
|
})
|
||||||
|
#define atomic_store(object, desired) \
|
||||||
|
atomic_store_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
#define atomic_load(object) \
|
#define atomic_load_explicit(object, order) \
|
||||||
__atomic_load(object, __ATOMIC_SEQ_CST)
|
({ __typeof__ (object) ptr = (object); \
|
||||||
#define atomic_load_explicit __atomic_load
|
__typeof__ (*ptr) tmp; \
|
||||||
|
__atomic_load (ptr, &tmp, (order)); \
|
||||||
|
tmp; \
|
||||||
|
})
|
||||||
|
#define atomic_load(object) atomic_load_explicit (object, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
#define atomic_exchange(object, desired) \
|
#define atomic_exchange_explicit(object, desired, order) \
|
||||||
__atomic_exchange(object, desired, __ATOMIC_SEQ_CST)
|
({ __typeof__ (object) ptr = (object); \
|
||||||
#define atomic_exchange_explicit __atomic_exchange
|
__typeof__ (*ptr) val = (desired); \
|
||||||
|
__typeof__ (*ptr) tmp; \
|
||||||
|
__atomic_exchange (ptr, &val, &tmp, (order)); \
|
||||||
|
tmp; \
|
||||||
|
})
|
||||||
|
#define atomic_exchange(object, desired) \
|
||||||
|
atomic_exchange_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
#define atomic_compare_exchange_strong(object, expected, desired) \
|
|
||||||
__atomic_compare_exchange(object, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
|
||||||
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||||
__atomic_compare_exchange(object, expected, desired, 0, success, failure)
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ (*ptr) tmp = desired; \
|
||||||
|
__atomic_compare_exchange(ptr, expected, &tmp, 0, success, failure); \
|
||||||
|
})
|
||||||
|
#define atomic_compare_exchange_strong(object, expected, desired) \
|
||||||
|
atomic_compare_exchange_strong_explicit (object, expected, desired, \
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
#define atomic_compare_exchange_weak(object, expected, desired) \
|
|
||||||
__atomic_compare_exchange(object, expected, desired, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
|
||||||
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
||||||
__atomic_compare_exchange(object, expected, desired, 1, success, failure)
|
({ __typeof__ (object) ptr = (object); \
|
||||||
|
__typeof__ (*ptr) tmp = desired; \
|
||||||
|
__atomic_compare_exchange(ptr, expected, &tmp, 1, success, failure); \
|
||||||
|
})
|
||||||
|
#define atomic_compare_exchange_weak(object, expected, desired) \
|
||||||
|
atomic_compare_exchange_weak_explicit (PTR, VAL, DES, \
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
#define atomic_fetch_add(object, operand) \
|
#define atomic_fetch_add(object, operand) \
|
||||||
__atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
|
__atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
|
||||||
|
@ -134,4 +162,16 @@ typedef struct {
|
||||||
__atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
|
__atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
|
||||||
#define atomic_fetch_and_explicit __atomic_fetch_and
|
#define atomic_fetch_and_explicit __atomic_fetch_and
|
||||||
|
|
||||||
|
extern void atomic_thread_fence (memory_order);
|
||||||
|
extern void __atomic_thread_fence (memory_order);
|
||||||
|
#define atomic_thread_fence(order) __atomic_thread_fence (order)
|
||||||
|
extern void atomic_signal_fence (memory_order);
|
||||||
|
extern void __atomic_signal_fence (memory_order);
|
||||||
|
#define atomic_signal_fence(order) __atomic_signal_fence (order)
|
||||||
|
extern bool __atomic_is_lock_free(size_t size, void *ptr);
|
||||||
|
#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ))
|
||||||
|
|
||||||
|
extern bool __atomic_test_and_set (void *, memory_order);
|
||||||
|
extern void __atomic_clear (bool *, memory_order);
|
||||||
|
|
||||||
#endif /* _STDATOMIC_H */
|
#endif /* _STDATOMIC_H */
|
||||||
|
|
10
lib/Makefile
10
lib/Makefile
|
@ -42,11 +42,11 @@ $(X)BT_O += tcov.o
|
||||||
|
|
||||||
DSO_O = dsohandle.o
|
DSO_O = dsohandle.o
|
||||||
|
|
||||||
I386_O = libtcc1.o alloca.o alloca-bt.o $(BT_O) stdatomic.o
|
I386_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o $(BT_O)
|
||||||
X86_64_O = libtcc1.o alloca.o alloca-bt.o $(BT_O) stdatomic.o
|
X86_64_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o $(BT_O)
|
||||||
ARM_O = libtcc1.o armeabi.o alloca.o armflush.o fetch_and_add.o $(BT_O)
|
ARM_O = libtcc1.o armeabi.o alloca.o armflush.o fetch_and_add.o stdatomic.o atomic.o $(BT_O)
|
||||||
ARM64_O = lib-arm64.o fetch_and_add.o $(BT_O)
|
ARM64_O = lib-arm64.o fetch_and_add.o stdatomic.o atomic.o $(BT_O)
|
||||||
RISCV64_O = lib-arm64.o fetch_and_add.o $(BT_O)
|
RISCV64_O = lib-arm64.o fetch_and_add.o stdatomic.o atomic.o $(BT_O)
|
||||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
|
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
|
||||||
|
|
||||||
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
|
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
|
||||||
|
|
606
lib/atomic.S
Normal file
606
lib/atomic.S
Normal file
|
@ -0,0 +1,606 @@
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
/* This file implements for arm/arm64/riscv:
|
||||||
|
* __atomic_compare_exchange_1
|
||||||
|
* __atomic_compare_exchange_2
|
||||||
|
* __atomic_compare_exchange_4
|
||||||
|
* __atomic_compare_exchange_8
|
||||||
|
*/
|
||||||
|
#if defined __arm__
|
||||||
|
|
||||||
|
#ifndef __TINYC__
|
||||||
|
.arch armv6k
|
||||||
|
.syntax unified
|
||||||
|
#endif
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_1
|
||||||
|
.type __atomic_compare_exchange_1, %function
|
||||||
|
__atomic_compare_exchange_1:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xe52de004
|
||||||
|
.int 0xe5d13000
|
||||||
|
.int 0xf57ff05b
|
||||||
|
.int 0xe1d0cf9f
|
||||||
|
.int 0xe15c0003
|
||||||
|
.int 0x1a000002
|
||||||
|
.int 0xe1c0ef92
|
||||||
|
.int 0xe35e0000
|
||||||
|
.int 0x1afffff9
|
||||||
|
.int 0x03a00001
|
||||||
|
.int 0x13a00000
|
||||||
|
.int 0xf57ff05b
|
||||||
|
.int 0x15c1c000
|
||||||
|
.int 0xe49df004
|
||||||
|
#else
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
ldrb r3, [r1]
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
.L1:
|
||||||
|
ldrexb ip, [r0]
|
||||||
|
cmp ip, r3
|
||||||
|
bne .L2
|
||||||
|
strexb lr, r2, [r0]
|
||||||
|
cmp lr, #0
|
||||||
|
bne .L1
|
||||||
|
.L2:
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
moveq r0, #1
|
||||||
|
movne r0, #0
|
||||||
|
strbne ip, [r1]
|
||||||
|
ldr pc, [sp], #4
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_1, .-__atomic_compare_exchange_1
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_2
|
||||||
|
.type __atomic_compare_exchange_2, %function
|
||||||
|
__atomic_compare_exchange_2:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xe52de004
|
||||||
|
.int 0xe1d130b0
|
||||||
|
.int 0xf57ff05b
|
||||||
|
.int 0xe1f0cf9f
|
||||||
|
.int 0xe15c0003
|
||||||
|
.int 0x1a000002
|
||||||
|
.int 0xe1e0ef92
|
||||||
|
.int 0xe35e0000
|
||||||
|
.int 0x1afffff9
|
||||||
|
.int 0x03a00001
|
||||||
|
.int 0x13a00000
|
||||||
|
.int 0xf57ff05b
|
||||||
|
.int 0x11c1c0b0
|
||||||
|
.int 0xe49df004
|
||||||
|
#else
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
ldrh r3, [r1]
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
.L3:
|
||||||
|
ldrexh ip, [r0]
|
||||||
|
cmp ip, r3
|
||||||
|
bne .L4
|
||||||
|
strexh lr, r2, [r0]
|
||||||
|
cmp lr, #0
|
||||||
|
bne .L3
|
||||||
|
.L4:
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
moveq r0, #1
|
||||||
|
movne r0, #0
|
||||||
|
strhne ip, [r1]
|
||||||
|
ldr pc, [sp], #4
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_2, .-__atomic_compare_exchange_2
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_4
|
||||||
|
.type __atomic_compare_exchange_4, %function
|
||||||
|
__atomic_compare_exchange_4:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xe52de004
|
||||||
|
.int 0xe5913000
|
||||||
|
.int 0xf57ff05b
|
||||||
|
.int 0xe190cf9f
|
||||||
|
.int 0xe15c0003
|
||||||
|
.int 0x1a000002
|
||||||
|
.int 0xe180ef92
|
||||||
|
.int 0xe35e0000
|
||||||
|
.int 0x1afffff9
|
||||||
|
.int 0x03a00001
|
||||||
|
.int 0x13a00000
|
||||||
|
.int 0xf57ff05b
|
||||||
|
.int 0x1581c000
|
||||||
|
.int 0xe49df004
|
||||||
|
#else
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
ldr r3, [r1]
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
.L5:
|
||||||
|
ldrex ip, [r0]
|
||||||
|
cmp ip, r3
|
||||||
|
bne .L6
|
||||||
|
strex lr, r2, [r0]
|
||||||
|
cmp lr, #0
|
||||||
|
bne .L5
|
||||||
|
.L6:
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
moveq r0, #1
|
||||||
|
movne r0, #0
|
||||||
|
strne ip, [r1]
|
||||||
|
ldr pc, [sp], #4
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_4, .-__atomic_compare_exchange_4
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __aarch64__
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_1
|
||||||
|
.type __atomic_compare_exchange_1, %function
|
||||||
|
__atomic_compare_exchange_1:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xa9be7bfd
|
||||||
|
.int 0x910003fd
|
||||||
|
.int 0xa90153f3
|
||||||
|
.int 0xaa0103f3
|
||||||
|
.int 0x12001c41
|
||||||
|
.int 0xaa0003e2
|
||||||
|
.int 0x39400274
|
||||||
|
.int 0x2a1403e0
|
||||||
|
.int 0x53001c10
|
||||||
|
.int 0x085ffc40
|
||||||
|
.int 0x6b10001f
|
||||||
|
.int 0x54000061
|
||||||
|
.int 0x0811fc41
|
||||||
|
.int 0x35ffff91
|
||||||
|
.int 0x6b34001f
|
||||||
|
.int 0x1a9f17e1
|
||||||
|
.int 0x54000040
|
||||||
|
.int 0x39000260
|
||||||
|
.int 0x2a0103e0
|
||||||
|
.int 0xa94153f3
|
||||||
|
.int 0xa8c27bfd
|
||||||
|
.int 0xd65f03c0
|
||||||
|
#else
|
||||||
|
stp x29, x30, [sp, -32]!
|
||||||
|
mov x29, sp
|
||||||
|
stp x19, x20, [sp, 16]
|
||||||
|
mov x19, x1
|
||||||
|
and w1, w2, 255
|
||||||
|
mov x2, x0
|
||||||
|
ldrb w20, [x19]
|
||||||
|
mov w0, w20
|
||||||
|
uxtb w16, w0
|
||||||
|
.L1:
|
||||||
|
ldaxrb w0, [x2]
|
||||||
|
cmp w0, w16
|
||||||
|
b.ne .L2
|
||||||
|
stlxrb w17, w1, [x2]
|
||||||
|
cbnz w17, .L1
|
||||||
|
.L2:
|
||||||
|
cmp w0, w20, uxtb
|
||||||
|
cset w1, eq
|
||||||
|
beq .L3
|
||||||
|
strb w0, [x19]
|
||||||
|
.L3:
|
||||||
|
mov w0, w1
|
||||||
|
ldp x19, x20, [sp, 16]
|
||||||
|
ldp x29, x30, [sp], 32
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_1, .-__atomic_compare_exchange_1
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_2
|
||||||
|
.type __atomic_compare_exchange_2, %function
|
||||||
|
__atomic_compare_exchange_2:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xa9be7bfd
|
||||||
|
.int 0x910003fd
|
||||||
|
.int 0xa90153f3
|
||||||
|
.int 0xaa0103f3
|
||||||
|
.int 0x12003c41
|
||||||
|
.int 0xaa0003e2
|
||||||
|
.int 0x79400274
|
||||||
|
.int 0x2a1403e0
|
||||||
|
.int 0x53003c10
|
||||||
|
.int 0x485ffc40
|
||||||
|
.int 0x6b10001f
|
||||||
|
.int 0x54000061
|
||||||
|
.int 0x4811fc41
|
||||||
|
.int 0x35ffff91
|
||||||
|
.int 0x6b34201f
|
||||||
|
.int 0x1a9f17e1
|
||||||
|
.int 0x54000040
|
||||||
|
.int 0x79000260
|
||||||
|
.int 0x2a0103e0
|
||||||
|
.int 0xa94153f3
|
||||||
|
.int 0xa8c27bfd
|
||||||
|
.int 0xd65f03c0
|
||||||
|
#else
|
||||||
|
stp x29, x30, [sp, -32]!
|
||||||
|
mov x29, sp
|
||||||
|
stp x19, x20, [sp, 16]
|
||||||
|
mov x19, x1
|
||||||
|
and w1, w2, 65535
|
||||||
|
mov x2, x0
|
||||||
|
ldrh w20, [x19]
|
||||||
|
mov w0, w20
|
||||||
|
uxth w16, w0
|
||||||
|
.L4:
|
||||||
|
ldaxrh w0, [x2]
|
||||||
|
cmp w0, w16
|
||||||
|
b.ne .L5
|
||||||
|
stlxrh w17, w1, [x2]
|
||||||
|
cbnz w17, .L4
|
||||||
|
.L5:
|
||||||
|
cmp w0, w20, uxth
|
||||||
|
cset w1, eq
|
||||||
|
beq .L6
|
||||||
|
strh w0, [x19]
|
||||||
|
.L6:
|
||||||
|
mov w0, w1
|
||||||
|
ldp x19, x20, [sp, 16]
|
||||||
|
ldp x29, x30, [sp], 32
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_2, .-__atomic_compare_exchange_2
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_4
|
||||||
|
.type __atomic_compare_exchange_4, %function
|
||||||
|
__atomic_compare_exchange_4:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xa9be7bfd
|
||||||
|
.int 0x910003fd
|
||||||
|
.int 0xa90153f3
|
||||||
|
.int 0xaa0103f3
|
||||||
|
.int 0x2a0203e1
|
||||||
|
.int 0xaa0003e2
|
||||||
|
.int 0xb9400274
|
||||||
|
.int 0x2a1403e0
|
||||||
|
.int 0x2a0003f0
|
||||||
|
.int 0x885ffc40
|
||||||
|
.int 0x6b10001f
|
||||||
|
.int 0x54000061
|
||||||
|
.int 0x8811fc41
|
||||||
|
.int 0x35ffff91
|
||||||
|
.int 0x6b14001f
|
||||||
|
.int 0x1a9f17e1
|
||||||
|
.int 0x54000040
|
||||||
|
.int 0xb9000260
|
||||||
|
.int 0x2a0103e0
|
||||||
|
.int 0xa94153f3
|
||||||
|
.int 0xa8c27bfd
|
||||||
|
.int 0xd65f03c0
|
||||||
|
#else
|
||||||
|
stp x29, x30, [sp, -32]!
|
||||||
|
mov x29, sp
|
||||||
|
stp x19, x20, [sp, 16]
|
||||||
|
mov x19, x1
|
||||||
|
mov w1, w2
|
||||||
|
mov x2, x0
|
||||||
|
ldr w20, [x19]
|
||||||
|
mov w0, w20
|
||||||
|
mov w16, w0
|
||||||
|
.L7:
|
||||||
|
ldaxr w0, [x2]
|
||||||
|
cmp w0, w16
|
||||||
|
b.ne .L8
|
||||||
|
stlxr w17, w1, [x2]
|
||||||
|
cbnz w17, .L7
|
||||||
|
.L8:
|
||||||
|
cmp w0, w20
|
||||||
|
cset w1, eq
|
||||||
|
beq .L9
|
||||||
|
str w0, [x19]
|
||||||
|
.L9:
|
||||||
|
mov w0, w1
|
||||||
|
ldp x19, x20, [sp, 16]
|
||||||
|
ldp x29, x30, [sp], 32
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_4, .-__atomic_compare_exchange_4
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_8
|
||||||
|
.type __atomic_compare_exchange_8, %function
|
||||||
|
__atomic_compare_exchange_8:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.int 0xa9be7bfd
|
||||||
|
.int 0x910003fd
|
||||||
|
.int 0xa90153f3
|
||||||
|
.int 0xaa0103f3
|
||||||
|
.int 0xaa0203e1
|
||||||
|
.int 0xaa0003e2
|
||||||
|
.int 0xf9400274
|
||||||
|
.int 0xaa1403e0
|
||||||
|
.int 0xaa0003f0
|
||||||
|
.int 0xc85ffc40
|
||||||
|
.int 0xeb10001f
|
||||||
|
.int 0x54000061
|
||||||
|
.int 0xc811fc41
|
||||||
|
.int 0x35ffff91
|
||||||
|
.int 0xeb14001f
|
||||||
|
.int 0x1a9f17e1
|
||||||
|
.int 0x54000040
|
||||||
|
.int 0xf9000260
|
||||||
|
.int 0x2a0103e0
|
||||||
|
.int 0xa94153f3
|
||||||
|
.int 0xa8c27bfd
|
||||||
|
.int 0xd65f03c0
|
||||||
|
#else
|
||||||
|
stp x29, x30, [sp, -32]!
|
||||||
|
mov x29, sp
|
||||||
|
stp x19, x20, [sp, 16]
|
||||||
|
mov x19, x1
|
||||||
|
mov x1, x2
|
||||||
|
mov x2, x0
|
||||||
|
ldr x20, [x19]
|
||||||
|
mov x0, x20
|
||||||
|
mov x16, x0
|
||||||
|
.L10:
|
||||||
|
ldaxr x0, [x2]
|
||||||
|
cmp x0, x16
|
||||||
|
b.ne .L11
|
||||||
|
stlxr w17, x1, [x2]
|
||||||
|
cbnz w17, .L10
|
||||||
|
.L11:
|
||||||
|
cmp x0, x20
|
||||||
|
cset w1, eq
|
||||||
|
beq .L12
|
||||||
|
str x0, [x19]
|
||||||
|
.L12:
|
||||||
|
mov w0, w1
|
||||||
|
ldp x19, x20, [sp, 16]
|
||||||
|
ldp x29, x30, [sp], 32
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_8, .-__atomic_compare_exchange_8
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#elif defined __riscv
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_1
|
||||||
|
.type __atomic_compare_exchange_1, %function
|
||||||
|
__atomic_compare_exchange_1:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.short 0x1141
|
||||||
|
.short 0x86ba
|
||||||
|
.short 0x873e
|
||||||
|
.short 0xe406
|
||||||
|
.int 0x0ff0000f
|
||||||
|
.int 0x0005c803
|
||||||
|
.int 0xff857893
|
||||||
|
.int 0x0008b783
|
||||||
|
.short 0x891d
|
||||||
|
.short 0x050e
|
||||||
|
.int 0x0ff00693
|
||||||
|
.int 0x00a696b3
|
||||||
|
.int 0x00a81833
|
||||||
|
.int 0x00a61633
|
||||||
|
.int 0xfff6c713
|
||||||
|
.short 0x8f7d
|
||||||
|
.int 0x00f6f333
|
||||||
|
.short 0x8f51
|
||||||
|
.int 0x03031263
|
||||||
|
.int 0x1008b32f
|
||||||
|
.int 0x00f31663
|
||||||
|
.int 0x18e8be2f
|
||||||
|
.int 0xfe0e1ae3
|
||||||
|
.int 0x40f30733
|
||||||
|
.short 0x879a
|
||||||
|
.short 0xff69
|
||||||
|
.int 0x0ff0000f
|
||||||
|
.short 0x4505
|
||||||
|
.short 0xa801
|
||||||
|
.int 0x00a7d7b3
|
||||||
|
.int 0x00f58023
|
||||||
|
.int 0x0ff0000f
|
||||||
|
.short 0x4501
|
||||||
|
.short 0x60a2
|
||||||
|
.short 0x0141
|
||||||
|
.short 0x8082
|
||||||
|
#else
|
||||||
|
addi sp,sp,-16
|
||||||
|
mv a3,a4
|
||||||
|
mv a4,a5
|
||||||
|
sd ra,8(sp)
|
||||||
|
fence
|
||||||
|
lbu a6,0(a1)
|
||||||
|
andi a7,a0,-8
|
||||||
|
ld a5,0(a7)
|
||||||
|
andi a0,a0,7
|
||||||
|
slli a0,a0,0x3
|
||||||
|
li a3,255
|
||||||
|
sll a3,a3,a0
|
||||||
|
sll a6,a6,a0
|
||||||
|
sll a2,a2,a0
|
||||||
|
.L1:
|
||||||
|
not a4,a3
|
||||||
|
and a4,a4,a5
|
||||||
|
and t1,a3,a5
|
||||||
|
or a4,a4,a2
|
||||||
|
bne t1,a6,.L4
|
||||||
|
.L2:
|
||||||
|
lr.d t1,(a7)
|
||||||
|
bne t1,a5,.L3
|
||||||
|
sc.d t3,a4,(a7)
|
||||||
|
bnez t3,.L2
|
||||||
|
.L3:
|
||||||
|
sub a4,t1,a5
|
||||||
|
mv a5,t1
|
||||||
|
bnez a4,.L1
|
||||||
|
fence
|
||||||
|
li a0,1
|
||||||
|
j .L5
|
||||||
|
.L4:
|
||||||
|
srl a5,a5,a0
|
||||||
|
sb a5,0(a1)
|
||||||
|
fence
|
||||||
|
li a0,0
|
||||||
|
.L5:
|
||||||
|
ld ra,8(sp)
|
||||||
|
addi sp,sp,16
|
||||||
|
jr ra
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_1, .-__atomic_compare_exchange_1
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_2
|
||||||
|
.type __atomic_compare_exchange_2, %function
|
||||||
|
__atomic_compare_exchange_2:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.short 0x1141
|
||||||
|
.short 0x86ba
|
||||||
|
.short 0x873e
|
||||||
|
.short 0xe406
|
||||||
|
.int 0x0ff0000f
|
||||||
|
.int 0x0005d803
|
||||||
|
.int 0xff857893
|
||||||
|
.short 0x67c1
|
||||||
|
.short 0x891d
|
||||||
|
.int 0x0008b703
|
||||||
|
.short 0x050e
|
||||||
|
.short 0x17fd
|
||||||
|
.int 0x00a797b3
|
||||||
|
.int 0x00a81833
|
||||||
|
.int 0x00a61633
|
||||||
|
.int 0xfff7c693
|
||||||
|
.short 0x8ef9
|
||||||
|
.int 0x00e7f333
|
||||||
|
.short 0x8ed1
|
||||||
|
.int 0x03031263
|
||||||
|
.int 0x1008b32f
|
||||||
|
.int 0x00e31663
|
||||||
|
.int 0x18d8be2f
|
||||||
|
.int 0xfe0e1ae3
|
||||||
|
.int 0x40e306b3
|
||||||
|
.short 0x871a
|
||||||
|
.short 0xfee9
|
||||||
|
.int 0x0ff0000f
|
||||||
|
.short 0x4505
|
||||||
|
.short 0xa801
|
||||||
|
.int 0x00a75733
|
||||||
|
.int 0x00e59023
|
||||||
|
.int 0x0ff0000f
|
||||||
|
.short 0x4501
|
||||||
|
.short 0x60a2
|
||||||
|
.short 0x0141
|
||||||
|
.short 0x8082
|
||||||
|
#else
|
||||||
|
addi sp,sp,-16
|
||||||
|
mv a3,a4
|
||||||
|
mv a4,a5
|
||||||
|
sd ra,8(sp)
|
||||||
|
fence
|
||||||
|
lhu a6,0(a1)
|
||||||
|
andi a7,a0,-8
|
||||||
|
lui a5,0x10
|
||||||
|
andi a0,a0,7
|
||||||
|
ld a4,0(a7)
|
||||||
|
slli a0,a0,0x3
|
||||||
|
addi a5,a5,-1
|
||||||
|
sll a5,a5,a0
|
||||||
|
sll a6,a6,a0
|
||||||
|
sll a2,a2,a0
|
||||||
|
.L6:
|
||||||
|
not a3,a5
|
||||||
|
and a3,a3,a4
|
||||||
|
and t1,a5,a4
|
||||||
|
or a3,a3,a2
|
||||||
|
bne t1,a6,.L9
|
||||||
|
.L7:
|
||||||
|
lr.d t1,(a7)
|
||||||
|
bne t1,a4,.L8
|
||||||
|
sc.d t3,a3,(a7)
|
||||||
|
bnez t3,.L7
|
||||||
|
.L8:
|
||||||
|
sub a3,t1,a4
|
||||||
|
mv a4,t1
|
||||||
|
bnez a3,.L6
|
||||||
|
fence
|
||||||
|
li a0,1
|
||||||
|
j .L10
|
||||||
|
.L9:
|
||||||
|
srl a4,a4,a0
|
||||||
|
sh a4,0(a1)
|
||||||
|
fence
|
||||||
|
li a0,0
|
||||||
|
.L10:
|
||||||
|
ld ra,8(sp)
|
||||||
|
addi sp,sp,16
|
||||||
|
jr ra
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_2, .-__atomic_compare_exchange_2
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_4
|
||||||
|
.type __atomic_compare_exchange_4, %function
|
||||||
|
__atomic_compare_exchange_4:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.short 0x419c
|
||||||
|
.int 0x0f50000f
|
||||||
|
.int 0x1405272f
|
||||||
|
.int 0x00f71663
|
||||||
|
.int 0x1cc5282f
|
||||||
|
.int 0xfe081ae3
|
||||||
|
.int 0x40f707bb
|
||||||
|
.int 0x0017b513
|
||||||
|
.short 0xc391
|
||||||
|
.short 0xc198
|
||||||
|
.short 0x8905
|
||||||
|
.short 0x8082
|
||||||
|
#else
|
||||||
|
lw a5,0(a1)
|
||||||
|
fence iorw,ow;
|
||||||
|
.L11:
|
||||||
|
lr.w.aq a4,0(a0)
|
||||||
|
bne a4,a5,.L12
|
||||||
|
sc.w.aq a6,a2,0(a0)
|
||||||
|
bnez a6,.L11
|
||||||
|
.L12:
|
||||||
|
subw a5,a4,a5
|
||||||
|
seqz a0,a5
|
||||||
|
beq a5,zero,.L13
|
||||||
|
sw a4,0(a1)
|
||||||
|
.L13:
|
||||||
|
andi a0,a0,1
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_4, .-__atomic_compare_exchange_4
|
||||||
|
|
||||||
|
.global __atomic_compare_exchange_8
|
||||||
|
.type __atomic_compare_exchange_8, %function
|
||||||
|
__atomic_compare_exchange_8:
|
||||||
|
#ifdef __TINYC__
|
||||||
|
.short 0x619c
|
||||||
|
.int 0x0f50000f
|
||||||
|
.int 0x1405372f
|
||||||
|
.int 0x00f71563
|
||||||
|
.int 0x1cc536af
|
||||||
|
.short 0xfaf5
|
||||||
|
.int 0x40f707b3
|
||||||
|
.int 0x0017b513
|
||||||
|
.short 0xc391
|
||||||
|
.short 0xe198
|
||||||
|
.short 0x8905
|
||||||
|
.short 0x8082
|
||||||
|
#else
|
||||||
|
ld a5,0(a1)
|
||||||
|
fence iorw,ow;
|
||||||
|
.L14:
|
||||||
|
lr.d.aq a4,0(a0)
|
||||||
|
bne a4,a5,.L15
|
||||||
|
sc.d.aq a3,a2,0(a0)
|
||||||
|
bnez a3,.L14
|
||||||
|
.L15:
|
||||||
|
sub a5,a4,a5
|
||||||
|
seqz a0,a5
|
||||||
|
beq a5,zero,.L16
|
||||||
|
sd a4,0(a1)
|
||||||
|
.L16:
|
||||||
|
andi a0,a0,1
|
||||||
|
ret
|
||||||
|
#endif
|
||||||
|
.size __atomic_compare_exchange_8, .-__atomic_compare_exchange_8
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
#endif
|
175
lib/stdatomic.c
175
lib/stdatomic.c
|
@ -5,6 +5,7 @@
|
||||||
#define uint32_t unsigned int
|
#define uint32_t unsigned int
|
||||||
#define uint64_t unsigned long long
|
#define uint64_t unsigned long long
|
||||||
#define bool _Bool
|
#define bool _Bool
|
||||||
|
#define false 0
|
||||||
#define true 1
|
#define true 1
|
||||||
#define __ATOMIC_RELAXED 0
|
#define __ATOMIC_RELAXED 0
|
||||||
#define __ATOMIC_CONSUME 1
|
#define __ATOMIC_CONSUME 1
|
||||||
|
@ -12,8 +13,10 @@
|
||||||
#define __ATOMIC_RELEASE 3
|
#define __ATOMIC_RELEASE 3
|
||||||
#define __ATOMIC_ACQ_REL 4
|
#define __ATOMIC_ACQ_REL 4
|
||||||
#define __ATOMIC_SEQ_CST 5
|
#define __ATOMIC_SEQ_CST 5
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
|
||||||
#define ATOMIC_X86_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
#if defined __i386__ || defined __x86_64__
|
||||||
|
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
||||||
bool __atomic_compare_exchange_##MODE \
|
bool __atomic_compare_exchange_##MODE \
|
||||||
(volatile void *atom, void *ref, TYPE xchg, \
|
(volatile void *atom, void *ref, TYPE xchg, \
|
||||||
bool weak, int success_memorder, int failure_memorder) \
|
bool weak, int success_memorder, int failure_memorder) \
|
||||||
|
@ -29,96 +32,132 @@
|
||||||
*(TYPE *)ref = rv; \
|
*(TYPE *)ref = rv; \
|
||||||
return (rv == cmp); \
|
return (rv == cmp); \
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
||||||
|
extern bool __atomic_compare_exchange_##MODE \
|
||||||
|
(volatile void *atom, void *ref, TYPE xchg, \
|
||||||
|
bool weak, int success_memorder, int failure_memorder);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ATOMIC_X86_LOAD(TYPE, MODE) \
|
#define ATOMIC_LOAD(TYPE, MODE) \
|
||||||
TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
|
TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
|
||||||
{ \
|
{ \
|
||||||
return *(volatile TYPE *)atom; \
|
return *(volatile TYPE *)atom; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ATOMIC_X86_STORE(TYPE, MODE) \
|
#define ATOMIC_STORE(TYPE, MODE) \
|
||||||
void __atomic_store_##MODE(volatile void *atom, TYPE value, int memorder) \
|
void __atomic_store_##MODE(volatile void *atom, TYPE value, int memorder) \
|
||||||
{ \
|
{ \
|
||||||
*(volatile TYPE *)atom = value; \
|
*(volatile TYPE *)atom = value; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some tcc targets set __GNUC__ */
|
#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP, RET) \
|
||||||
#if defined(__GNUC__) && !defined(__TINYC__)
|
|
||||||
#define ATOMIC_LOAD(t,a,b,c) t b; __atomic_load((t *)a, (t *)&b, c)
|
|
||||||
#define COMPARE_EXCHANGE(t,a,b,c,d,e,f) __atomic_compare_exchange((t *)a,b,&c,d,e,f)
|
|
||||||
#else
|
|
||||||
#define ATOMIC_LOAD(t,a,b,c) t b = __atomic_load((t *)a, c)
|
|
||||||
#define COMPARE_EXCHANGE(t,a,b,c,d,e,f) __atomic_compare_exchange((t *)a,b,c,d,e,f)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP) \
|
|
||||||
TYPE __atomic_##NAME##_##MODE(volatile void *atom, TYPE value, int memorder) \
|
TYPE __atomic_##NAME##_##MODE(volatile void *atom, TYPE value, int memorder) \
|
||||||
{ \
|
{ \
|
||||||
TYPE xchg; \
|
TYPE xchg, cmp; \
|
||||||
ATOMIC_LOAD(TYPE, atom, cmp, __ATOMIC_RELAXED); \
|
__atomic_load((TYPE *)atom, (TYPE *)&cmp, __ATOMIC_RELAXED); \
|
||||||
do { \
|
do { \
|
||||||
xchg = (OP); \
|
xchg = (OP); \
|
||||||
} while (!COMPARE_EXCHANGE(TYPE, atom, &cmp, xchg, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \
|
} while (!__atomic_compare_exchange((TYPE *)atom, &cmp, &xchg, true, \
|
||||||
return cmp; \
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \
|
||||||
|
return RET; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ATOMIC_EXCHANGE(TYPE, MODE) \
|
#define ATOMIC_EXCHANGE(TYPE, MODE) \
|
||||||
ATOMIC_GEN_OP(TYPE, MODE, exchange, value)
|
ATOMIC_GEN_OP(TYPE, MODE, exchange, value, cmp)
|
||||||
|
#define ATOMIC_ADD_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, add_fetch, (cmp + value), xchg)
|
||||||
|
#define ATOMIC_SUB_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, sub_fetch, (cmp - value), xchg)
|
||||||
|
#define ATOMIC_AND_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, and_fetch, (cmp & value), xchg)
|
||||||
|
#define ATOMIC_OR_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, or_fetch, (cmp | value), xchg)
|
||||||
|
#define ATOMIC_XOR_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, xor_fetch, (cmp ^ value), xchg)
|
||||||
|
#define ATOMIC_NAND_FETCH(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, nand_fetch, ~(cmp & value), xchg)
|
||||||
#define ATOMIC_FETCH_ADD(TYPE, MODE) \
|
#define ATOMIC_FETCH_ADD(TYPE, MODE) \
|
||||||
ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value))
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value), cmp)
|
||||||
#define ATOMIC_FETCH_SUB(TYPE, MODE) \
|
#define ATOMIC_FETCH_SUB(TYPE, MODE) \
|
||||||
ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value))
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value), cmp)
|
||||||
#define ATOMIC_FETCH_AND(TYPE, MODE) \
|
#define ATOMIC_FETCH_AND(TYPE, MODE) \
|
||||||
ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value))
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value), cmp)
|
||||||
#define ATOMIC_FETCH_OR(TYPE, MODE) \
|
#define ATOMIC_FETCH_OR(TYPE, MODE) \
|
||||||
ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value))
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value), cmp)
|
||||||
#define ATOMIC_FETCH_XOR(TYPE, MODE) \
|
#define ATOMIC_FETCH_XOR(TYPE, MODE) \
|
||||||
ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value))
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value), cmp)
|
||||||
|
#define ATOMIC_FETCH_NAND(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_nand, ~(cmp & value), cmp)
|
||||||
|
|
||||||
ATOMIC_X86_STORE(uint8_t, 1)
|
#define ATOMIC_GEN(TYPE, SIZE, SUFFIX) \
|
||||||
ATOMIC_X86_STORE(uint16_t, 2)
|
ATOMIC_STORE(TYPE, SIZE) \
|
||||||
ATOMIC_X86_STORE(uint32_t, 4)
|
ATOMIC_LOAD(TYPE, SIZE) \
|
||||||
|
ATOMIC_COMPARE_EXCHANGE(TYPE, SIZE, SUFFIX) \
|
||||||
|
ATOMIC_EXCHANGE(TYPE, SIZE) \
|
||||||
|
ATOMIC_ADD_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_SUB_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_AND_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_OR_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_XOR_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_NAND_FETCH(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_ADD(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_SUB(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_AND(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_OR(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_XOR(TYPE, SIZE) \
|
||||||
|
ATOMIC_FETCH_NAND(TYPE, SIZE)
|
||||||
|
|
||||||
ATOMIC_X86_LOAD(uint8_t, 1)
|
ATOMIC_GEN(uint8_t, 1, "b")
|
||||||
ATOMIC_X86_LOAD(uint16_t, 2)
|
ATOMIC_GEN(uint16_t, 2, "w")
|
||||||
ATOMIC_X86_LOAD(uint32_t, 4)
|
ATOMIC_GEN(uint32_t, 4, "l")
|
||||||
|
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint8_t, 1, "b")
|
ATOMIC_GEN(uint64_t, 8, "q")
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint16_t, 2, "w")
|
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint32_t, 4, "l")
|
|
||||||
|
|
||||||
ATOMIC_EXCHANGE(uint8_t, 1)
|
|
||||||
ATOMIC_EXCHANGE(uint16_t, 2)
|
|
||||||
ATOMIC_EXCHANGE(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_ADD(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_ADD(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_ADD(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_SUB(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_SUB(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_SUB(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_AND(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_AND(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_AND(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_OR(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_OR(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_OR(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_XOR(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_XOR(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_XOR(uint32_t, 4)
|
|
||||||
|
|
||||||
#if defined __x86_64__
|
|
||||||
ATOMIC_X86_STORE(uint64_t, 8)
|
|
||||||
ATOMIC_X86_LOAD(uint64_t, 8)
|
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint64_t, 8, "q")
|
|
||||||
ATOMIC_EXCHANGE(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_ADD(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_SUB(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_AND(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_OR(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_XOR(uint64_t, 8)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool __atomic_test_and_set (volatile void *ptr, int memorder)
|
||||||
|
{
|
||||||
|
return __atomic_exchange_1(ptr, 1, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __atomic_clear (volatile void *ptr, int memorder)
|
||||||
|
{
|
||||||
|
__atomic_store_1(ptr, 0, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __atomic_signal_fence (int memorder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void __atomic_thread_fence (int memorder)
|
||||||
|
{
|
||||||
|
#if defined __i386__
|
||||||
|
asm volatile("lock orl $0, (%esp)");
|
||||||
|
#elif defined __x86_64__
|
||||||
|
asm volatile("lock orq $0, (%rsp)");
|
||||||
|
#elif defined __arm__
|
||||||
|
asm volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5
|
||||||
|
#elif defined __aarch64__
|
||||||
|
asm volatile(".int 0xd5033bbf"); // dmb ish
|
||||||
|
#elif defined __riscv
|
||||||
|
asm volatile(".int 0x0ff0000f"); // fence iorw,iorw
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __atomic_is_lock_free(size_t size, void *ptr)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
switch (size) {
|
||||||
|
case 1: ret = true; break;
|
||||||
|
case 2: ret = true; break;
|
||||||
|
case 4: ret = true; break;
|
||||||
|
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
||||||
|
case 8: ret = true; break;
|
||||||
|
#else
|
||||||
|
case 8: ret = false; break;
|
||||||
|
#endif
|
||||||
|
default: ret = false; break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
57
tccgen.c
57
tccgen.c
|
@ -5171,8 +5171,9 @@ static void parse_builtin_params(int nc, const char *args)
|
||||||
|
|
||||||
static void parse_atomic(int atok)
|
static void parse_atomic(int atok)
|
||||||
{
|
{
|
||||||
int size, align, arg;
|
int size, align, arg, t, save = 0;
|
||||||
CType *atom, *atom_ptr, ct = {0};
|
CType *atom, *atom_ptr, ct = {0};
|
||||||
|
SValue store;
|
||||||
char buf[40];
|
char buf[40];
|
||||||
static const char *const templates[] = {
|
static const char *const templates[] = {
|
||||||
/*
|
/*
|
||||||
|
@ -5185,19 +5186,28 @@ static void parse_atomic(int atok)
|
||||||
* A read-only atomic
|
* A read-only atomic
|
||||||
* p pointer to memory
|
* p pointer to memory
|
||||||
* v value
|
* v value
|
||||||
|
* l load pointer
|
||||||
|
* s save pointer
|
||||||
* m memory model
|
* m memory model
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* keep in order of appearance in tcctok.h: */
|
/* keep in order of appearance in tcctok.h: */
|
||||||
/* __atomic_store */ "avm.?",
|
/* __atomic_store */ "alm.?",
|
||||||
/* __atomic_load */ "Am.v",
|
/* __atomic_load */ "Asm.v",
|
||||||
/* __atomic_exchange */ "avm.v",
|
/* __atomic_exchange */ "alsm.v",
|
||||||
/* __atomic_compare_exchange */ "apvbmm.b",
|
/* __atomic_compare_exchange */ "aplbmm.b",
|
||||||
/* __atomic_fetch_add */ "avm.v",
|
/* __atomic_fetch_add */ "avm.v",
|
||||||
/* __atomic_fetch_sub */ "avm.v",
|
/* __atomic_fetch_sub */ "avm.v",
|
||||||
/* __atomic_fetch_or */ "avm.v",
|
/* __atomic_fetch_or */ "avm.v",
|
||||||
/* __atomic_fetch_xor */ "avm.v",
|
/* __atomic_fetch_xor */ "avm.v",
|
||||||
/* __atomic_fetch_and */ "avm.v"
|
/* __atomic_fetch_and */ "avm.v",
|
||||||
|
/* __atomic_fetch_nand */ "avm.v",
|
||||||
|
/* __atomic_and_fetch */ "avm.v",
|
||||||
|
/* __atomic_sub_fetch */ "avm.v",
|
||||||
|
/* __atomic_or_fetch */ "avm.v",
|
||||||
|
/* __atomic_xor_fetch */ "avm.v",
|
||||||
|
/* __atomic_and_fetch */ "avm.v",
|
||||||
|
/* __atomic_nand_fetch */ "avm.v"
|
||||||
};
|
};
|
||||||
const char *template = templates[(atok - TOK___atomic_store)];
|
const char *template = templates[(atok - TOK___atomic_store)];
|
||||||
|
|
||||||
|
@ -5235,6 +5245,16 @@ static void parse_atomic(int atok)
|
||||||
case 'v':
|
case 'v':
|
||||||
gen_assign_cast(atom);
|
gen_assign_cast(atom);
|
||||||
break;
|
break;
|
||||||
|
case 'l':
|
||||||
|
indir();
|
||||||
|
gen_assign_cast(atom);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
save = 1;
|
||||||
|
indir();
|
||||||
|
store = *vtop;
|
||||||
|
vpop();
|
||||||
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
gen_assign_cast(&int_type);
|
gen_assign_cast(&int_type);
|
||||||
break;
|
break;
|
||||||
|
@ -5261,18 +5281,26 @@ static void parse_atomic(int atok)
|
||||||
|
|
||||||
sprintf(buf, "%s_%d", get_tok_str(atok, 0), size);
|
sprintf(buf, "%s_%d", get_tok_str(atok, 0), size);
|
||||||
vpush_helper_func(tok_alloc_const(buf));
|
vpush_helper_func(tok_alloc_const(buf));
|
||||||
vrott(arg + 1);
|
vrott(arg - save + 1);
|
||||||
gfunc_call(arg);
|
gfunc_call(arg - save);
|
||||||
|
|
||||||
vpush(&ct);
|
vpush(&ct);
|
||||||
PUT_R_RET(vtop, ct.t);
|
PUT_R_RET(vtop, ct.t);
|
||||||
if (ct.t == VT_BOOL) {
|
t = ct.t & VT_BTYPE;
|
||||||
|
if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) {
|
||||||
#ifdef PROMOTE_RET
|
#ifdef PROMOTE_RET
|
||||||
vtop->r |= BFVAL(VT_MUSTCAST, 1);
|
vtop->r |= BFVAL(VT_MUSTCAST, 1);
|
||||||
#else
|
#else
|
||||||
vtop->type.t = VT_INT;
|
vtop->type.t = VT_INT;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
gen_cast(&ct);
|
||||||
|
if (save) {
|
||||||
|
vpush(&ct);
|
||||||
|
*vtop = store;
|
||||||
|
vswap();
|
||||||
|
vstore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void unary(void)
|
ST_FUNC void unary(void)
|
||||||
|
@ -5660,6 +5688,13 @@ ST_FUNC void unary(void)
|
||||||
case TOK___atomic_fetch_or:
|
case TOK___atomic_fetch_or:
|
||||||
case TOK___atomic_fetch_xor:
|
case TOK___atomic_fetch_xor:
|
||||||
case TOK___atomic_fetch_and:
|
case TOK___atomic_fetch_and:
|
||||||
|
case TOK___atomic_fetch_nand:
|
||||||
|
case TOK___atomic_add_fetch:
|
||||||
|
case TOK___atomic_sub_fetch:
|
||||||
|
case TOK___atomic_or_fetch:
|
||||||
|
case TOK___atomic_xor_fetch:
|
||||||
|
case TOK___atomic_and_fetch:
|
||||||
|
case TOK___atomic_nand_fetch:
|
||||||
parse_atomic(tok);
|
parse_atomic(tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
7
tcctok.h
7
tcctok.h
|
@ -187,6 +187,13 @@
|
||||||
DEF_ATOMIC(atomic_fetch_or)
|
DEF_ATOMIC(atomic_fetch_or)
|
||||||
DEF_ATOMIC(atomic_fetch_xor)
|
DEF_ATOMIC(atomic_fetch_xor)
|
||||||
DEF_ATOMIC(atomic_fetch_and)
|
DEF_ATOMIC(atomic_fetch_and)
|
||||||
|
DEF_ATOMIC(atomic_fetch_nand)
|
||||||
|
DEF_ATOMIC(atomic_add_fetch)
|
||||||
|
DEF_ATOMIC(atomic_sub_fetch)
|
||||||
|
DEF_ATOMIC(atomic_or_fetch)
|
||||||
|
DEF_ATOMIC(atomic_xor_fetch)
|
||||||
|
DEF_ATOMIC(atomic_and_fetch)
|
||||||
|
DEF_ATOMIC(atomic_nand_fetch)
|
||||||
|
|
||||||
/* pragma */
|
/* pragma */
|
||||||
DEF(TOK_pack, "pack")
|
DEF(TOK_pack, "pack")
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
#define NR_THREADS 16
|
#define NR_THREADS 16
|
||||||
#define NR_STEPS ((uint32_t)UINT16_MAX * 4)
|
#define NR_STEPS ((uint32_t)UINT16_MAX)
|
||||||
|
|
||||||
#define BUG_ON(COND) \
|
#define BUG_ON(COND) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -14,14 +14,34 @@
|
||||||
abort(); \
|
abort(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
||||||
|
#define HAS_64BITS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
atomic_flag flag;
|
||||||
|
atomic_uchar uc;
|
||||||
|
atomic_ushort us;
|
||||||
|
atomic_uint ui;
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_size_t ul;
|
||||||
|
#endif
|
||||||
|
} counter_type;
|
||||||
|
|
||||||
static
|
static
|
||||||
void *adder_simple(void *arg)
|
void *adder_simple(void *arg)
|
||||||
{
|
{
|
||||||
size_t step;
|
size_t step;
|
||||||
atomic_size_t *counter = arg;
|
counter_type *counter = arg;
|
||||||
|
|
||||||
for (step = 0; step < NR_STEPS; ++step)
|
for (step = 0; step < NR_STEPS; ++step) {
|
||||||
atomic_fetch_add_explicit(counter, 1, memory_order_relaxed);
|
atomic_fetch_add_explicit(&counter->uc, 1, memory_order_relaxed);
|
||||||
|
atomic_fetch_add_explicit(&counter->us, 1, memory_order_relaxed);
|
||||||
|
atomic_fetch_add_explicit(&counter->ui, 1, memory_order_relaxed);
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_fetch_add_explicit(&counter->ul, 1, memory_order_relaxed);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -30,16 +50,60 @@ static
|
||||||
void *adder_cmpxchg(void *arg)
|
void *adder_cmpxchg(void *arg)
|
||||||
{
|
{
|
||||||
size_t step;
|
size_t step;
|
||||||
atomic_size_t *counter = arg;
|
counter_type *counter = arg;
|
||||||
|
|
||||||
for (step = 0; step < NR_STEPS; ++step) {
|
for (step = 0; step < NR_STEPS; ++step) {
|
||||||
size_t xchg;
|
unsigned char xchgc;
|
||||||
size_t cmp = atomic_load_explicit(counter, memory_order_relaxed);
|
unsigned short xchgs;
|
||||||
|
unsigned int xchgi;
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
size_t xchgl;
|
||||||
|
#endif
|
||||||
|
unsigned char cmpc = atomic_load_explicit(&counter->uc, memory_order_relaxed);
|
||||||
|
unsigned short cmps = atomic_load_explicit(&counter->us, memory_order_relaxed);
|
||||||
|
unsigned int cmpi = atomic_load_explicit(&counter->ui, memory_order_relaxed);
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
size_t cmpl = atomic_load_explicit(&counter->ul, memory_order_relaxed);
|
||||||
|
#endif
|
||||||
|
|
||||||
do {
|
do {
|
||||||
xchg = (cmp + 1);
|
xchgc = (cmpc + 1);
|
||||||
} while (!atomic_compare_exchange_strong_explicit(counter,
|
} while (!atomic_compare_exchange_strong_explicit(&counter->uc,
|
||||||
&cmp, xchg, memory_order_relaxed, memory_order_relaxed));
|
&cmpc, xchgc, memory_order_relaxed, memory_order_relaxed));
|
||||||
|
do {
|
||||||
|
xchgs = (cmps + 1);
|
||||||
|
} while (!atomic_compare_exchange_strong_explicit(&counter->us,
|
||||||
|
&cmps, xchgs, memory_order_relaxed, memory_order_relaxed));
|
||||||
|
do {
|
||||||
|
xchgi = (cmpi + 1);
|
||||||
|
} while (!atomic_compare_exchange_strong_explicit(&counter->ui,
|
||||||
|
&cmpi, xchgi, memory_order_relaxed, memory_order_relaxed));
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
do {
|
||||||
|
xchgl = (cmpl + 1);
|
||||||
|
} while (!atomic_compare_exchange_strong_explicit(&counter->ul,
|
||||||
|
&cmpl, xchgl, memory_order_relaxed, memory_order_relaxed));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void *adder_test_and_set(void *arg)
|
||||||
|
{
|
||||||
|
size_t step;
|
||||||
|
counter_type *counter = arg;
|
||||||
|
|
||||||
|
for (step = 0; step < NR_STEPS; ++step) {
|
||||||
|
while (atomic_flag_test_and_set(&counter->flag));
|
||||||
|
++counter->uc;
|
||||||
|
++counter->us;
|
||||||
|
++counter->ui;
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
++counter->ul;
|
||||||
|
#endif
|
||||||
|
atomic_flag_clear(&counter->flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -49,10 +113,16 @@ static
|
||||||
void atomic_counter_test(void *(*adder)(void *arg))
|
void atomic_counter_test(void *(*adder)(void *arg))
|
||||||
{
|
{
|
||||||
size_t index;
|
size_t index;
|
||||||
atomic_size_t counter;
|
counter_type counter;
|
||||||
pthread_t thread[NR_THREADS];
|
pthread_t thread[NR_THREADS];
|
||||||
|
|
||||||
atomic_init(&counter, 0);
|
atomic_flag_clear(&counter.flag);
|
||||||
|
atomic_init(&counter.uc, 0);
|
||||||
|
atomic_init(&counter.us, 0);
|
||||||
|
atomic_init(&counter.ui, 0);
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_init(&counter.ul, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (index = 0; index < NR_THREADS; ++index)
|
for (index = 0; index < NR_THREADS; ++index)
|
||||||
BUG_ON(pthread_create(&thread[index], NULL, adder, (void *)&counter));
|
BUG_ON(pthread_create(&thread[index], NULL, adder, (void *)&counter));
|
||||||
|
@ -60,7 +130,13 @@ void atomic_counter_test(void *(*adder)(void *arg))
|
||||||
for (index = 0; index < NR_THREADS; ++index)
|
for (index = 0; index < NR_THREADS; ++index)
|
||||||
BUG_ON(pthread_join(thread[index], NULL));
|
BUG_ON(pthread_join(thread[index], NULL));
|
||||||
|
|
||||||
if (atomic_load(&counter) == (NR_THREADS * NR_STEPS))
|
if (atomic_load(&counter.uc) == ((NR_THREADS * NR_STEPS) & 0xffu)
|
||||||
|
&& atomic_load(&counter.us) == ((NR_THREADS * NR_STEPS) & 0xffffu)
|
||||||
|
&& atomic_load(&counter.ui) == (NR_THREADS * NR_STEPS)
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
&& atomic_load(&counter.ul) == (NR_THREADS * NR_STEPS)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
printf("SUCCESS\n");
|
printf("SUCCESS\n");
|
||||||
else
|
else
|
||||||
printf("FAILURE\n");
|
printf("FAILURE\n");
|
||||||
|
@ -70,6 +146,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
atomic_counter_test(adder_simple);
|
atomic_counter_test(adder_simple);
|
||||||
atomic_counter_test(adder_cmpxchg);
|
atomic_counter_test(adder_cmpxchg);
|
||||||
|
atomic_counter_test(adder_test_and_set);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
SUCCESS
|
SUCCESS
|
||||||
SUCCESS
|
SUCCESS
|
||||||
|
SUCCESS
|
||||||
|
|
|
@ -16,6 +16,14 @@ int main()
|
||||||
r = atomic_compare_exchange_strong(&a, &b, 99);
|
r = atomic_compare_exchange_strong(&a, &b, 99);
|
||||||
printf("%d %d %d\n", r, a, b);
|
printf("%d %d %d\n", r, a, b);
|
||||||
|
|
||||||
|
atomic_store(&a, b + 5);
|
||||||
|
r = atomic_exchange(&a, 33);
|
||||||
|
printf("%d %d %d\n", r, a, b);
|
||||||
|
|
||||||
|
atomic_store(&a, b + 10);
|
||||||
|
r = atomic_exchange(&a, 66);
|
||||||
|
printf("%d %d %d\n", r, a, b);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +58,117 @@ int main()
|
||||||
printf("%d %d %d %d\n", p.c[0], p.c[1], p.c[2], p.c[3]);
|
printf("%d %d %d %d\n", p.c[0], p.c[1], p.c[2], p.c[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_op
|
||||||
|
|
||||||
|
#define OP1(func, v, e1, e2) atomic_##func(&c, v) == e1 && c == e2
|
||||||
|
#define OP2(func, v, e1, e2) atomic_##func(&s, v) == e1 && s == e2
|
||||||
|
#define OP4(func, v, e1, e2) atomic_##func(&i, v) == e1 && i == e2
|
||||||
|
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
||||||
|
#define OP8(func, v, e1, e2) atomic_##func(&l, v) == e1 && l == e2
|
||||||
|
#define HAS_64BITS
|
||||||
|
#else
|
||||||
|
#define OP8(func, v, e1, e2) 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OP(func, v, e1, e2) printf ("%s: %s\n", #func, \
|
||||||
|
OP1(func,v,e1,e2) && OP2(func,v,e1,e2) && \
|
||||||
|
OP4(func,v,e1,e2) && OP8(func,v,e1,e2) \
|
||||||
|
? "SUCCESS" : "FAIL");
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
atomic_char c;
|
||||||
|
atomic_short s;
|
||||||
|
atomic_int i;
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_size_t l;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
atomic_init(&c, 0);
|
||||||
|
atomic_init(&s, 0);
|
||||||
|
atomic_init(&i, 0);
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_init(&l, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OP(fetch_add, 10, 0, 10);
|
||||||
|
OP(fetch_sub, 5, 10, 5);
|
||||||
|
OP(fetch_or, 0x10, 5, 21);
|
||||||
|
OP(fetch_xor, 0x20, 21, 53);
|
||||||
|
OP(fetch_and, 0x0f, 53, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_op2
|
||||||
|
|
||||||
|
typedef __SIZE_TYPE__ size64_t;
|
||||||
|
|
||||||
|
#define OP1(func, v, e1, e2) \
|
||||||
|
__atomic_##func(&c, v, __ATOMIC_SEQ_CST) == e1 && c == e2
|
||||||
|
#define OP2(func, v, e1, e2)\
|
||||||
|
__atomic_##func(&s, v, __ATOMIC_SEQ_CST) == e1 && s == e2
|
||||||
|
#define OP4(func, v, e1, e2)\
|
||||||
|
__atomic_##func(&i, v, __ATOMIC_SEQ_CST) == e1 && i == e2
|
||||||
|
#if defined __x86_64__ || defined __aarch64__ || defined __riscv
|
||||||
|
#define OP8(func, v, e1, e2)\
|
||||||
|
__atomic_##func(&l, v, __ATOMIC_SEQ_CST) == e1 && l == e2
|
||||||
|
#define HAS_64BITS
|
||||||
|
#else
|
||||||
|
#define OP8(func, v, e1, e2) 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OP(func, v, e1, e2) printf ("%s: %s\n", #func, \
|
||||||
|
OP1(func,v,e1,e2) && OP2(func,v,e1,e2) && \
|
||||||
|
OP4(func,v,e1,e2) && OP8(func,v,e1,e2) \
|
||||||
|
? "SUCCESS" : "FAIL");
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
signed char c;
|
||||||
|
short s;
|
||||||
|
int i;
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
size64_t l;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
atomic_init(&c, 0);
|
||||||
|
atomic_init(&s, 0);
|
||||||
|
atomic_init(&i, 0);
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_init(&l, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OP(fetch_add, 10, 0, 10);
|
||||||
|
OP(fetch_sub, 5, 10, 5);
|
||||||
|
OP(fetch_or, 0x10, 5, 21);
|
||||||
|
OP(fetch_xor, 0x20, 21, 53);
|
||||||
|
OP(fetch_and, 0x0f, 53, 5);
|
||||||
|
OP(fetch_nand, 0x01, 5, -2);
|
||||||
|
|
||||||
|
atomic_init(&c, 0);
|
||||||
|
atomic_init(&s, 0);
|
||||||
|
atomic_init(&i, 0);
|
||||||
|
#ifdef HAS_64BITS
|
||||||
|
atomic_init(&l, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OP(add_fetch, 10, 10, 10);
|
||||||
|
OP(sub_fetch, 5, 5, 5);
|
||||||
|
OP(or_fetch, 0x10, 21, 21);
|
||||||
|
OP(xor_fetch, 0x20, 53, 53);
|
||||||
|
OP(and_fetch, 0x0f, 5, 5);
|
||||||
|
OP(nand_fetch, 0x01, -2, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_thread_signal
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
atomic_thread_fence(__ATOMIC_SEQ_CST);
|
||||||
|
atomic_signal_fence(__ATOMIC_SEQ_CST);
|
||||||
|
printf ("%d\n", atomic_is_lock_free(&c));
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined test_atomic_error_1
|
#elif defined test_atomic_error_1
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
[test_atomic_compare_exchange]
|
[test_atomic_compare_exchange]
|
||||||
1 99 77
|
1 99 77
|
||||||
0 80 80
|
0 80 80
|
||||||
|
85 33 80
|
||||||
|
90 66 80
|
||||||
|
|
||||||
[test_atomic_store]
|
[test_atomic_store]
|
||||||
r = 12, i = 24
|
r = 12, i = 24
|
||||||
|
@ -11,23 +13,47 @@ r = 12, i = 24
|
||||||
[test_atomic_store_struct]
|
[test_atomic_store_struct]
|
||||||
1 2 3 4
|
1 2 3 4
|
||||||
|
|
||||||
|
[test_atomic_op]
|
||||||
|
fetch_add: SUCCESS
|
||||||
|
fetch_sub: SUCCESS
|
||||||
|
fetch_or: SUCCESS
|
||||||
|
fetch_xor: SUCCESS
|
||||||
|
fetch_and: SUCCESS
|
||||||
|
|
||||||
|
[test_atomic_op2]
|
||||||
|
fetch_add: SUCCESS
|
||||||
|
fetch_sub: SUCCESS
|
||||||
|
fetch_or: SUCCESS
|
||||||
|
fetch_xor: SUCCESS
|
||||||
|
fetch_and: SUCCESS
|
||||||
|
fetch_nand: SUCCESS
|
||||||
|
add_fetch: SUCCESS
|
||||||
|
sub_fetch: SUCCESS
|
||||||
|
or_fetch: SUCCESS
|
||||||
|
xor_fetch: SUCCESS
|
||||||
|
and_fetch: SUCCESS
|
||||||
|
nand_fetch: SUCCESS
|
||||||
|
|
||||||
|
[test_atomic_thread_signal]
|
||||||
|
1
|
||||||
|
|
||||||
[test_atomic_error_1]
|
[test_atomic_error_1]
|
||||||
125_atomic_misc.c:57: error: pointer expected
|
125_atomic_misc.c:176: error: pointer expected
|
||||||
|
|
||||||
[test_atomic_error_2]
|
[test_atomic_error_2]
|
||||||
125_atomic_misc.c:64: error: integral or integer-sized pointer target type expected
|
125_atomic_misc.c:183: error: integral or integer-sized pointer target type expected
|
||||||
|
|
||||||
[test_atomic_error_3]
|
[test_atomic_error_3]
|
||||||
125_atomic_misc.c:71: error: integral or integer-sized pointer target type expected
|
125_atomic_misc.c:190: error: integral or integer-sized pointer target type expected
|
||||||
|
|
||||||
[test_atomic_error_4]
|
[test_atomic_error_4]
|
||||||
125_atomic_misc.c:79: error: pointer target type mismatch in argument 2
|
125_atomic_misc.c:198: error: pointer target type mismatch in argument 2
|
||||||
|
|
||||||
[test_atomic_warn_1]
|
[test_atomic_warn_1]
|
||||||
125_atomic_misc.c:87: warning: assignment makes integer from pointer without a cast
|
125_atomic_misc.c:206: warning: assignment makes integer from pointer without a cast
|
||||||
|
|
||||||
[test_atomic_warn_2]
|
[test_atomic_warn_2]
|
||||||
125_atomic_misc.c:97: warning: assignment from incompatible pointer type
|
125_atomic_misc.c:216: warning: assignment from incompatible pointer type
|
||||||
|
|
||||||
[test_atomic_warn_3]
|
[test_atomic_warn_3]
|
||||||
125_atomic_misc.c:105: warning: assignment of read-only location
|
125_atomic_misc.c:224: warning: assignment of read-only location
|
||||||
|
|
|
@ -23,8 +23,6 @@ ifeq (,$(filter i386,$(ARCH)))
|
||||||
endif
|
endif
|
||||||
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
||||||
SKIP += 85_asm-outside-function.test # x86 asm
|
SKIP += 85_asm-outside-function.test # x86 asm
|
||||||
SKIP += 124_atomic_counter.test
|
|
||||||
SKIP += 125_atomic_misc.test # currently only x86 supported
|
|
||||||
SKIP += 127_asm_goto.test # hardcodes x86 asm
|
SKIP += 127_asm_goto.test # hardcodes x86 asm
|
||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG_backtrace),no)
|
ifeq ($(CONFIG_backtrace),no)
|
||||||
|
|
Loading…
Add table
Reference in a new issue