Thanks Marshall! Howard
On Jul 20, 2011, at 10:53 AM, Marshall Clow wrote: > Author: marshall > Date: Wed Jul 20 09:53:53 2011 > New Revision: 135586 > > URL: http://llvm.org/viewvc/llvm-project?rev=135586&view=rev > Log: > Exception handling stuctures, and thread-local variables for exception > handling > > Added: > libcxxabi/trunk/src/cxa_exception.hpp > libcxxabi/trunk/src/cxa_exception_storage.cpp > libcxxabi/trunk/test/test_exception_storage.cpp > > Added: libcxxabi/trunk/src/cxa_exception.hpp > URL: > http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception.hpp?rev=135586&view=auto > ============================================================================== > --- libcxxabi/trunk/src/cxa_exception.hpp (added) > +++ libcxxabi/trunk/src/cxa_exception.hpp Wed Jul 20 09:53:53 2011 > @@ -0,0 +1,95 @@ > +#include <exception> // for std::unexpected_handler and > std::terminate_handler > +#include <cxxabi.h> > +#include "unwind.h" > + > +namespace __cxxabiv1 { > + > + struct __cxa_exception { > +#if __LP64__ > + // This is a new field to support C++ 0x exception_ptr. > + // For binary compatibility it is at the start of this > + // struct which is prepended to the object thrown in > + // __cxa_allocate_exception. > + size_t referenceCount; > +#endif > + > + // Manage the exception object itself. > + std::type_info *exceptionType; > + void (*exceptionDestructor)(void *); > + std::unexpected_handler unexpectedHandler; > + std::terminate_handler terminateHandler; > + > + __cxa_exception *nextException; > + > + int handlerCount; > + > +#ifdef __ARM_EABI_UNWINDER__ > + __cxa_exception* nextPropagatingException; > + int propagationCount; > +#else > + int handlerSwitchValue; > + const unsigned char *actionRecord; > + const unsigned char *languageSpecificData; > + void *catchTemp; > + void *adjustedPtr; > +#endif > + > +#if !__LP64__ > + // This is a new field to support C++ 0x exception_ptr. > + // For binary compatibility it is placed where the compiler > + // previously adding padded to 64-bit align unwindHeader. > + size_t referenceCount; > +#endif > + > + _Unwind_Exception unwindHeader; > + }; > + > + struct __cxa_dependent_exception { > +#if __LP64__ > + void* primaryException; > +#endif > + > + // Unused dummy data (should be set to null) > + std::type_info *exceptionType; > + void (*exceptionDestructor)(void *); > + > + std::unexpected_handler unexpectedHandler; > + std::terminate_handler terminateHandler; > + > + __cxa_exception *nextException; > + > + int handlerCount; > + > +#ifdef __ARM_EABI_UNWINDER__ > + __cxa_exception* nextPropagatingException; > + int propagationCount; > +#else > + int handlerSwitchValue; > + const unsigned char *actionRecord; > + const unsigned char *languageSpecificData; > + void * catchTemp; > + void *adjustedPtr; > +#endif > + > +#if !__LP64__ > + void* primaryException; > +#endif > + > + _Unwind_Exception unwindHeader; > + }; > + > + struct __cxa_eh_globals { > + __cxa_exception * caughtExceptions; > + unsigned int uncaughtExceptions; > +#ifdef __ARM_EABI_UNWINDER__ > + __cxa_exception* propagatingExceptions; > +#endif > + }; > + > + extern "C" __cxa_eh_globals * __cxa_get_globals () throw(); > + extern "C" __cxa_eh_globals * __cxa_get_globals_fast () throw(); > + > + extern "C" void * __cxa_allocate_dependent_exception () throw(); > + extern "C" void __cxa_free_dependent_exception (void * > dependent_exception) throw(); > + > +} > \ No newline at end of file > > Added: libcxxabi/trunk/src/cxa_exception_storage.cpp > URL: > http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception_storage.cpp?rev=135586&view=auto > ============================================================================== > --- libcxxabi/trunk/src/cxa_exception_storage.cpp (added) > +++ libcxxabi/trunk/src/cxa_exception_storage.cpp Wed Jul 20 09:53:53 2011 > @@ -0,0 +1,81 @@ > +//===--------------------- cxa_exception_storage.cpp > ----------------------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is dual licensed under the MIT and the University of Illinois > Open > +// Source Licenses. See LICENSE.TXT for details. > +// > +// > +// This file implements the storage for the "Caught Exception Stack" > +// http://www.codesourcery.com/public/cxx-abi/abi-eh.html (section 2.2.2) > +// > +//===----------------------------------------------------------------------===// > + > +#include "cxa_exception.hpp" > + > +#ifdef HAS_THREAD_LOCAL > + > +namespace __cxxabiv1 { > + > +namespace { > + __cxa_eh_globals * __globals () throw () { > + static thread_local __cxa_eh_globals eh_globals; > + return &eh_globals; > + } > + } > + > +extern "C" { > + __cxa_eh_globals * __cxa_get_globals () throw() { return __globals > (); } > + __cxa_eh_globals * __cxa_get_globals_fast () throw() { return __globals > (); } > + } > +} > + > +#else > + > +#include <pthread.h> > +#include <cstdlib> // for calloc, free > +#include <exception> // for std::terminate > + > +// In general, we treat all pthread errors as fatal - our error > +// reporting mechanism is std::terminate. > + > +namespace __cxxabiv1 { > +namespace { > + pthread_once_t flag_ = PTHREAD_ONCE_INIT; > + pthread_key_t key_; > + > + void destruct_ (void *p) throw () { > + std::free ( p ); > + if ( 0 != ::pthread_setspecific ( key_, NULL )) std::terminate (); > + } > + > + void construct_ () throw () { > + if ( 0 != pthread_key_create ( &key_, destruct_ )) std::terminate (); > + } > +} > + > +extern "C" { > + __cxa_eh_globals * __cxa_get_globals () throw () { > + // First time through, create the key. > + if ( 0 != pthread_once ( &flag_, construct_ )) std::terminate (); > + > + // Try to get the globals for this thread > + __cxa_eh_globals* retVal = __cxa_get_globals_fast (); > + > + // If this is the first time we've been asked for these globals, create > them > + if ( NULL == retVal ) { > + retVal = static_cast<__cxa_eh_globals*> > + (std::calloc (1, sizeof (__cxa_eh_globals))); > + if ( NULL == retVal ) std::terminate (); > + if ( 0 != pthread_setspecific ( key_, retVal )) std::terminate > (); > + } > + return retVal; > + } > + > + __cxa_eh_globals * __cxa_get_globals_fast () throw () { > + return static_cast<__cxa_eh_globals*>(::pthread_getspecific(key_)); > + } > + > +} > +} > +#endif > > Added: libcxxabi/trunk/test/test_exception_storage.cpp > URL: > http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_exception_storage.cpp?rev=135586&view=auto > ============================================================================== > --- libcxxabi/trunk/test/test_exception_storage.cpp (added) > +++ libcxxabi/trunk/test/test_exception_storage.cpp Wed Jul 20 09:53:53 2011 > @@ -0,0 +1,64 @@ > +#include <cstdlib> > +#include <algorithm> > +#include <iostream> > +#include <pthread.h> > + > +#include "cxa_exception.hpp" > + > +typedef __cxxabiv1::__cxa_eh_globals globals_t ; > + > +void *thread_code (void *parm) { > + size_t *result = (size_t *) parm; > + globals_t *glob1, *glob2; > + > + glob1 = __cxxabiv1::__cxa_get_globals (); > + if ( NULL == glob1 ) > + std::cerr << "Got null result from __cxa_get_globals" << std::endl; > + > + glob2 = __cxxabiv1::__cxa_get_globals_fast (); > + if ( glob1 != glob2 ) > + std::cerr << "Got different globals!" << std::endl; > + > + *result = (size_t) glob1; > + sleep ( 1 ); > + return parm; > + } > + > + > +#define NUMTHREADS 10 > +size_t thread_globals [ NUMTHREADS ] = { 0 }; > +pthread_t threads [ NUMTHREADS ]; > + > +void print_sizes ( size_t *first, size_t *last ) { > + std::cout << "{ " << std::hex; > + for ( size_t *iter = first; iter != last; ++iter ) > + std::cout << *iter << " "; > + std::cout << "}" << std::dec << std::endl; > + } > + > +int main ( int argc, char *argv [] ) { > + int retVal = 0; > + > +// Make the threads, let them run, and wait for them to finish > + for ( int i = 0; i < NUMTHREADS; ++i ) > + pthread_create( threads + i, NULL, thread_code, (void *) > (thread_globals + i)); > + for ( int i = 0; i < NUMTHREADS; ++i ) > + pthread_join ( threads [ i ], NULL ); > + > + for ( int i = 0; i < NUMTHREADS; ++i ) > + if ( 0 == thread_globals [ i ] ) { > + std::cerr << "Thread #" << i << " had a zero global" << > std::endl; > + retVal = 1; > + } > + > +// print_sizes ( thread_globals, thread_globals + NUMTHREADS ); > + std::sort ( thread_globals, thread_globals + NUMTHREADS ); > + for ( int i = 1; i < NUMTHREADS; ++i ) { > + if ( thread_globals [ i - 1 ] == thread_globals [ i ] ) > + std::cerr << "Duplicate thread globals (" << i-1 << " and " << i > << ")" << std::endl; > + retVal = 2; > + } > +// print_sizes ( thread_globals, thread_globals + NUMTHREADS ); > + > + return retVal; > + } > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
