1 /* Test multi-threading using LD_AUDIT.
2 
3    Copyright (C) 2018-2022 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5 
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10 
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <https://www.gnu.org/licenses/>.  */
19 
20 /* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a
21    library with a huge number of functions in order to validate lazy symbol
22    binding with an audit library.  We use one thread per CPU to test that
23    concurrent lazy resolution does not have any defects which would cause
24    the process to fail.  We use an LD_AUDIT library to force the testing of
25    the relocation resolution caching code in the dynamic loader i.e.
26    _dl_runtime_profile and _dl_profile_fixup.  */
27 
28 #include <support/support.h>
29 #include <support/xthread.h>
30 #include <strings.h>
31 #include <stdlib.h>
32 #include <sys/sysinfo.h>
33 
34 /* Declare the functions we are going to call.  */
35 #define externnum
36 #include "tst-audit-threads.h"
37 #undef externnum
38 
39 int num_threads;
40 pthread_barrier_t barrier;
41 
42 void
sync_all(int num)43 sync_all (int num)
44 {
45   pthread_barrier_wait (&barrier);
46 }
47 
48 void
call_all_ret_nums(void)49 call_all_ret_nums (void)
50 {
51   /* Call each function one at a time from all threads.  */
52 #define callnum
53 #include "tst-audit-threads.h"
54 #undef callnum
55 }
56 
57 void *
thread_main(void * unused)58 thread_main (void *unused)
59 {
60   call_all_ret_nums ();
61   return NULL;
62 }
63 
64 #define STR2(X) #X
65 #define STR(X) STR2(X)
66 
67 static int
do_test(void)68 do_test (void)
69 {
70   int i;
71   pthread_t *threads;
72 
73   num_threads = get_nprocs ();
74   if (num_threads <= 1)
75     num_threads = 2;
76 
77   /* Used to synchronize all the threads after calling each retNumN.  */
78   xpthread_barrier_init (&barrier, NULL, num_threads);
79 
80   threads = (pthread_t *) xcalloc (num_threads, sizeof (pthread_t));
81   for (i = 0; i < num_threads; i++)
82     threads[i] = xpthread_create(NULL, thread_main, NULL);
83 
84   for (i = 0; i < num_threads; i++)
85     xpthread_join(threads[i]);
86 
87   free (threads);
88 
89   return 0;
90 }
91 
92 /* This test usually takes less than 3s to run.  However, there are cases that
93    take up to 30s.  */
94 #define TIMEOUT 60
95 #include <support/test-driver.c>
96