1 /* Test basic thread_local support.
2 Copyright (C) 2015-2018 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/>. */
44 to_string (const counter
&c
)
47 snprintf (buf
, sizeof (buf
), "%d/%d",
48 c
.constructed
, c
.destructed
);
52 template <counter
*Counter
>
55 counting () __attribute__ ((noinline
, noclone
));
56 ~counting () __attribute__ ((noinline
, noclone
));
57 void operation () __attribute__ ((noinline
, noclone
));
60 template<counter
*Counter
>
61 __attribute__ ((noinline
, noclone
))
62 counting
<Counter
>::counting ()
64 ++Counter
->constructed
;
67 template<counter
*Counter
>
68 __attribute__ ((noinline
, noclone
))
69 counting
<Counter
>::~counting ()
71 ++Counter
->destructed
;
74 template<counter
*Counter
>
75 void __attribute__ ((noinline
, noclone
))
76 counting
<Counter
>::operation ()
78 // Optimization barrier.
82 static counter counter_static
;
83 static counter counter_anonymous_namespace
;
84 static counter counter_extern
;
85 static counter counter_function_local
;
86 static bool errors (false);
91 return to_string (counter_static
)
92 + ' ' + to_string (counter_anonymous_namespace
)
93 + ' ' + to_string (counter_extern
)
94 + ' ' + to_string (counter_function_local
);
98 check_counters (const char *name
, const char *expected
)
100 std::string actual
{all_counters ()};
101 if (actual
!= expected
)
103 printf ("error: %s: (%s) != (%s)\n",
104 name
, actual
.c_str (), expected
);
112 counter_static
.reset ();
113 counter_anonymous_namespace
.reset ();
114 counter_extern
.reset ();
115 counter_function_local
.reset ();
118 static thread_local counting
<&counter_static
> counting_static
;
120 thread_local counting
<&counter_anonymous_namespace
>
121 counting_anonymous_namespace
;
123 extern thread_local counting
<&counter_extern
> counting_extern
;
124 thread_local counting
<&counter_extern
> counting_extern
;
127 thread_without_access (void *)
133 thread_with_access (void *)
135 thread_local counting
<&counter_function_local
> counting_function_local
;
136 counting_function_local
.operation ();
137 check_counters ("early in thread_with_access", "0/0 0/0 0/0 1/0");
138 counting_static
.operation ();
139 counting_anonymous_namespace
.operation ();
140 counting_extern
.operation ();
141 check_counters ("in thread_with_access", "1/0 1/0 1/0 1/0");
148 std::function
<void (void *(void *))> do_pthread
=
149 [](void *(func
) (void *))
152 int ret
= pthread_create (&thr
, nullptr, func
, nullptr);
156 printf ("error: pthread_create: %m\n");
160 ret
= pthread_join (thr
, nullptr);
164 printf ("error: pthread_join: %m\n");
169 std::function
<void (void *(void *))> do_std_thread
=
170 [](void *(func
) (void *))
172 std::thread thr
{[func
] {func (nullptr);}};
176 std::array
<std::pair
<const char *, std::function
<void (void *(void *))>>, 2>
179 {"pthread_create", do_pthread
},
180 {"std::thread", do_std_thread
},
183 for (auto do_thread
: do_thread_X
)
185 printf ("info: testing %s\n", do_thread
.first
);
186 check_counters ("initial", "0/0 0/0 0/0 0/0");
187 do_thread
.second (thread_without_access
);
188 check_counters ("after thread_without_access", "0/0 0/0 0/0 0/0");
190 do_thread
.second (thread_with_access
);
191 check_counters ("after thread_with_access", "1/1 1/1 1/1 1/1");
198 #define TEST_FUNCTION do_test ()
199 #include "../test-skeleton.c"