@@ -53,6 +53,19 @@ static unsigned long nerrors[2] =
53
53
0
54
54
};
55
55
56
+ /****************************************************************************
57
+ * Private Types
58
+ ****************************************************************************/
59
+
60
+ typedef struct
61
+ {
62
+ pthread_mutex_t * mutex_ptr ;
63
+ volatile int * mutex_value ;
64
+ unsigned long * nloops ;
65
+ unsigned long * nerrors ;
66
+ int thread_id ;
67
+ } mutex_thread_args_t ;
68
+
56
69
/****************************************************************************
57
70
* Private Functions
58
71
****************************************************************************/
@@ -103,11 +116,172 @@ static void *thread_func(FAR void *parameter)
103
116
return NULL ; /* Non-reachable -- needed for some compilers */
104
117
}
105
118
119
+ static void * moved_mutex_thread_func (FAR void * parameter )
120
+ {
121
+ FAR mutex_thread_args_t * args = (FAR mutex_thread_args_t * )parameter ;
122
+
123
+ int id = args -> thread_id ;
124
+ int ndx = id - 1 ;
125
+ int i ;
126
+ unsigned long local_loops = 0 ;
127
+
128
+ for (local_loops = 0 ; local_loops < NLOOPS ; local_loops ++ )
129
+ {
130
+ int status = pthread_mutex_lock (args -> mutex_ptr );
131
+ if (status != 0 )
132
+ {
133
+ printf ("ERROR moved mutex thread %d: pthread_mutex_lock failed, "
134
+ "status=%d\n" , id , status );
135
+ ASSERT (false);
136
+ }
137
+
138
+ if (* (args -> mutex_value ) == 1 )
139
+ {
140
+ printf ("ERROR moved mutex thread=%d: "
141
+ "moved_mutex_value should be zero, "
142
+ "instead moved_mutex_value=%d\n" ,
143
+ id , * (args -> mutex_value ));
144
+ ASSERT (false);
145
+ args -> nerrors [ndx ]++ ;
146
+ }
147
+
148
+ * (args -> mutex_value ) = 1 ;
149
+ for (i = 0 ; i < 10 ; i ++ )
150
+ {
151
+ pthread_yield ();
152
+ }
153
+
154
+ * (args -> mutex_value ) = 0 ;
155
+
156
+ status = pthread_mutex_unlock (args -> mutex_ptr );
157
+ if (status != 0 )
158
+ {
159
+ printf ("ERROR moved mutex thread %d: pthread_mutex_unlock failed, "
160
+ "status=%d\n" , id , status );
161
+ ASSERT (false);
162
+ }
163
+ }
164
+
165
+ args -> nloops [ndx ] = local_loops ;
166
+ pthread_exit (NULL );
167
+ return NULL ;
168
+ }
169
+
106
170
/****************************************************************************
107
- * Public Functions
171
+ * Name: mutex_move_test
172
+ *
173
+ * Description:
174
+ * Test the mutex move functionality. This test creates a mutex, moves
175
+ * it to a new location, and then starts two threads that use the moved
176
+ * mutex.
177
+ * POSIX specification does not define the behavior of a mutex that is
178
+ * moved. This test is intended to verify that the mutex can be moved,
179
+ * it's useful for some cases, see the discussion in
180
+ * https://github.com/rust-lang/rust/pull/138400
181
+ *
108
182
****************************************************************************/
109
183
110
- void mutex_test (void )
184
+ static void mutex_move_test (void )
185
+ {
186
+ pthread_t thread1 ;
187
+ pthread_t thread2 ;
188
+ #ifdef SDCC
189
+ pthread_addr_t result1 ;
190
+ pthread_addr_t result2 ;
191
+ pthread_attr_t attr ;
192
+ #endif
193
+ int status ;
194
+ pthread_mutex_t initial_mutex ;
195
+ pthread_mutex_t moved_mutex ;
196
+ volatile int moved_mutex_value = 0 ;
197
+ unsigned long moved_nloops [2 ] =
198
+ {
199
+ 0 ,
200
+ 0
201
+ };
202
+
203
+ unsigned long moved_nerrors [2 ] =
204
+ {
205
+ 0 ,
206
+ 0
207
+ };
208
+
209
+ printf ("\nTesting moved mutex\n" );
210
+
211
+ /* Allocate and initialize first mutex */
212
+
213
+ pthread_mutex_init (& initial_mutex , NULL );
214
+
215
+ /* Copy the mutex to new location */
216
+
217
+ memcpy (& moved_mutex , & initial_mutex , sizeof (pthread_mutex_t ));
218
+
219
+ /* Destroy the original mutex */
220
+
221
+ pthread_mutex_destroy (& initial_mutex );
222
+
223
+ mutex_thread_args_t thread1_args ;
224
+ mutex_thread_args_t thread2_args ;
225
+
226
+ thread1_args .mutex_ptr = & moved_mutex ;
227
+ thread1_args .mutex_value = & moved_mutex_value ;
228
+ thread1_args .nloops = moved_nloops ;
229
+ thread1_args .nerrors = moved_nerrors ;
230
+ thread1_args .thread_id = 1 ;
231
+
232
+ thread2_args .mutex_ptr = & moved_mutex ;
233
+ thread2_args .mutex_value = & moved_mutex_value ;
234
+ thread2_args .nloops = moved_nloops ;
235
+ thread2_args .nerrors = moved_nerrors ;
236
+ thread2_args .thread_id = 2 ;
237
+
238
+ /* Start two threads using the moved mutex */
239
+
240
+ printf ("Starting moved mutex thread 1\n" );
241
+ #ifdef SDCC
242
+ pthread_attr_init (& attr );
243
+ status = pthread_create (& thread1 , & attr , moved_mutex_thread_func ,
244
+ & thread1_args );
245
+ #else
246
+ status = pthread_create (& thread1 , NULL , moved_mutex_thread_func ,
247
+ & thread1_args );
248
+ #endif
249
+ if (status != 0 )
250
+ {
251
+ printf ("ERROR in moved mutex thread#1 creation\n" );
252
+ ASSERT (false);
253
+ }
254
+
255
+ printf ("Starting moved mutex thread 2\n" );
256
+ #ifdef SDCC
257
+ status = pthread_create (& thread2 , & attr , moved_mutex_thread_func ,
258
+ & thread2_args );
259
+ #else
260
+ status = pthread_create (& thread2 , NULL , moved_mutex_thread_func ,
261
+ & thread2_args );
262
+ #endif
263
+ if (status != 0 )
264
+ {
265
+ printf ("ERROR in moved mutex thread#2 creation\n" );
266
+ ASSERT (false);
267
+ }
268
+
269
+ #ifdef SDCC
270
+ pthread_join (thread1 , & result1 );
271
+ pthread_join (thread2 , & result2 );
272
+ #else
273
+ pthread_join (thread1 , NULL );
274
+ pthread_join (thread2 , NULL );
275
+ #endif
276
+
277
+ pthread_mutex_destroy (& moved_mutex );
278
+
279
+ printf ("\t\tThread1\tThread2\n" );
280
+ printf ("\tMoved Loops\t%lu\t%lu\n" , moved_nloops [0 ], moved_nloops [1 ]);
281
+ printf ("\tMoved Errors\t%lu\t%lu\n" , moved_nerrors [0 ], moved_nerrors [1 ]);
282
+ }
283
+
284
+ void mutex_simple_test (void )
111
285
{
112
286
pthread_t thread1 ;
113
287
pthread_t thread2 ;
@@ -164,3 +338,13 @@ void mutex_test(void)
164
338
printf ("\tLoops\t%lu\t%lu\n" , nloops [0 ], nloops [1 ]);
165
339
printf ("\tErrors\t%lu\t%lu\n" , nerrors [0 ], nerrors [1 ]);
166
340
}
341
+
342
+ /****************************************************************************
343
+ * Public Functions
344
+ ****************************************************************************/
345
+
346
+ void mutex_test (void )
347
+ {
348
+ mutex_simple_test ();
349
+ mutex_move_test ();
350
+ }
0 commit comments