@@ -185,8 +185,113 @@ static void test_task_local_data_basic(void)
185185 test_task_local_data__destroy (skel );
186186}
187187
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+
188291void test_task_local_data (void )
189292{
190293 if (test__start_subtest ("task_local_data_basic" ))
191294 test_task_local_data_basic ();
295+ if (test__start_subtest ("task_local_data_race" ))
296+ test_task_local_data_race ();
192297}
0 commit comments