stdatomic_runtime.c (2900B)
1 #include <stdatomic.h> 2 #include <stdbool.h> 3 #include <stddef.h> 4 5 struct Blob { 6 int a; 7 int b; 8 int c; 9 }; 10 11 void __atomic_load(int size, void* src, void* dest, int model); 12 void __atomic_store(int size, void* dest, void* src, int model); 13 void __atomic_exchange(int size, void* ptr, void* val, void* old, int model); 14 int __atomic_compare_exchange(int size, void* ptr, void* expected, 15 void* desired, int success, int failure); 16 17 static int same_blob(const struct Blob* a, const struct Blob* b) { 18 return a->a == b->a && a->b == b->b && a->c == b->c; 19 } 20 21 static int header_ops(void) { 22 atomic_int x = ATOMIC_VAR_INIT(0); 23 atomic_init(&x, 1); 24 atomic_store_explicit(&x, 10, memory_order_relaxed); 25 if (atomic_load(&x) != 10) return 0; 26 if (atomic_exchange(&x, 20) != 10) return 0; 27 28 int expected = 20; 29 if (!atomic_compare_exchange_strong(&x, &expected, 30)) return 0; 30 if (expected != 20 || atomic_load(&x) != 30) return 0; 31 if (atomic_compare_exchange_strong(&x, &expected, 40)) return 0; 32 if (expected != 30 || atomic_load(&x) != 30) return 0; 33 34 if (atomic_fetch_add(&x, 5) != 30) return 0; 35 if (atomic_fetch_sub(&x, 3) != 35) return 0; 36 if (atomic_fetch_or(&x, 1) != 32) return 0; 37 if (atomic_fetch_xor(&x, 3) != 33) return 0; 38 if (atomic_fetch_and(&x, 15) != 34) return 0; 39 40 atomic_flag f = ATOMIC_FLAG_INIT; 41 if (atomic_flag_test_and_set(&f)) return 0; 42 if (!atomic_flag_test_and_set_explicit(&f, memory_order_acquire)) return 0; 43 atomic_flag_clear_explicit(&f, memory_order_release); 44 if (atomic_flag_test_and_set(&f)) return 0; 45 return 21; 46 } 47 48 static int runtime_fallback_ops(void) { 49 struct Blob obj; 50 struct Blob out; 51 struct Blob val; 52 struct Blob old; 53 struct Blob expected; 54 struct Blob desired; 55 56 obj.a = 1; 57 obj.b = 2; 58 obj.c = 3; 59 __atomic_load((int)sizeof(obj), &obj, &out, __ATOMIC_SEQ_CST); 60 if (!same_blob(&out, &obj)) return 1; 61 62 val.a = 4; 63 val.b = 5; 64 val.c = 6; 65 __atomic_store((int)sizeof(obj), &obj, &val, __ATOMIC_RELEASE); 66 if (!same_blob(&obj, &val)) return 2; 67 68 desired.a = 7; 69 desired.b = 8; 70 desired.c = 9; 71 __atomic_exchange((int)sizeof(obj), &obj, &desired, &old, __ATOMIC_ACQ_REL); 72 if (!same_blob(&old, &val) || !same_blob(&obj, &desired)) return 3; 73 74 expected = desired; 75 val.a = 10; 76 val.b = 11; 77 val.c = 12; 78 if (!__atomic_compare_exchange((int)sizeof(obj), &obj, &expected, &val, 79 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 80 return 4; 81 } 82 if (!same_blob(&obj, &val)) return 5; 83 84 expected.a = 0; 85 expected.b = 0; 86 expected.c = 0; 87 if (__atomic_compare_exchange((int)sizeof(obj), &obj, &expected, &desired, 88 __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)) { 89 return 6; 90 } 91 if (!same_blob(&expected, &val) || !same_blob(&obj, &val)) return 7; 92 return 21; 93 } 94 95 int test_main(void) { return header_ops() + runtime_fallback_ops(); }