diff options
| author | joerg <joerg@NetBSD.org> | 2014-05-15 23:56:01 +0000 |
|---|---|---|
| committer | joerg <joerg@NetBSD.org> | 2014-05-15 23:56:01 +0000 |
| commit | e793739d31dc28ab70e8373a3cc572499d403da8 (patch) | |
| tree | 8cfb35f7e4488a6f71fcd3697351f3ebafd5cb3b /external/bsd/libc++ | |
| parent | 7972508cd3db7ea3857a7e0059b22fd1910c8fe9 (diff) | |
Import libcxxrt revision 4eb349088dda15d2de9a8c7b144c3f2d5f390269.
Restore support for 32bit architectures without 64bit CAS.
Support DWARF exception handling on ARM.
Diffstat (limited to 'external/bsd/libc++')
| -rw-r--r-- | external/bsd/libc++/dist/libcxxrt/src/cxxabi.h | 2 | ||||
| -rw-r--r-- | external/bsd/libc++/dist/libcxxrt/src/exception.cc | 30 | ||||
| -rw-r--r-- | external/bsd/libc++/dist/libcxxrt/src/guard.cc | 99 | ||||
| -rw-r--r-- | external/bsd/libc++/dist/libcxxrt/src/unwind.h | 2 |
4 files changed, 92 insertions, 41 deletions
diff --git a/external/bsd/libc++/dist/libcxxrt/src/cxxabi.h b/external/bsd/libc++/dist/libcxxrt/src/cxxabi.h index 7c8336076bb..411c4c749cc 100644 --- a/external/bsd/libc++/dist/libcxxrt/src/cxxabi.h +++ b/external/bsd/libc++/dist/libcxxrt/src/cxxabi.h @@ -110,7 +110,7 @@ struct __cxa_exception * 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 --git a/external/bsd/libc++/dist/libcxxrt/src/exception.cc b/external/bsd/libc++/dist/libcxxrt/src/exception.cc index 048021ae2ef..ed5ad2b9865 100644 --- a/external/bsd/libc++/dist/libcxxrt/src/exception.cc +++ b/external/bsd/libc++/dist/libcxxrt/src/exception.cc @@ -71,7 +71,7 @@ static void saveLandingPad(struct _Unwind_Context *context, 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 @@ static int loadLandingPad(struct _Unwind_Context *context, 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 int loadLandingPad(struct _Unwind_Context *context, 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 @@ struct __cxa_dependent_exception 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 @@ static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c) { 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 @@ static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c) * 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 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce 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 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce // 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 @@ static handler_type check_action_record(_Unwind_Context *context, { 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 handler_type check_action_record(_Unwind_Context *context, 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 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) 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 @@ namespace std 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 --git a/external/bsd/libc++/dist/libcxxrt/src/guard.cc b/external/bsd/libc++/dist/libcxxrt/src/guard.cc index d9220a0aba2..ecfe2434376 100644 --- a/external/bsd/libc++/dist/libcxxrt/src/guard.cc +++ b/external/bsd/libc++/dist/libcxxrt/src/guard.cc @@ -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 INITIALISED = 1; 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 @@ static const guard_t INITIALISED = static_cast<guard_t>(1) << 56; */ 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 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(); + if (INITIALISED != *INIT_PART(guard_object)) + return 1; + + // 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" int __cxa_guard_acquire(volatile guard_t *guard_object) 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_abort(volatile guard_t *guard_object) */ 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 --git a/external/bsd/libc++/dist/libcxxrt/src/unwind.h b/external/bsd/libc++/dist/libcxxrt/src/unwind.h index e463a2a781d..130dd6d82fc 100644 --- a/external/bsd/libc++/dist/libcxxrt/src/unwind.h +++ b/external/bsd/libc++/dist/libcxxrt/src/unwind.h @@ -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" |
