Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/bsd/libc++/dist/libcxxrt/src Import libcxxrt revisi...



details:   https://anonhg.NetBSD.org/src/rev/70b1572f46cf
branches:  trunk
changeset: 795991:70b1572f46cf
user:      joerg <joerg%NetBSD.org@localhost>
date:      Thu May 15 23:56:01 2014 +0000

description:
Import libcxxrt revision 4eb349088dda15d2de9a8c7b144c3f2d5f390269.
Restore support for 32bit architectures without 64bit CAS.
Support DWARF exception handling on ARM.

diffstat:

 external/bsd/libc++/dist/libcxxrt/src/cxxabi.h     |   2 +-
 external/bsd/libc++/dist/libcxxrt/src/exception.cc |  30 ++++--
 external/bsd/libc++/dist/libcxxrt/src/guard.cc     |  99 +++++++++++++++------
 external/bsd/libc++/dist/libcxxrt/src/unwind.h     |   2 +-
 4 files changed, 92 insertions(+), 41 deletions(-)

diffs (299 lines):

diff -r 0c2a15e7fc22 -r 70b1572f46cf external/bsd/libc++/dist/libcxxrt/src/cxxabi.h
--- a/external/bsd/libc++/dist/libcxxrt/src/cxxabi.h    Thu May 15 23:53:10 2014 +0000
+++ b/external/bsd/libc++/dist/libcxxrt/src/cxxabi.h    Thu May 15 23:56:01 2014 +0000
@@ -110,7 +110,7 @@
         * handler count reaches 0 (which it doesn't with the top bit set).
         */
        int handlerCount;
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        /**
         * The ARM EH ABI requires the unwind library to keep track of exceptions
         * during cleanups.  These support nesting, so we need to keep a list of
diff -r 0c2a15e7fc22 -r 70b1572f46cf external/bsd/libc++/dist/libcxxrt/src/exception.cc
--- a/external/bsd/libc++/dist/libcxxrt/src/exception.cc        Thu May 15 23:53:10 2014 +0000
+++ b/external/bsd/libc++/dist/libcxxrt/src/exception.cc        Thu May 15 23:56:01 2014 +0000
@@ -71,7 +71,7 @@
                            int selector,
                            dw_eh_ptr_t landingPad)
 {
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        // On ARM, we store the saved exception in the generic part of the structure
        ucb->barrier_cache.sp = _Unwind_GetGR(context, 13);
        ucb->barrier_cache.bitpattern[1] = static_cast<uint32_t>(selector);
@@ -95,7 +95,7 @@
                           unsigned long *selector,
                           dw_eh_ptr_t *landingPad)
 {
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        *selector = ucb->barrier_cache.bitpattern[1];
        *landingPad = reinterpret_cast<dw_eh_ptr_t>(ucb->barrier_cache.bitpattern[3]);
        return 1;
@@ -113,7 +113,7 @@
 static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex,
                                                     struct _Unwind_Context *context)
 {
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; }
 #endif
        return _URC_CONTINUE_UNWIND;
@@ -204,7 +204,7 @@
        terminate_handler terminateHandler;
        __cxa_exception *nextException;
        int handlerCount;
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        _Unwind_Exception *nextCleanup;
        int cleanupCount;
 #endif
@@ -654,7 +654,7 @@
 {
        Dl_info myinfo;
        int mylookup =
-               dladdr(reinterpret_cast<const void *>(__cxa_current_exception_type), &myinfo);
+               dladdr(reinterpret_cast<void *>(__cxa_current_exception_type), &myinfo);
        void *ip = reinterpret_cast<void*>(_Unwind_GetIP(context));
        Dl_info info;
        if (dladdr(ip, &info) != 0)
@@ -673,6 +673,11 @@
  * If the failure happened by falling off the end of the stack without finding
  * a handler, prints a back trace before aborting.
  */
+#if __GNUC__ > 3 && __GNUC_MINOR__ > 2
+extern "C" void *__cxa_begin_catch(void *e) throw();
+#else
+extern "C" void *__cxa_begin_catch(void *e);
+#endif
 static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exception)
 {
        switch (err)
@@ -681,12 +686,14 @@
                case _URC_FATAL_PHASE1_ERROR:
                        fprintf(stderr, "Fatal error during phase 1 unwinding\n");
                        break;
-#ifndef __arm__
+#if !defined(__arm__) || defined(__ARM_DWARF_EH__)
                case _URC_FATAL_PHASE2_ERROR:
                        fprintf(stderr, "Fatal error during phase 2 unwinding\n");
                        break;
 #endif
                case _URC_END_OF_STACK:
+                       __cxa_begin_catch (&(thrown_exception->unwindHeader));
+                       std::terminate();
                        fprintf(stderr, "Terminating due to uncaught exception %p", 
                                        static_cast<void*>(thrown_exception));
                        thrown_exception = realExceptionFromException(thrown_exception);
@@ -716,6 +723,9 @@
                        // Print a back trace if no handler is found.
                        // TODO: Make this optional
                        _Unwind_Backtrace(trace, 0);
+
+                       // Just abort. No need to call std::terminate for the second time
+                       abort();
                        break;
        }
        std::terminate();
