From fb8cc3b07be8677604df8df8e7b270edc2000aef Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Tue, 27 Mar 2012 19:34:09 +0100 Subject: Ensure the correct happens-before relationship between set / get functions. Add the C++11 std::get_new_handler(). --- src/atomic.h | 29 +++++++++++++++++++++++++++++ src/exception.cc | 10 ++++++---- src/memory.cc | 25 +++++++++++++------------ 3 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 src/atomic.h diff --git a/src/atomic.h b/src/atomic.h new file mode 100644 index 0000000..bcd8a47 --- /dev/null +++ b/src/atomic.h @@ -0,0 +1,29 @@ + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +/** + * Swap macro that enforces a happens-before relationship with a corresponding + * ATOMIC_LOAD. + */ +#if __has_feature(cxx_atomic) +#define ATOMIC_SWAP(addr, val)\ + __atomic_exchange(addr, val, __ATOMIC_ACQ_REL) +#elif __has_builtin(__sync_swap) +#define ATOMIC_SWAP(addr, val)\ + __sync_swap(addr, val) +#else +#define ATOMIC_SWAP(addr, val)\ + __sync_lock_test_and_set(addr, val) +#endif + +#if __has_feature(cxx_atomic) +#define ATOMIC_LOAD(addr)\ + __atomic_load(addr, __ATOMIC_ACQUIRE) +#else +#define ATOMIC_LOAD(addr)\ + (__sync_synchronize(), *addr) +#endif diff --git a/src/exception.cc b/src/exception.cc index fe56297..6e841ef 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -32,6 +32,7 @@ #include #include "typeinfo.h" #include "dwarf_eh.h" +#include "atomic.h" #include "cxxabi.h" #pragma weak pthread_key_create @@ -1328,7 +1329,7 @@ namespace std { if (thread_local_handlers) { return pathscale::set_unexpected(f); } - return __sync_lock_test_and_set(&unexpectedHandler, f); + return ATOMIC_SWAP(&terminateHandler, f); } /** * Sets the function that is called to terminate the program. @@ -1336,7 +1337,8 @@ namespace std terminate_handler set_terminate(terminate_handler f) throw() { if (thread_local_handlers) { return pathscale::set_terminate(f); } - return __sync_lock_test_and_set(&terminateHandler, f); + + return ATOMIC_SWAP(&terminateHandler, f); } /** * Terminates the program, calling a custom terminate implementation if @@ -1390,7 +1392,7 @@ namespace std { return info->unexpectedHandler; } - return unexpectedHandler; + return ATOMIC_LOAD(&unexpectedHandler); } /** * Returns the current terminate handler. @@ -1402,7 +1404,7 @@ namespace std { return info->terminateHandler; } - return terminateHandler; + return ATOMIC_LOAD(&terminateHandler); } } #ifdef __arm__ diff --git a/src/memory.cc b/src/memory.cc index bd7fd22..fec861a 100644 --- a/src/memory.cc +++ b/src/memory.cc @@ -36,14 +36,8 @@ #include #include #include "stdexcept.h" +#include "atomic.h" -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#if !__has_builtin(__sync_swap) -#define __sync_swap __sync_lock_test_and_set -#endif namespace std { @@ -67,7 +61,12 @@ namespace std __attribute__((weak)) new_handler set_new_handler(new_handler handler) { - return __sync_swap(&new_handl, handler); + return ATOMIC_SWAP(&new_handl, handler); + } + __attribute__((weak)) + new_handler get_new_handler(void) + { + return ATOMIC_LOAD(&new_handl); } } @@ -78,9 +77,10 @@ void* operator new(size_t size) void * mem = malloc(size); while (0 == mem) { - if (0 != new_handl) + new_handler h = std::get_new_handler(); + if (0 != h) { - new_handl(); + h(); } else { @@ -98,11 +98,12 @@ void* operator new(size_t size, const std::nothrow_t &) throw() void *mem = malloc(size); while (0 == mem) { - if (0 != new_handl) + new_handler h = std::get_new_handler(); + if (0 != h) { try { - new_handl(); + h(); } catch (...) { -- cgit v1.2.3