litmus: seq-lock: add MODEL_ASSERT() for the important behavior
[c11tester.git] / test / litmus / seq-lock.cc
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <threads.h>
4 #include <atomic>
5
6 #include "model-assert.h"
7
8 /*
9  * This 'seqlock' example should never trigger the MODEL_ASSERT() for
10  * release/acquire; it may trigger the MODEL_ASSERT() for release/consume
11  */
12
13 std::atomic_int x;
14 std::atomic_int y;
15 std::atomic_int z;
16
17 static int N = 1;
18
19 static void a(void *obj)
20 {
21         for (int i = 0; i < N; i++) {
22                 x.store(2 * i + 1, std::memory_order_release);
23                 y.store(i + 1, std::memory_order_release);
24                 z.store(i + 1, std::memory_order_release);
25                 x.store(2 * i + 2, std::memory_order_release);
26         }
27 }
28
29 static void b(void *obj)
30 {
31         int x1, y1, z1, x2;
32         x1 = x.load(std::memory_order_acquire);
33         y1 = y.load(std::memory_order_acquire);
34         z1 = z.load(std::memory_order_acquire);
35         x2 = x.load(std::memory_order_acquire);
36         printf("x: %d\n", x1);
37         printf("y: %d\n", y1);
38         printf("z: %d\n", z1);
39         printf("x: %d\n", x2);
40
41         /* If x1 and x2 are the same, even value, then y1 must equal z1 */
42         MODEL_ASSERT(x1 != x2 || x1 & 0x1 || y1 == z1);
43 }
44
45 int user_main(int argc, char **argv)
46 {
47         thrd_t t1, t2;
48
49         if (argc > 1)
50                 N = atoi(argv[1]);
51
52         printf("N: %d\n", N);
53
54         atomic_init(&x, 0);
55         atomic_init(&y, 0);
56         atomic_init(&z, 0);
57
58         printf("Main thread: creating 2 threads\n");
59         thrd_create(&t1, (thrd_start_t)&a, NULL);
60         thrd_create(&t2, (thrd_start_t)&b, NULL);
61
62         thrd_join(t1);
63         thrd_join(t2);
64         printf("Main thread is finished\n");
65
66         return 0;
67 }