1 /* Copyright (C) 2003-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <dlfcn.h>
19 #include <errno.h>
20 #include <pthread.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 
26 #define N 3
27 
28 void (*test1) (void), (*test2) (void);
29 
30 pthread_barrier_t b2, b3;
31 
32 static void *
tf(void * arg)33 tf (void *arg)
34 {
35   int i;
36 
37   for (i = 0; i <= (uintptr_t) arg; ++i)
38     {
39       int r = pthread_barrier_wait (&b3);
40       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
41 	{
42 	  puts ("tf: barrier_wait failed");
43 	  exit (1);
44 	}
45     }
46 
47   test1 ();
48 
49   for (i = 0; i < 3; ++i)
50     {
51       int r = pthread_barrier_wait (&b3);
52       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
53 	{
54 	  puts ("tf: barrier_wait failed");
55 	  exit (1);
56 	}
57     }
58 
59   test2 ();
60 
61   for (i = 0; i < 3 - (uintptr_t) arg; ++i)
62     {
63       int r = pthread_barrier_wait (&b3);
64       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
65 	{
66 	  puts ("tf: barrier_wait failed");
67 	  exit (1);
68 	}
69     }
70 
71   return NULL;
72 }
73 
74 static void *
tf2(void * arg)75 tf2 (void *arg)
76 {
77   int r = pthread_barrier_wait (&b2);
78   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
79     {
80       puts ("tf2: barrier_wait failed");
81       exit (1);
82     }
83 
84   int i;
85   for (i = 0; i < N; ++i)
86     tf (arg);
87   return NULL;
88 }
89 
90 int
do_test(void)91 do_test (void)
92 {
93   pthread_t th[2];
94   const char *modules[N]
95     = { "tst-tls4moda.so", "tst-tls4moda.so", "tst-tls4modb.so" };
96 
97   if (pthread_barrier_init (&b2, NULL, 2) != 0)
98     {
99       puts ("barrier_init failed");
100       return 1;
101     }
102 
103   if (pthread_barrier_init (&b3, NULL, 3) != 0)
104     {
105       puts ("barrier_init failed");
106       return 1;
107     }
108 
109   if (pthread_create (&th[0], NULL, tf2, (void *) (uintptr_t) 1))
110     {
111       puts ("pthread_create failed");
112       return 1;
113     }
114 
115   int r = pthread_barrier_wait (&b2);
116   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
117     {
118       puts ("barrier_wait failed");
119       return 1;
120     }
121 
122   int i;
123   for (i = 0; i < N; ++i)
124     {
125       void *h = dlopen (modules[i], RTLD_LAZY);
126       if (h == NULL)
127 	{
128 	  printf ("dlopen failed %s\n", dlerror ());
129 	  return 1;
130 	}
131 
132       test1 = dlsym (h, "test1");
133       if (test1 == NULL)
134 	{
135 	  printf ("dlsym for test1 failed %s\n", dlerror ());
136 	  return 1;
137 	}
138 
139       test2 = dlsym (h, "test2");
140       if (test2 == NULL)
141 	{
142 	  printf ("dlsym for test2 failed %s\n", dlerror ());
143 	  return 1;
144 	}
145 
146       if (pthread_create (&th[1], NULL, tf, (void *) (uintptr_t) 2))
147 	{
148 	  puts ("pthread_create failed");
149 	  return 1;
150 	}
151 
152       tf ((void *) (uintptr_t) 0);
153 
154       if (pthread_join (th[1], NULL) != 0)
155 	{
156 	  puts ("join failed");
157 	  return 1;
158 	}
159 
160       if (dlclose (h))
161 	{
162 	  puts ("dlclose failed");
163 	  return 1;
164 	}
165 
166       printf ("test %d with %s succeeded\n", i, modules[i]);
167     }
168 
169   if (pthread_join (th[0], NULL) != 0)
170     {
171       puts ("join failed");
172       return 1;
173     }
174 
175   return 0;
176 }
177 
178 #define TEST_FUNCTION do_test ()
179 #include "../test-skeleton.c"
180