| @@ -0,0 +1,75 @@ |
| | 1 | #include <stddef.h> |
| | 2 | #include <stdint.h> |
| | 3 | #include <stdlib.h> |
| | 4 | #include <stdio.h> |
| | 5 | #include <pthread.h> |
| | 6 | #include <stdatomic.h> |
| | 7 | |
| | 8 | #define NR_THREADS 16 |
| | 9 | #define NR_STEPS ((uint32_t)UINT16_MAX * 4) |
| | 10 | |
| | 11 | #define BUG_ON(COND) \ |
| | 12 | do { \ |
| | 13 | if (!!(COND)) \ |
| | 14 | abort(); \ |
| | 15 | } while (0) |
| | 16 | |
| | 17 | static |
| | 18 | void *adder_simple(void *arg) |
| | 19 | { |
| | 20 | size_t step; |
| | 21 | atomic_size_t *counter = arg; |
| | 22 | |
| | 23 | for (step = 0; step < NR_STEPS; ++step) |
| | 24 | atomic_fetch_add_explicit(counter, 1, memory_order_relaxed); |
| | 25 | |
| | 26 | return NULL; |
| | 27 | } |
| | 28 | |
| | 29 | static |
| | 30 | void *adder_cmpxchg(void *arg) |
| | 31 | { |
| | 32 | size_t step; |
| | 33 | atomic_size_t *counter = arg; |
| | 34 | |
| | 35 | for (step = 0; step < NR_STEPS; ++step) { |
| | 36 | size_t xchg; |
| | 37 | size_t cmp = atomic_load_explicit(counter, memory_order_relaxed); |
| | 38 | |
| | 39 | do { |
| | 40 | xchg = (cmp + 1); |
| | 41 | } while (!atomic_compare_exchange_strong_explicit(counter, |
| | 42 | &cmp, xchg, memory_order_relaxed, memory_order_relaxed)); |
| | 43 | } |
| | 44 | |
| | 45 | return NULL; |
| | 46 | } |
| | 47 | |
| | 48 | static |
| | 49 | void atomic_counter_test(void *(*adder)(void *arg)) |
| | 50 | { |
| | 51 | size_t index; |
| | 52 | atomic_size_t counter; |
| | 53 | pthread_t thread[NR_THREADS]; |
| | 54 | |
| | 55 | atomic_init(&counter, 0); |
| | 56 | |
| | 57 | for (index = 0; index < NR_THREADS; ++index) |
| | 58 | BUG_ON(pthread_create(&thread[index], NULL, adder, (void *)&counter)); |
| | 59 | |
| | 60 | for (index = 0; index < NR_THREADS; ++index) |
| | 61 | BUG_ON(pthread_join(thread[index], NULL)); |
| | 62 | |
| | 63 | if (atomic_load(&counter) == (NR_THREADS * NR_STEPS)) |
| | 64 | printf("SUCCESS\n"); |
| | 65 | else |
| | 66 | printf("FAILURE\n"); |
| | 67 | } |
| | 68 | |
| | 69 | int main(void) |
| | 70 | { |
| | 71 | atomic_counter_test(adder_simple); |
| | 72 | atomic_counter_test(adder_cmpxchg); |
| | 73 | |
| | 74 | return 0; |
| | 75 | } |