diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-01-25 17:05:41 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-01-25 17:05:41 +0000 |
commit | 156745f575946b366c430fc2bc7b9a90d5925b29 (patch) | |
tree | e6c05ad7994d2d78c857a4397dace716751f4858 | |
parent | 672085f2aef23a8ab5b73f97279f3b9a5f207d8a (diff) | |
download | src-156745f575946b366c430fc2bc7b9a90d5925b29.tar.gz src-156745f575946b366c430fc2bc7b9a90d5925b29.zip |
Import libcxxrt master 03c83f5a57be8c5b1a29a68de5638744f17d28bavendor/libcxxrt/2024-01-25-fd484be8d1e94a1fcf6bc5c67e5c07b65ada19b6vendor/libcxxrt
Interesting fixes:
03c83f5 add __cxa_init_primary_exception (#23)
5d8a158 Fix two bugs in __cxa_end_cleanup()
b00c6c5 Insert padding in __cxa_dependent_exception
45ca8b1 Insert padding in __cxa_exception struct for compatibility
f2e5509 Fix unlock in two-word version and add missing comment.
6229590 Add an option for disabling emergency buffers. (#14)
-rw-r--r-- | cxxabi.h | 15 | ||||
-rw-r--r-- | exception.cc | 60 | ||||
-rw-r--r-- | guard.cc | 9 |
3 files changed, 73 insertions, 11 deletions
@@ -78,6 +78,13 @@ struct __cxa_exception { #if __LP64__ /** + * Now _Unwind_Exception is marked with __attribute__((aligned)), which + * implies __cxa_exception is also aligned. Insert padding in the + * beginning of the struct, rather than before unwindHeader. + */ + void *reserve; + + /** * Reference count. Used to support the C++11 exception_ptr class. This * is prepended to the structure in 64-bit mode and squeezed in to the * padding left before the 64-bit aligned _Unwind_Exception at the end in @@ -196,6 +203,14 @@ __cxa_eh_globals *__cxa_get_globals_fast(void); std::type_info * __cxa_current_exception_type(); + +void *__cxa_allocate_exception(size_t thrown_size); + +void __cxa_free_exception(void* thrown_exception); + +__cxa_exception *__cxa_init_primary_exception( + void *object, std::type_info* tinfo, void (*dest)(void *)); + /** * Throws an exception returned by __cxa_current_primary_exception(). This * exception may have been caught in another thread. diff --git a/exception.cc b/exception.cc index 57c818839e80..15f93aeb23dc 100644 --- a/exception.cc +++ b/exception.cc @@ -162,6 +162,7 @@ struct __cxa_thread_info terminate_handler terminateHandler; /** The unexpected exception handler for this thread. */ unexpected_handler unexpectedHandler; +#ifndef LIBCXXRT_NO_EMERGENCY_MALLOC /** * The number of emergency buffers held by this thread. This is 0 in * normal operation - the emergency buffers are only used when malloc() @@ -170,6 +171,7 @@ struct __cxa_thread_info * in ABI spec [3.3.1]). */ int emergencyBuffersHeld; +#endif /** * The exception currently running in a cleanup. */ @@ -197,6 +199,7 @@ struct __cxa_thread_info struct __cxa_dependent_exception { #if __LP64__ + void *reserve; void *primaryException; #endif std::type_info *exceptionType; @@ -219,6 +222,17 @@ struct __cxa_dependent_exception #endif _Unwind_Exception unwindHeader; }; +static_assert(sizeof(__cxa_exception) == sizeof(__cxa_dependent_exception), + "__cxa_exception and __cxa_dependent_exception should have the same size"); +static_assert(offsetof(__cxa_exception, referenceCount) == + offsetof(__cxa_dependent_exception, primaryException), + "referenceCount and primaryException should have the same offset"); +static_assert(offsetof(__cxa_exception, unwindHeader) == + offsetof(__cxa_dependent_exception, unwindHeader), + "unwindHeader fields should have the same offset"); +static_assert(offsetof(__cxa_dependent_exception, unwindHeader) == + offsetof(__cxa_dependent_exception, adjustedPtr) + 8, + "there should be no padding before unwindHeader"); namespace std @@ -433,6 +447,23 @@ extern "C" __cxa_eh_globals *ABI_NAMESPACE::__cxa_get_globals_fast(void) return &(thread_info_fast()->globals); } +#ifdef LIBCXXRT_NO_EMERGENCY_MALLOC +static char *alloc_or_die(size_t size) +{ + char *buffer = static_cast<char*>(calloc(1, size)); + + if (buffer == nullptr) + { + fputs("Out of memory attempting to allocate exception\n", stderr); + std::terminate(); + } + return buffer; +} +static void free_exception(char *e) +{ + free(e); +} +#else /** * An emergency allocation reserved for when malloc fails. This is treated as * 16 buffers of 1KB each. @@ -572,6 +603,7 @@ static void free_exception(char *e) free(e); } } +#endif /** * Allocates an exception structure. Returns a pointer to the space that can @@ -759,6 +791,21 @@ static void throw_exception(__cxa_exception *ex) report_failure(err, ex); } +extern "C" __cxa_exception *__cxa_init_primary_exception( + void *object, std::type_info* tinfo, void (*dest)(void *)) { + __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(object) - 1; + + ex->referenceCount = 0; + ex->exceptionType = tinfo; + + ex->exceptionDestructor = dest; + + ex->unwindHeader.exception_class = exception_class; + ex->unwindHeader.exception_cleanup = exception_cleanup; + + return ex; +} + /** * ABI function for throwing an exception. Takes the object to be thrown (the @@ -769,15 +816,8 @@ extern "C" void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void(*dest)(void*)) { - __cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1; - + __cxa_exception *ex = __cxa_init_primary_exception(thrown_exception, tinfo, dest); ex->referenceCount = 1; - ex->exceptionType = tinfo; - - ex->exceptionDestructor = dest; - - ex->unwindHeader.exception_class = exception_class; - ex->unwindHeader.exception_cleanup = exception_cleanup; throw_exception(ex); } @@ -1563,8 +1603,10 @@ asm ( ".type __cxa_end_cleanup, \"function\" \n" "__cxa_end_cleanup: \n" " push {r1, r2, r3, r4} \n" +" mov r4, lr \n" " bl __cxa_get_cleanup \n" -" push {r1, r2, r3, r4} \n" +" mov lr, r4 \n" +" pop {r1, r2, r3, r4} \n" " b _Unwind_Resume \n" " bl abort \n" ".popsection \n" @@ -69,7 +69,12 @@ * progress). The bit to use depends on the byte order of the target. * * On many 32-bit platforms, 64-bit atomics are unavailable (or slow) and so we - * treat the two halves of the 64-bit word as independent values and + * treat the two halves of the 64-bit word as independent values and establish + * an ordering on them such that the guard word is never modified unless the + * lock word is in the locked state. This means that we can do double-checked + * locking by loading the guard word and, if it is not initialised, trying to + * transition the lock word from the unlocked to locked state, and then + * manipulate the guard word. */ namespace { @@ -227,7 +232,7 @@ namespace // If another thread did manage to initialise this, release // the lock and notify the caller that initialisation is // done. - lock_word.store(initialised, memory_order::release); + lock_word.store(0, memory_order::release); return GuardState::InitDone; } return GuardState::InitLockSucceeded; |