]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/tst-tls-manydynamic.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / elf / tst-tls-manydynamic.c
CommitLineData
01b23a30 1/* Test with many dynamic TLS variables.
04277e02 2 Copyright (C) 2016-2019 Free Software Foundation, Inc.
01b23a30
FW
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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/>. */
18
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). */
24
25#include "tst-tls-manydynamic.h"
26
36fe25fd 27#include <errno.h>
01b23a30
FW
28#include <dlfcn.h>
29#include <pthread.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34static int do_test (void);
36fe25fd
WSM
35#include <support/xthread.h>
36#include <support/test-driver.c>
01b23a30
FW
37
38void *handles[COUNT];
39set_value_func set_value_funcs[COUNT];
40get_value_func get_value_funcs[COUNT];
41
42static void
43init_functions (void)
44{
45 for (int i = 0; i < COUNT; ++i)
46 {
47 /* Open the module. */
48 {
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)
53 {
54 printf ("error: dlopen failed: %s\n", dlerror ());
55 exit (1);
56 }
57 }
58
59 /* Obtain the setter function. */
60 {
61 char fname[100];
62 snprintf (fname, sizeof (fname), "set_value_%02d", i);
63 void *func = dlsym (handles[i], fname);
64 if (func == NULL)
65 {
66 printf ("error: dlsym: %s\n", dlerror ());
67 exit (1);
68 }
69 set_value_funcs[i] = func;
70 }
71
72 /* Obtain the getter function. */
73 {
74 char fname[100];
75 snprintf (fname, sizeof (fname), "get_value_%02d", i);
76 void *func = dlsym (handles[i], fname);
77 if (func == NULL)
78 {
79 printf ("error: dlsym: %s\n", dlerror ());
80 exit (1);
81 }
82 get_value_funcs[i] = func;
83 }
84 }
85}
86
87static pthread_barrier_t barrier;
88
89/* Running thread which forces real TLS initialization. */
90static void *
91blocked_thread_func (void *closure)
92{
93 xpthread_barrier_wait (&barrier);
94
95 /* TLS test runs here in the main thread. */
96
97 xpthread_barrier_wait (&barrier);
98 return NULL;
99}
100
101static int
102do_test (void)
103{
104 {
105 int ret = pthread_barrier_init (&barrier, NULL, 2);
106 if (ret != 0)
107 {
108 errno = ret;
109 printf ("error: pthread_barrier_init: %m\n");
110 exit (1);
111 }
112 }
113
114 pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL);
115 xpthread_barrier_wait (&barrier);
116
117 init_functions ();
118
119 struct value values[COUNT];
120 /* Initialze the TLS variables. */
121 for (int i = 0; i < COUNT; ++i)
122 {
123 for (int j = 0; j < PER_VALUE_COUNT; ++j)
124 values[i].num[j] = rand ();
125 set_value_funcs[i] (&values[i]);
126 }
127
128 /* Read back their values to check that they do not overlap. */
129 for (int i = 0; i < COUNT; ++i)
130 {
131 struct value actual;
132 get_value_funcs[i] (&actual);
133
134 for (int j = 0; j < PER_VALUE_COUNT; ++j)
135 if (actual.num[j] != values[i].num[j])
136 {
137 printf ("error: mismatch at variable %d/%d: %d != %d\n",
138 i, j, actual.num[j], values[i].num[j]);
139 exit (1);
140 }
141 }
142
143 xpthread_barrier_wait (&barrier);
144 xpthread_join (blocked_thread);
145
146 /* Close the modules. */
147 for (int i = 0; i < COUNT; ++i)
148 dlclose (handles[i]);
149
150 return 0;
151}