@@ -972,7 +982,7 @@
                {
                        bool matched = false;
                        *selector = filter;
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
                        filter++;
                        std::type_info *handler_type = get_type_info_entry(context, lsda, filter--);
                        while (handler_type)
@@ -1017,7 +1027,7 @@
 static void pushCleanupException(_Unwind_Exception *exceptionObject,
                                  __cxa_exception *ex)
 {
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        __cxa_thread_info *info = thread_info_fast();
        if (ex)
        {
@@ -1062,7 +1072,7 @@
                realEx = realExceptionFromException(ex);
        }
 
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
        unsigned char *lsda_addr =
                static_cast<unsigned char*>(_Unwind_GetLanguageSpecificData(context));
 #else
@@ -1486,7 +1496,7 @@
                return ATOMIC_LOAD(&terminateHandler);
        }
 }
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
 extern "C" _Unwind_Exception *__cxa_get_cleanup(void)
 {
        __cxa_thread_info *info = thread_info_fast();
diff -r 0c2a15e7fc22 -r 70b1572f46cf external/bsd/libc++/dist/libcxxrt/src/guard.cc
--- a/external/bsd/libc++/dist/libcxxrt/src/guard.cc    Thu May 15 23:53:10 2014 +0000
+++ b/external/bsd/libc++/dist/libcxxrt/src/guard.cc    Thu May 15 23:56:01 2014 +0000
@@ -70,10 +70,14 @@
 #ifdef __arm__
 // ARM ABI - 32-bit guards.
 typedef uint32_t guard_t;
+typedef uint32_t guard_lock_t;
 static const uint32_t LOCKED = static_cast<guard_t>(1) << 31;
 static const uint32_t INITIALISED = 1;
-#else
+#define LOCK_PART(guard) (guard)
+#define INIT_PART(guard) (guard)
+#elif defined(_LP64)
 typedef uint64_t guard_t;
+typedef uint64_t guard_lock_t;
 #      if defined(__LITTLE_ENDIAN__)
 static const guard_t LOCKED = static_cast<guard_t>(1) << 63;
 static const guard_t INITIALISED = 1;
@@ -81,7 +85,30 @@
 static const guard_t LOCKED = 1;
 static const guard_t INITIALISED = static_cast<guard_t>(1) << 56;
 #      endif
+#define LOCK_PART(guard) (guard)
+#define INIT_PART(guard) (guard)
+#else
+#      if defined(__LITTLE_ENDIAN__)
+typedef struct {
+       uint32_t init_half;
+       uint32_t lock_half;
+} guard_t;
+typedef uint32_t guard_lock_t;
+static const uint32_t LOCKED = static_cast<guard_lock_t>(1) << 31;
+static const uint32_t INITIALISED = 1;
+#      else
+typedef struct {
+       uint32_t init_half;
+       uint32_t lock_half;
+} guard_t;
+static_assert(sizeof(guard_t) == sizeof(uint64_t), "");
+static const uint32_t LOCKED = 1;
+static const uint32_t INITIALISED = static_cast<guard_lock_t>(1) << 24;
+#      endif
+#define LOCK_PART(guard) (&(guard)->lock_half)
+#define INIT_PART(guard) (&(guard)->init_half)
 #endif
+static const guard_lock_t INITIAL = 0;
 
 /**
  * Acquires a lock on a guard, returning 0 if the object has already been
@@ -90,42 +117,49 @@
  */
 extern "C" int __cxa_guard_acquire(volatile guard_t *guard_object)
 {
+       guard_lock_t old;
        // Not an atomic read, doesn't establish a happens-before relationship, but
        // if one is already established and we end up seeing an initialised state
        // then it's a fast path, otherwise we'll do something more expensive than
        // this test anyway...
-       if ((INITIALISED == *guard_object)) { return 0; }
+       if (INITIALISED == *INIT_PART(guard_object))
+               return 0;
        // Spin trying to do the initialisation
-       while (1)
+       for (;;)
        {
                // Loop trying to move the value of the guard from 0 (not
                // locked, not initialised) to the locked-uninitialised
                // position.
-               switch (__sync_val_compare_and_swap(guard_object, 0, LOCKED))
-               {
-                       // If the old value was 0, we succeeded, so continue
-                       // initialising
-                       case 0:
+               old = __sync_val_compare_and_swap(LOCK_PART(guard_object),
+                   INITIAL, LOCKED);
+               if (old == INITIAL) {
+                       // Lock obtained.  If lock and init bit are
+                       // in separate words, check for init race.
+                       if (INIT_PART(guard_object) == LOCK_PART(guard_object))
+                               return 1;
+                       if (INITIALISED != *INIT_PART(guard_object))
                                return 1;
-                       // If this was already initialised, return and let the caller skip
-                       // initialising it again.
-                       case INITIALISED:
-                               return 0;
-                       // If it is locked by another thread, relinquish the CPU and try
-                       // again later.
-                       case LOCKED:
-                       case LOCKED | INITIALISED:
-                               sched_yield();
-                               break;
-                       // If it is some other value, then something has gone badly wrong.
-                       // Give up.
-                       default:
-                               fprintf(stderr, "Invalid state detected attempting to lock static initialiser.\n");
-                               abort();
+
+                       // No need for a memory barrier here,
+                       // see first comment.
+                       *LOCK_PART(guard_object) = INITIAL;
+                       return 0;
                }
+               // If lock and init bit are in the same word, check again
+               // if we are done.
+               if (INIT_PART(guard_object) == LOCK_PART(guard_object) &&
+                   old == INITIALISED)
+                       return 0;
+
+               assert(old == LOCKED);
+               // Another thread holds the lock.
+               // If lock and init bit are in different words, check
+               // if we are done before yielding and looping.
+               if (INIT_PART(guard_object) != LOCK_PART(guard_object) &&
+                   INITIALISED == *INIT_PART(guard_object))
+                       return 0;
+               sched_yield();
        }
-       //__builtin_unreachable();
-       return 0;
 }
 
 /**
@@ -135,7 +169,8 @@
 extern "C" void __cxa_guard_abort(volatile guard_t *guard_object)
 {
        __attribute__((unused))
-       bool reset = __sync_bool_compare_and_swap(guard_object, LOCKED, 0);
+       bool reset = __sync_bool_compare_and_swap(LOCK_PART(guard_object),
+           LOCKED, INITIAL);
        assert(reset);
 }
 /**
@@ -144,9 +179,15 @@
  */
 extern "C" void __cxa_guard_release(volatile guard_t *guard_object)
 {
+       guard_lock_t old;
+       if (INIT_PART(guard_object) == LOCK_PART(guard_object))
+               old = LOCKED;
+       else
+               old = INITIAL;
        __attribute__((unused))
-       bool reset = __sync_bool_compare_and_swap(guard_object, LOCKED, INITIALISED);
+       bool reset = __sync_bool_compare_and_swap(INIT_PART(guard_object),
+           old, INITIALISED);
        assert(reset);
+       if (INIT_PART(guard_object) != LOCK_PART(guard_object))
+               *LOCK_PART(guard_object) = INITIAL;
 }
-
-
diff -r 0c2a15e7fc22 -r 70b1572f46cf external/bsd/libc++/dist/libcxxrt/src/unwind.h
--- a/external/bsd/libc++/dist/libcxxrt/src/unwind.h    Thu May 15 23:53:10 2014 +0000
+++ b/external/bsd/libc++/dist/libcxxrt/src/unwind.h    Thu May 15 23:56:01 2014 +0000
@@ -27,7 +27,7 @@
 extern "C" {
 #endif
 
-#ifdef __arm__
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
 #include "unwind-arm.h"
 #else
 #include "unwind-itanium.h"



Home | Main Index | Thread Index | Old Index