1
1
#include <stdatomic.h>
2
2
#include <stddef.h>
3
3
#include <threads.h>
4
-
5
- mtx_t mx ;
6
-
7
- int t1 (void * dummy ) {
8
- mtx_lock (& mx );
9
- mtx_unlock (& mx );
4
+
5
+ /// Note that since this is a C test case, mutexes
6
+ /// are not created/valid until `mtx_init` is called.
7
+ mtx_t mx1 ;
8
+ mtx_t mx2 ;
9
+
10
+ int t1 (void * data ) {
11
+ mtx_lock (& mx1 );
12
+ mtx_unlock (& mx1 );
13
+ return 0 ;
14
+ }
15
+
16
+ int t2 (void * data ) {
17
+ mtx_lock (& mx2 );
18
+ mtx_unlock (& mx2 );
19
+ return 0 ;
20
+ }
21
+
22
+ int t3 (void * data ) {
23
+ mtx_t * mxl = (mtx_t * )data ;
24
+ mtx_lock (mxl );
25
+ mtx_unlock (mxl );
10
26
return 0 ;
11
27
}
12
-
28
+
29
+ int t4 (void * data ) {
30
+ mtx_t * mxl = (mtx_t * )data ;
31
+ mtx_lock (mxl );
32
+ mtx_unlock (mxl );
33
+ return 0 ;
34
+ }
35
+
36
+ // case 1 - correctly waiting for a well-behaved thread
13
37
int f1 () {
14
38
thrd_t threads [5 ];
15
-
16
- mtx_init (& mx , mtx_plain );
17
-
18
- for (size_t i = 0 ; i < 5 ; i ++ ) {
39
+
40
+ mtx_init (& mx1 , mtx_plain ); // COMPLIANT
41
+
42
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
19
43
thrd_create (& threads [i ], t1 , NULL );
20
-
21
44
}
22
- for (size_t i = 0 ; i < 5 ; i ++ ) {
45
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
23
46
thrd_join (threads [i ], 0 );
24
47
}
25
-
26
- mtx_destroy (& mx );
48
+
49
+ mtx_destroy (& mx1 );
27
50
return 0 ;
28
51
}
29
52
53
+ // case 2 - incorrectly waiting for a well behaved thread.
30
54
int f2 () {
31
55
thrd_t threads [5 ];
32
-
33
- mtx_init (& mx , mtx_plain );
34
-
35
- for (size_t i = 0 ; i < 5 ; i ++ ) {
36
- thrd_create (& threads [i ], t1 , NULL );
56
+
57
+ mtx_init (& mx2 , mtx_plain ); // NON_COMPLIANT
58
+
59
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
60
+ thrd_create (& threads [i ], t2 , NULL );
61
+ }
62
+
63
+ mtx_destroy (& mx2 );
64
+ return 0 ;
65
+ }
66
+
67
+ // case 3 - correctly waiting for a well-behaved thread, with a local mutex.
68
+ int f3 () {
69
+ thrd_t threads [5 ];
70
+
71
+ mtx_t mxl ;
72
+
73
+ mtx_init (& mxl , mtx_plain ); // COMPLIANT
74
+
75
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
76
+ thrd_create (& threads [i ], t3 , & mxl );
77
+ }
78
+
79
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
80
+ thrd_join (threads [i ], 0 );
37
81
}
38
82
39
- mtx_destroy (& mx );
83
+ mtx_destroy (& mxl );
40
84
return 0 ;
41
- }
85
+ }
86
+
87
+ // case 4 - incorrectly waiting for a well behaved thread, with a local mutex.
88
+ int f4 () {
89
+ thrd_t threads [5 ];
90
+ mtx_t mxl ;
91
+
92
+ mtx_init (& mxl , mtx_plain ); // NON_COMPLIANT
93
+
94
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
95
+ thrd_create (& threads [i ], t3 , & mxl );
96
+ }
97
+
98
+ mtx_destroy (& mxl );
99
+ return 0 ;
100
+ }
101
+
102
+ // case 5 - incorrectly waiting with a stack local variable.
103
+ int f5 () {
104
+ thrd_t threads [5 ];
105
+ mtx_t mxl ;
106
+
107
+ mtx_init (& mxl , mtx_plain ); // NON_COMPLIANT
108
+
109
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
110
+ thrd_create (& threads [i ], t4 , & mxl );
111
+ }
112
+
113
+ return 0 ;
114
+ }
115
+
116
+ // case 6 - correctly waiting with a stack local variable.
117
+ int f6 () {
118
+ thrd_t threads [5 ];
119
+ mtx_t mxl ;
120
+
121
+ mtx_init (& mxl , mtx_plain ); // COMPLIANT
122
+
123
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
124
+ thrd_create (& threads [i ], t4 , & mxl );
125
+ }
126
+
127
+ for (size_t i = 0 ; i < 1 ; i ++ ) {
128
+ thrd_join (threads [i ], 0 );
129
+ }
130
+
131
+ return 0 ;
132
+ }
0 commit comments