[cfe-commits] [libcxxabi] r135586 - in /libcxxabi/trunk: src/cxa_exception.hpp src/cxa_exception_storage.cpp test/test_exception_storage.cpp
Howard Hinnant
hhinnant at apple.com
Wed Jul 20 08:07:56 PDT 2011
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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list