[cfe-commits] [libcxxabi] r135586 - in /libcxxabi/trunk: src/cxa_exception.hpp src/cxa_exception_storage.cpp test/test_exception_storage.cpp

Marshall Clow mclow at qualcomm.com
Wed Jul 20 07:53:53 PDT 2011


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;
+    }





More information about the cfe-commits mailing list