kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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(); }