• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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