arm: Implement memchr ifunc selection in C
[glibc.git] / elf / tst-tls-manydynamic.c
blobb072d0be68354aaf5bc7dacf0a3a6563a4846be6
1 /* Test with many dynamic TLS variables.
2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 /* This test intends to exercise dynamic TLS variable allocation. It
20 achieves this by combining dlopen (to avoid static TLS allocation
21 after static TLS resizing), many DSOs with a large variable (to
22 exceed the static TLS reserve), and an already-running thread (to
23 force full dynamic TLS initialization). */
25 #include "tst-tls-manydynamic.h"
27 #include <errno.h>
28 #include <dlfcn.h>
29 #include <pthread.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
34 static int do_test (void);
35 #include <support/xthread.h>
36 #include <support/test-driver.c>
38 void *handles[COUNT];
39 set_value_func set_value_funcs[COUNT];
40 get_value_func get_value_funcs[COUNT];
42 static void
43 init_functions (void)
45 for (int i = 0; i < COUNT; ++i)
47 /* Open the module. */
49 char soname[100];
50 snprintf (soname, sizeof (soname), "tst-tls-manydynamic%02dmod.so", i);
51 handles[i] = dlopen (soname, RTLD_LAZY);
52 if (handles[i] == NULL)
54 printf ("error: dlopen failed: %s\n", dlerror ());
55 exit (1);
59 /* Obtain the setter function. */
61 char fname[100];
62 snprintf (fname, sizeof (fname), "set_value_%02d", i);
63 void *func = dlsym (handles[i], fname);
64 if (func == NULL)
66 printf ("error: dlsym: %s\n", dlerror ());
67 exit (1);
69 set_value_funcs[i] = func;
72 /* Obtain the getter function. */
74 char fname[100];
75 snprintf (fname, sizeof (fname), "get_value_%02d", i);
76 void *func = dlsym (handles[i], fname);
77 if (func == NULL)
79 printf ("error: dlsym: %s\n", dlerror ());
80 exit (1);
82 get_value_funcs[i] = func;
87 static pthread_barrier_t barrier;
89 /* Running thread which forces real TLS initialization. */
90 static void *
91 blocked_thread_func (void *closure)
93 xpthread_barrier_wait (&barrier);
95 /* TLS test runs here in the main thread. */
97 xpthread_barrier_wait (&barrier);
98 return NULL;
101 static int
102 do_test (void)
105 int ret = pthread_barrier_init (&barrier, NULL, 2);
106 if (ret != 0)
108 errno = ret;
109 printf ("error: pthread_barrier_init: %m\n");
110 exit (1);
114 pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL);
115 xpthread_barrier_wait (&barrier);
117 init_functions ();
119 struct value values[COUNT];
120 /* Initialze the TLS variables. */
121 for (int i = 0; i < COUNT; ++i)
123 for (int j = 0; j < PER_VALUE_COUNT; ++j)
124 values[i].num[j] = rand ();
125 set_value_funcs[i] (&values[i]);
128 /* Read back their values to check that they do not overlap. */
129 for (int i = 0; i < COUNT; ++i)
131 struct value actual;
132 get_value_funcs[i] (&actual);
134 for (int j = 0; j < PER_VALUE_COUNT; ++j)
135 if (actual.num[j] != values[i].num[j])
137 printf ("error: mismatch at variable %d/%d: %d != %d\n",
138 i, j, actual.num[j], values[i].num[j]);
139 exit (1);
143 xpthread_barrier_wait (&barrier);
144 xpthread_join (blocked_thread);
146 /* Close the modules. */
147 for (int i = 0; i < COUNT; ++i)
148 dlclose (handles[i]);
150 return 0;