1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com>
4 */
5 /* Basic functionality test for tst_fuzzy_sync.h similar to the atomic tests
6 * (test15.c). One thread writes to the odd indexes of an array while the
7 * other writes to the even. If the threads are not synchronised then they
8 * will probably write to the wrong indexes as they share an index variable
9 * which they should take it in turns to update.
10 */
11
12 #include <stdlib.h>
13 #include "tst_test.h"
14 #include "tst_safe_pthread.h"
15 #include "tst_fuzzy_sync.h"
16
17 /* LOOPS * 2 + 1 must be less than INT_MAX */
18 #define LOOPS 0xFFFFULL
19
20 static volatile char seq[LOOPS * 2 + 1];
21 static struct tst_fzsync_pair pair;
22 static volatile int seq_n;
23 static volatile char last_wins;
24
setup(void)25 static void setup(void)
26 {
27 pair.exec_loops = LOOPS;
28 tst_fzsync_pair_init(&pair);
29 }
30
worker(void * v LTP_ATTRIBUTE_UNUSED)31 static void *worker(void *v LTP_ATTRIBUTE_UNUSED)
32 {
33 unsigned long long i;
34
35 for (i = 0; tst_fzsync_run_b(&pair); i++) {
36 tst_fzsync_start_race_b(&pair);
37 usleep(1);
38 last_wins = 'B';
39 tst_fzsync_end_race_b(&pair);
40 seq[seq_n] = 'B';
41 seq_n = (i + 1) * 2 % (int)LOOPS * 2;
42 }
43
44 if (i != LOOPS) {
45 tst_res(TFAIL,
46 "Worker performed wrong number of iterations: %lld != %lld",
47 i, LOOPS);
48 }
49
50 return NULL;
51 }
52
run(void)53 static void run(void)
54 {
55 unsigned int i, j, fail = 0, lost_race = 0;
56
57 tst_fzsync_pair_reset(&pair, worker);
58 for (i = 0; tst_fzsync_run_a(&pair); i++) {
59 tst_fzsync_start_race_a(&pair);
60 seq[seq_n] = 'A';
61 seq_n = i * 2 + 1;
62 last_wins = 'A';
63 tst_fzsync_end_race_a(&pair);
64 if (last_wins == 'B')
65 lost_race++;
66 }
67
68 tst_res(TINFO, "Checking sequence...");
69 for (i = 0; i < LOOPS; i++) {
70 j = i * 2;
71 if (seq[j] != 'A') {
72 tst_res(TFAIL, "Expected A, but found %c at %d",
73 seq[j], j);
74 fail = 1;
75 }
76 j = i * 2 + 1;
77 if (seq[j] != 'B') {
78 tst_res(TFAIL, "Expected A, but found %c at %d",
79 seq[j], j);
80 fail = 1;
81 }
82 }
83
84 if (!fail)
85 tst_res(TPASS, "Sequence is correct");
86
87 if (lost_race < 100)
88 tst_res(TFAIL, "A only lost the race %d times", lost_race);
89 else
90 tst_res(TPASS, "A lost the race %d times", lost_race);
91 }
92
cleanup(void)93 static void cleanup(void)
94 {
95 tst_fzsync_pair_cleanup(&pair);
96 }
97
98 static struct tst_test test = {
99 .setup = setup,
100 .cleanup = cleanup,
101 .test_all = run,
102 };
103