1b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//===-------------------- test_exception_storage.cpp ----------------------===//
2b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//
3b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//                     The LLVM Compiler Infrastructure
4b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//
5b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant// Source Licenses. See LICENSE.TXT for details.
7b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//
8b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant//===----------------------------------------------------------------------===//
9b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant
10e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include "../src/config.h"
11e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
1261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow#include <cstdlib>
1361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow#include <algorithm>
1461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow#include <iostream>
15e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if !LIBCXXABI_SINGLE_THREADED
16e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#  include <pthread.h>
17e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
1827b00d862a71566e4d6e5fef5fd29bf8280a2f4aHoward Hinnant#include <unistd.h>
1961b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
2027b00d862a71566e4d6e5fef5fd29bf8280a2f4aHoward Hinnant#include "../src/cxa_exception.hpp"
2161b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
2261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clowtypedef __cxxabiv1::__cxa_eh_globals globals_t ;
2361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
2461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clowvoid *thread_code (void *parm) {
2561b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    size_t *result = (size_t *) parm;
2661b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    globals_t *glob1, *glob2;
2761b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
2861b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    glob1 = __cxxabiv1::__cxa_get_globals ();
2961b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    if ( NULL == glob1 )
3061b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow        std::cerr << "Got null result from __cxa_get_globals" << std::endl;
3161b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
3261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    glob2 = __cxxabiv1::__cxa_get_globals_fast ();
3361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    if ( glob1 != glob2 )
3461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow        std::cerr << "Got different globals!" << std::endl;
3561b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
3661b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    *result = (size_t) glob1;
3761b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    sleep ( 1 );
3861b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    return parm;
3961b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    }
4061b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
41e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if !LIBCXXABI_SINGLE_THREADED
4261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow#define NUMTHREADS  10
4361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clowsize_t      thread_globals [ NUMTHREADS ] = { 0 };
4461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clowpthread_t   threads        [ NUMTHREADS ];
45e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
4661b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
4761b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clowvoid print_sizes ( size_t *first, size_t *last ) {
4861b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    std::cout << "{ " << std::hex;
4961b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    for ( size_t *iter = first; iter != last; ++iter )
5061b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow        std::cout << *iter << " ";
5161b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    std::cout << "}" << std::dec << std::endl;
5261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    }
5361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
5461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clowint main ( int argc, char *argv [] ) {
5561b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    int retVal = 0;
5661b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
57e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if LIBCXXABI_SINGLE_THREADED
58e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    size_t thread_globals;
59e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    retVal = thread_code(&thread_globals) != 0;
60e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#else
6161b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow//  Make the threads, let them run, and wait for them to finish
6261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    for ( int i = 0; i < NUMTHREADS; ++i )
6361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow        pthread_create( threads + i, NULL, thread_code, (void *) (thread_globals + i));
6461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    for ( int i = 0; i < NUMTHREADS; ++i )
6561b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow        pthread_join ( threads [ i ], NULL );
6661b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
6761b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    for ( int i = 0; i < NUMTHREADS; ++i )
6861b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow        if ( 0 == thread_globals [ i ] ) {
6961b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow            std::cerr << "Thread #" << i << " had a zero global" << std::endl;
7061b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow            retVal = 1;
7161b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow            }
7261b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow
7361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow//  print_sizes ( thread_globals, thread_globals + NUMTHREADS );
7461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    std::sort ( thread_globals, thread_globals + NUMTHREADS );
756953d901c3fd95e27241b305f35a0fc97bd881e6Howard Hinnant    for ( int i = 1; i < NUMTHREADS; ++i )
766953d901c3fd95e27241b305f35a0fc97bd881e6Howard Hinnant        if ( thread_globals [ i - 1 ] == thread_globals [ i ] ) {
7761b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow            std::cerr << "Duplicate thread globals (" << i-1 << " and " << i << ")" << std::endl;
7861b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow            retVal = 2;
7961b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow            }
8061b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow//  print_sizes ( thread_globals, thread_globals + NUMTHREADS );
81e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
82e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
8361b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    return retVal;
8461b898e4f717ecb3ce6aaa2652f7da712452d693Marshall Clow    }
85