Skip to content

Commit 42d5567

Browse files
smeenaildionne
andcommitted
[libc++abi] Overhaul test_exception_storage.pass.cpp
I'm making a change in this area (https://reviews.llvm.org/D138461), so update the test: * Add proper synchronization instead of a sleep. * Avoid some unnecessary size_t casts. * Spawn the number of hardware threads instead of 10. * Check that `__cxa_get_globals` and `__cxa_get_globals_fast` return the same values. * Split the test in with-threads and without-threads tests to simplify the code. Differential Revision: https://reviews.llvm.org/D138460 Co-authored-by: Louis Dionne <[email protected]>
1 parent ee2a7bc commit 42d5567

File tree

2 files changed

+87
-62
lines changed

2 files changed

+87
-62
lines changed

libcxxabi/test/test_exception_storage.pass.cpp

Lines changed: 10 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -6,71 +6,19 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include <algorithm>
10-
#include <cstdio>
11-
#include <cstdlib>
12-
#include <__threading_support>
13-
#include <unistd.h>
9+
// UNSUPPORTED: c++03
1410

11+
#include "assert_macros.h"
12+
#include "concat_macros.h"
1513
#include "../src/cxa_exception.h"
1614

17-
#include "test_macros.h"
15+
int main(int, char**) {
16+
void* globals = __cxxabiv1::__cxa_get_globals();
17+
TEST_REQUIRE(globals != nullptr, TEST_WRITE_CONCATENATED("Got null result from __cxa_get_globals"));
1818

19-
typedef __cxxabiv1::__cxa_eh_globals globals_t;
19+
void* fast_globals = __cxxabiv1::__cxa_get_globals_fast();
20+
TEST_REQUIRE(globals == fast_globals, TEST_WRITE_CONCATENATED("__cxa_get_globals returned ", globals,
21+
" but __cxa_get_globals_fast returned ", fast_globals));
2022

21-
void* thread_code(void* parm) {
22-
size_t* result = (size_t*)parm;
23-
globals_t *glob1, *glob2;
24-
25-
glob1 = __cxxabiv1::__cxa_get_globals();
26-
if (NULL == glob1)
27-
std::printf("Got null result from __cxa_get_globals\n");
28-
29-
glob2 = __cxxabiv1::__cxa_get_globals_fast();
30-
if (glob1 != glob2)
31-
std::printf("Got different globals!\n");
32-
33-
*result = (size_t)glob1;
34-
#ifndef TEST_HAS_NO_THREADS
35-
sleep(1);
36-
#endif
37-
return parm;
38-
}
39-
40-
#ifndef TEST_HAS_NO_THREADS
41-
# define NUMTHREADS 10
42-
size_t thread_globals[NUMTHREADS] = {0};
43-
std::__libcpp_thread_t threads[NUMTHREADS];
44-
#endif
45-
46-
int main() {
47-
#ifndef TEST_HAS_NO_THREADS
48-
// Make the threads, let them run, and wait for them to finish
49-
for (int i = 0; i < NUMTHREADS; ++i)
50-
std::__libcpp_thread_create(threads + i, thread_code, (void*)(thread_globals + i));
51-
for (int i = 0; i < NUMTHREADS; ++i)
52-
std::__libcpp_thread_join(&threads[i]);
53-
54-
int retVal = 0;
55-
for (int i = 0; i < NUMTHREADS; ++i) {
56-
if (0 == thread_globals[i]) {
57-
std::printf("Thread #%d had a zero global\n", i);
58-
retVal = 1;
59-
}
60-
}
61-
62-
std::sort(thread_globals, thread_globals + NUMTHREADS);
63-
for (int i = 1; i < NUMTHREADS; ++i) {
64-
if (thread_globals[i - 1] == thread_globals[i]) {
65-
std::printf("Duplicate thread globals (%d and %d)\n", i - 1, i);
66-
retVal = 2;
67-
}
68-
}
69-
return retVal;
70-
#else // TEST_HAS_NO_THREADS
71-
size_t thread_globals;
72-
thread_code(&thread_globals);
73-
// Check that __cxa_get_globals() is not NULL.
74-
return (thread_globals == 0) ? 1 : 0;
75-
#endif // !TEST_HAS_NO_THREADS
23+
return 0;
7624
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===----------------------------------------------------------------------===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, no-threads
10+
11+
#include "test_macros.h"
12+
13+
#include <algorithm>
14+
#include <condition_variable>
15+
#include <functional>
16+
#include <mutex>
17+
#include <thread>
18+
#include <utility>
19+
#include <vector>
20+
21+
#include "assert_macros.h"
22+
#include "concat_macros.h"
23+
#include "../src/cxa_exception.h"
24+
25+
static int threads_remaining;
26+
static std::mutex threads_remaining_lock;
27+
static std::condition_variable threads_remaining_cv;
28+
29+
static void thread_code(void*& globals) {
30+
std::thread::id thread_id = std::this_thread::get_id();
31+
(void)thread_id;
32+
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));
36+
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));
41+
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);
46+
--threads_remaining;
47+
if (threads_remaining == 0) {
48+
lock.unlock();
49+
threads_remaining_cv.notify_all();
50+
} else {
51+
threads_remaining_cv.wait(lock, []() { return threads_remaining == 0; });
52+
}
53+
}
54+
55+
int main(int, char**) {
56+
int num_threads = std::thread::hardware_concurrency();
57+
if (num_threads == 0)
58+
num_threads = 4; // arbitrary fallback value
59+
60+
std::vector<void*> thread_globals(num_threads);
61+
std::vector<std::thread> threads;
62+
threads_remaining = num_threads;
63+
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)
68+
thread.join();
69+
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]));
74+
}
75+
76+
return 0;
77+
}

0 commit comments

Comments
 (0)