[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