1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, no-threads
11 #include "test_macros.h"
14 #include <condition_variable>
21 #include "assert_macros.h"
22 #include "concat_macros.h"
23 #include "../src/cxa_exception.h"
25 static int threads_remaining
;
26 static std::mutex threads_remaining_lock
;
27 static std::condition_variable threads_remaining_cv
;
29 static void thread_code(void*& globals
) {
30 std::thread::id thread_id
= std::this_thread::get_id();
33 globals
= __cxxabiv1::__cxa_get_globals();
34 TEST_REQUIRE(globals
!= nullptr,
35 TEST_WRITE_CONCATENATED("Got null result from __cxa_get_globals on thread ", thread_id
));
37 void* fast_globals
= __cxxabiv1::__cxa_get_globals_fast();
38 TEST_REQUIRE(globals
== fast_globals
,
39 TEST_WRITE_CONCATENATED("__cxa_get_globals returned ", globals
, " but __cxa_get_globals_fast returned ",
40 fast_globals
, " on thread ", thread_id
));
42 // Ensure that all threads are running at the same time, since we check for
43 // duplicate globals below. We do this manually instead of using std::barrier
44 // or std::latch to avoid requiring C++20.
45 std::unique_lock
<std::mutex
> lock(threads_remaining_lock
);
47 if (threads_remaining
== 0) {
49 threads_remaining_cv
.notify_all();
51 threads_remaining_cv
.wait(lock
, []() { return threads_remaining
== 0; });
55 int main(int, char**) {
56 int num_threads
= std::thread::hardware_concurrency();
58 num_threads
= 4; // arbitrary fallback value
60 std::vector
<void*> thread_globals(num_threads
);
61 std::vector
<std::thread
> threads
;
62 threads_remaining
= num_threads
;
64 // Make the threads, let them run, and wait for them to finish
65 for (int i
= 0; i
< num_threads
; ++i
)
66 threads
.emplace_back(thread_code
, std::ref(thread_globals
[i
]));
67 for (std::thread
& thread
: threads
)
70 std::sort(thread_globals
.begin(), thread_globals
.end());
71 for (int i
= 1; i
< num_threads
; ++i
) {
72 TEST_REQUIRE(thread_globals
[i
- 1] != thread_globals
[i
],
73 TEST_WRITE_CONCATENATED("Duplicate thread globals ", thread_globals
[i
]));