@@ -185,8 +185,113 @@ static void test_task_local_data_basic(void)
185
185
test_task_local_data__destroy (skel );
186
186
}
187
187
188
+ #define TEST_RACE_THREAD_NUM (TLD_MAX_DATA_CNT - 3)
189
+
190
+ void * test_task_local_data_race_thread (void * arg )
191
+ {
192
+ int err = 0 , id = (intptr_t )arg ;
193
+ char key_name [32 ];
194
+ tld_key_t key ;
195
+
196
+ key = tld_create_key ("value_not_exist" , TLD_PAGE_SIZE + 1 );
197
+ if (tld_key_err_or_zero (key ) != - E2BIG ) {
198
+ err = 1 ;
199
+ goto out ;
200
+ }
201
+
202
+ /* Only one thread will succeed in creating value1 */
203
+ key = tld_create_key ("value1" , sizeof (int ));
204
+ if (!tld_key_is_err (key ))
205
+ tld_keys [1 ] = key ;
206
+
207
+ /* Only one thread will succeed in creating value2 */
208
+ key = tld_create_key ("value2" , sizeof (struct test_tld_struct ));
209
+ if (!tld_key_is_err (key ))
210
+ tld_keys [2 ] = key ;
211
+
212
+ snprintf (key_name , 32 , "thread_%d" , id );
213
+ tld_keys [id ] = tld_create_key (key_name , sizeof (int ));
214
+ if (tld_key_is_err (tld_keys [id ]))
215
+ err = 2 ;
216
+ out :
217
+ return (void * )(intptr_t )err ;
218
+ }
219
+
220
+ static void test_task_local_data_race (void )
221
+ {
222
+ LIBBPF_OPTS (bpf_test_run_opts , opts );
223
+ pthread_t thread [TEST_RACE_THREAD_NUM ];
224
+ struct test_task_local_data * skel ;
225
+ int fd , i , j , err , * data ;
226
+ void * ret = NULL ;
227
+
228
+ skel = test_task_local_data__open_and_load ();
229
+ if (!ASSERT_OK_PTR (skel , "skel_open_and_load" ))
230
+ return ;
231
+
232
+ tld_keys = calloc (TLD_MAX_DATA_CNT , sizeof (tld_key_t ));
233
+ if (!ASSERT_OK_PTR (tld_keys , "calloc tld_keys" ))
234
+ goto out ;
235
+
236
+ fd = bpf_map__fd (skel -> maps .tld_data_map );
237
+
238
+ ASSERT_FALSE (tld_key_is_err (value0_key ), "TLD_DEFINE_KEY" );
239
+ tld_keys [0 ] = value0_key ;
240
+
241
+ for (j = 0 ; j < 100 ; j ++ ) {
242
+ reset_tld ();
243
+
244
+ for (i = 0 ; i < TEST_RACE_THREAD_NUM ; i ++ ) {
245
+ /*
246
+ * Try to make tld_create_key() race with each other. Call
247
+ * tld_create_key(), both valid and invalid, from different threads.
248
+ */
249
+ err = pthread_create (& thread [i ], NULL , test_task_local_data_race_thread ,
250
+ (void * )(intptr_t )(i + 3 ));
251
+ if (CHECK_FAIL (err ))
252
+ break ;
253
+ }
254
+
255
+ /* Wait for all tld_create_key() to return */
256
+ for (i = 0 ; i < TEST_RACE_THREAD_NUM ; i ++ ) {
257
+ pthread_join (thread [i ], & ret );
258
+ if (CHECK_FAIL (ret ))
259
+ break ;
260
+ }
261
+
262
+ /* Write a unique number to each TLD */
263
+ for (i = 0 ; i < TLD_MAX_DATA_CNT ; i ++ ) {
264
+ data = tld_get_data (fd , tld_keys [i ]);
265
+ if (CHECK_FAIL (!data ))
266
+ break ;
267
+ * data = i ;
268
+ }
269
+
270
+ /* Read TLDs and check the value to see if any address collides with another */
271
+ for (i = 0 ; i < TLD_MAX_DATA_CNT ; i ++ ) {
272
+ data = tld_get_data (fd , tld_keys [i ]);
273
+ if (CHECK_FAIL (* data != i ))
274
+ break ;
275
+ }
276
+
277
+ /* Run task_main to make sure no invalid TLDs are added */
278
+ err = bpf_prog_test_run_opts (bpf_program__fd (skel -> progs .task_main ), & opts );
279
+ ASSERT_OK (err , "run task_main" );
280
+ ASSERT_OK (opts .retval , "task_main retval" );
281
+ }
282
+ out :
283
+ if (tld_keys ) {
284
+ free (tld_keys );
285
+ tld_keys = NULL ;
286
+ }
287
+ tld_free ();
288
+ test_task_local_data__destroy (skel );
289
+ }
290
+
188
291
void test_task_local_data (void )
189
292
{
190
293
if (test__start_subtest ("task_local_data_basic" ))
191
294
test_task_local_data_basic ();
295
+ if (test__start_subtest ("task_local_data_race" ))
296
+ test_task_local_data_race ();
192
297
}
0 commit comments