From cf9c2eb9d95c5857dca552a6b10eb943528969fd Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Fri, 10 Apr 2020 13:49:39 +0100 Subject: [PATCH] Addressing OE linking issues when built with GCC (#167) * Use C++17 inline statics This leads to better codegen in GCC, and fixes some linking issues in OE. * Detect GCC and OE combination and fall-back to lock based ABA. * clangformat --- src/ds/aba.h | 10 ++++++++-- src/ds/defines.h | 4 ++++ src/ds/helpers.h | 10 +++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/ds/aba.h b/src/ds/aba.h index 048f7e4f7..38aaa3605 100644 --- a/src/ds/aba.h +++ b/src/ds/aba.h @@ -7,7 +7,8 @@ * implementable with double-word compare and exchange or with load-link * store conditional. * - * We provide a lock based implementation. + * We provide a lock based implementation as a backup for other platforms + * without appropriate intrinsics. */ namespace snmalloc { @@ -16,7 +17,12 @@ namespace snmalloc // check this on other platforms using a thread_local. inline thread_local bool operation_in_flight = false; #endif -#ifdef PLATFORM_IS_X86 + // The !(defined(GCC_NOT_CLANG) && defined(OPEN_ENCLAVE)) is required as + // GCC is outputing a function call to libatomic, rather than just the x86 + // instruction, this causes problems for linking later. For this case + // fall back to locked implementation. +#if defined(PLATFORM_IS_X86) && \ + !(defined(GCC_NOT_CLANG) && defined(OPEN_ENCLAVE)) template class ABA { diff --git a/src/ds/defines.h b/src/ds/defines.h index 74a8e38a5..f697e1f24 100644 --- a/src/ds/defines.h +++ b/src/ds/defines.h @@ -19,6 +19,10 @@ #endif #if !defined(__clang__) && defined(__GNUC__) +# define GCC_NOT_CLANG +#endif + +#ifdef GCC_NOT_CLANG # if __GNUC__ >= 8 # define GCC_VERSION_EIGHT_PLUS # endif diff --git a/src/ds/helpers.h b/src/ds/helpers.h index c2f2ead08..b47901195 100644 --- a/src/ds/helpers.h +++ b/src/ds/helpers.h @@ -13,18 +13,18 @@ namespace snmalloc template class Singleton { + inline static std::atomic_flag flag; + inline static std::atomic initialised = false; + inline static Object obj; + public: /** * If argument is non-null, then it is assigned the value * true, if this is the first call to get. * At most one call will be first. */ - inline static Object& get(bool* first = nullptr) + inline SNMALLOC_SLOW_PATH static Object& get(bool* first = nullptr) { - static std::atomic_flag flag; - static std::atomic initialised; - static Object obj; - // If defined should be initially false; SNMALLOC_ASSERT(first == nullptr || *first == false);