11#include <stdatomic.h>
22#include <stddef.h>
33#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 );
1026 return 0 ;
1127}
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
1337int f1 () {
1438 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 ++ ) {
1943 thrd_create (& threads [i ], t1 , NULL );
20-
2144 }
22- for (size_t i = 0 ; i < 5 ; i ++ ) {
45+ for (size_t i = 0 ; i < 1 ; i ++ ) {
2346 thrd_join (threads [i ], 0 );
2447 }
25-
26- mtx_destroy (& mx );
48+
49+ mtx_destroy (& mx1 );
2750 return 0 ;
2851}
2952
53+ // case 2 - incorrectly waiting for a well behaved thread.
3054int f2 () {
3155 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 );
3781 }
3882
39- mtx_destroy (& mx );
83+ mtx_destroy (& mxl );
4084 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