diff --git a/libcxxabi/test/test_exception_storage.pass.cpp b/libcxxabi/test/test_exception_storage.pass.cpp --- a/libcxxabi/test/test_exception_storage.pass.cpp +++ b/libcxxabi/test/test_exception_storage.pass.cpp @@ -8,69 +8,66 @@ #include #include -#include +#include +#include #include <__threading_support> -#include #include "../src/cxa_exception.h" #include "test_macros.h" -typedef __cxxabiv1::__cxa_eh_globals globals_t ; +void* thread_code(void* parm) { + void* globals = __cxxabiv1::__cxa_get_globals(); + if (!globals) + std::fprintf(stderr, "Got null result from __cxa_get_globals\n"); -void *thread_code (void *parm) { - size_t *result = (size_t *) parm; - globals_t *glob1, *glob2; + void* fast_globals = __cxxabiv1::__cxa_get_globals_fast(); + if (globals != fast_globals) { + std::fprintf(stderr, "Got different result from __cxa_get_globals (%p) and __cxa_get_globals_fast (%p) \n", globals, + fast_globals); + globals = nullptr; + } - glob1 = __cxxabiv1::__cxa_get_globals (); - if ( NULL == glob1 ) - std::printf("Got null result from __cxa_get_globals\n"); - - glob2 = __cxxabiv1::__cxa_get_globals_fast (); - if ( glob1 != glob2 ) - std::printf("Got different globals!\n"); - - *result = (size_t) glob1; -#ifndef TEST_HAS_NO_THREADS - sleep ( 1 ); -#endif - return parm; + *static_cast(parm) = globals; + return parm; } -#ifndef TEST_HAS_NO_THREADS -#define NUMTHREADS 10 -size_t thread_globals [ NUMTHREADS ] = { 0 }; -std::__libcpp_thread_t threads [ NUMTHREADS ]; -#endif - int main() { #ifndef TEST_HAS_NO_THREADS -// Make the threads, let them run, and wait for them to finish - for ( int i = 0; i < NUMTHREADS; ++i ) - std::__libcpp_thread_create ( threads + i, thread_code, (void *) (thread_globals + i)); - for ( int i = 0; i < NUMTHREADS; ++i ) - std::__libcpp_thread_join ( &threads [ i ] ); + int num_threads = std::thread::hardware_concurrency(); + if (num_threads == 0) + num_threads = 4; // arbitrary fallback value - int retVal = 0; - for ( int i = 0; i < NUMTHREADS; ++i ) { - if ( 0 == thread_globals [ i ] ) { - std::printf("Thread #%d had a zero global\n", i); - retVal = 1; - } - } + std::vector thread_globals(num_threads); + std::vector threads(num_threads); + + // Make the threads, let them run, and wait for them to finish + for (int i = 0; i < num_threads; ++i) + std::__libcpp_thread_create(&threads[i], thread_code, &thread_globals[i]); + for (int i = 0; i < num_threads; ++i) + std::__libcpp_thread_join(&threads[i]); + + for (int i = 0; i < num_threads; ++i) { + // Either __cxa_get_globals was nullptr or __cxa_get_globals_fast returned a + // different value. We already diagnosed both in the thread. + if (!thread_globals[i]) + return 1; + } - std::sort ( thread_globals, thread_globals + NUMTHREADS ); - for ( int i = 1; i < NUMTHREADS; ++i ) { - if ( thread_globals [ i - 1 ] == thread_globals [ i ] ) { - std::printf("Duplicate thread globals (%d and %d)\n", i-1, i); - retVal = 2; - } + int retval = 0; + std::sort(thread_globals.begin(), thread_globals.end()); + for (int i = 1; i < num_threads; ++i) { + if (thread_globals[i - 1] == thread_globals[i]) { + std::fprintf(stderr, "Duplicate thread globals (%d: %p and %d: %p)\n", i - 1, thread_globals[i - 1], i, + thread_globals[i]); + retval = 2; } - return retVal; -#else // TEST_HAS_NO_THREADS - size_t thread_globals; - thread_code(&thread_globals); - // Check that __cxa_get_globals() is not NULL. - return (thread_globals == 0) ? 1 : 0; + } + return retval; +#else // TEST_HAS_NO_THREADS + void* thread_globals; + thread_code(&thread_globals); + // Check that __cxa_get_globals() is not NULL. + return (thread_globals == 0) ? 1 : 0; #endif // !TEST_HAS_NO_THREADS }