mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 23:54:16 +08:00
Add GCC-style atomic builtins: __atomic_*_n
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
This commit adds GCC-compatible atomic builtins to stdatomic.h for
better compatibility with code relying on GCC's atomic primitives.
1. **New Macros**:
- `__atomic_compare_exchange_n`.
- `__atomic_load_n`.
- `__atomic_store_n`.
2. **Motivation**:
- Improves compatibility with codebases using GCC's atomic builtins
directly.
- Simplifies atomic operations by allowing direct value passing
(instead of pointers), enhancing code readability.
- Aligns TCC's atomic support closer to GCC/Clang for cross-compiler
projects.
3. **Testing**:
- Verified with basic test cases (integer CAS, load/store) on x86.
- Confirmed no regressions in existing atomic operations.
- This change does not affect existing C11 `atomic_*` APIs.
- Struct types are intentionally unsupported in `_n` variants due to
complexity.
This commit is contained in:
parent
f10ab130ec
commit
36ff4f52b5
@ -94,6 +94,8 @@ typedef struct {
|
||||
#define atomic_init(object, desired) \
|
||||
atomic_store_explicit(object, desired, __ATOMIC_RELAXED)
|
||||
|
||||
#define __atomic_store_n(ptr, val, order) \
|
||||
(*(ptr) = (val), __atomic_store((ptr), &(typeof(*(ptr))){val}, (order)))
|
||||
#define atomic_store_explicit(object, desired, order) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp = (desired); \
|
||||
@ -102,6 +104,10 @@ typedef struct {
|
||||
#define atomic_store(object, desired) \
|
||||
atomic_store_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define __atomic_load_n(ptr, order) \
|
||||
({ typeof(*(ptr)) __val; \
|
||||
__atomic_load((ptr), &__val, (order)); \
|
||||
__val; })
|
||||
#define atomic_load_explicit(object, order) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp; \
|
||||
@ -119,7 +125,10 @@ typedef struct {
|
||||
})
|
||||
#define atomic_exchange(object, desired) \
|
||||
atomic_exchange_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define __atomic_compare_exchange_n(ptr, expected, desired, weak, success, failure) \
|
||||
({ typeof(*(ptr)) __desired = (desired); \
|
||||
__atomic_compare_exchange((ptr), (expected), &__desired, \
|
||||
(weak), (success), (failure)); })
|
||||
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp = desired; \
|
||||
@ -128,7 +137,6 @@ typedef struct {
|
||||
#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_explicit(object, expected, desired, success, failure) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp = desired; \
|
||||
|
||||
75
tests/tests2/136_atomic_gcc_style.c
Normal file
75
tests/tests2/136_atomic_gcc_style.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
// Test 1: Basic functionality of __atomic_store_n and __atomic_load_n
|
||||
{
|
||||
int atomic_var = 0;
|
||||
__atomic_store_n(&atomic_var, 42, __ATOMIC_SEQ_CST);
|
||||
int loaded = __atomic_load_n(&atomic_var, __ATOMIC_SEQ_CST);
|
||||
assert(loaded == 42);
|
||||
}
|
||||
|
||||
// Test 2: Successful exchange with __atomic_compare_exchange_n
|
||||
{
|
||||
int atomic_var = 100;
|
||||
int expected = 100;
|
||||
bool success = __atomic_compare_exchange_n(
|
||||
&atomic_var, &expected, 200,
|
||||
false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST
|
||||
);
|
||||
assert(success);
|
||||
assert(atomic_var == 200);
|
||||
assert(expected == 100); // expected remains unchanged on success
|
||||
}
|
||||
|
||||
// Test 3: Failed exchange with __atomic_compare_exchange_n (update expected)
|
||||
{
|
||||
int atomic_var = 100;
|
||||
int expected = 99;
|
||||
bool success = __atomic_compare_exchange_n(
|
||||
&atomic_var, &expected, 200,
|
||||
false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST
|
||||
);
|
||||
assert(!success);
|
||||
assert(atomic_var == 100);
|
||||
assert(expected == 100); // expected updated to current value on failure
|
||||
}
|
||||
|
||||
// Test 4: Weak version (spurious failure handling)
|
||||
{
|
||||
int atomic_var = 50;
|
||||
int expected = 50;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (__atomic_compare_exchange_n(
|
||||
&atomic_var, &expected, 60,
|
||||
true, __ATOMIC_RELAXED, __ATOMIC_RELAXED
|
||||
)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(atomic_var == 60);
|
||||
}
|
||||
|
||||
// Test 5: Pointer type operations
|
||||
{
|
||||
int value = 100;
|
||||
int* atomic_ptr = &value;
|
||||
int* new_ptr = NULL;
|
||||
__atomic_store_n(&atomic_ptr, new_ptr, __ATOMIC_RELEASE);
|
||||
int* loaded_ptr = __atomic_load_n(&atomic_ptr, __ATOMIC_ACQUIRE);
|
||||
assert(loaded_ptr == NULL);
|
||||
}
|
||||
|
||||
// Test 6: Relaxed memory ordering
|
||||
{
|
||||
int atomic_var = 0;
|
||||
__atomic_store_n(&atomic_var, 10, __ATOMIC_RELAXED);
|
||||
assert(__atomic_load_n(&atomic_var, __ATOMIC_RELAXED) == 10);
|
||||
}
|
||||
|
||||
printf("All atomic tests passed!\n");
|
||||
return 0;
|
||||
}
|
||||
1
tests/tests2/136_atomic_gcc_style.expect
Normal file
1
tests/tests2/136_atomic_gcc_style.expect
Normal file
@ -0,0 +1 @@
|
||||
All atomic tests passed!
|
||||
Loading…
Reference in New Issue
Block a user