diff --git a/src/snmalloc/README.md b/src/snmalloc/README.md index 0366a5e..05347b4 100644 --- a/src/snmalloc/README.md +++ b/src/snmalloc/README.md @@ -9,6 +9,7 @@ These are arranged in a hierarchy such that each of the directories may include - `aal/` provides the architecture abstraction layer (AAL). This layer provides abstractions over CPU-specific intrinsics and defines things such as the virtual address-space size. There is a single AAL for an snmalloc instantiation. + - `ds_aal/` provides data structures that depend on the AAL. - `pal/` provides the platform abstraction layer (PAL). This exposes OS- or environment-specific abstractions into the rest of the code. An snmalloc instantiation may use more than one PAL, including ones provided by the user. diff --git a/src/snmalloc/ds/ds.h b/src/snmalloc/ds/ds.h index a26eb20..e24b1f2 100644 --- a/src/snmalloc/ds/ds.h +++ b/src/snmalloc/ds/ds.h @@ -3,12 +3,11 @@ * */ #pragma once +#include "../ds_aal/ds_aal.h" #include "../pal/pal.h" #include "aba.h" #include "allocconfig.h" #include "combininglock.h" #include "entropy.h" -#include "flaglock.h" #include "mpmcstack.h" #include "pagemap.h" -#include "singleton.h" diff --git a/src/snmalloc/ds_aal/ds_aal.h b/src/snmalloc/ds_aal/ds_aal.h new file mode 100644 index 0000000..bf16de4 --- /dev/null +++ b/src/snmalloc/ds_aal/ds_aal.h @@ -0,0 +1,9 @@ +/** + * Data structures used by snmalloc that only depend on the AAL (Architecture + * Abstraction Layer) and not on the platform. These structures can be used + * to implement the Pal. + */ +#pragma once +#include "../aal/aal.h" +#include "flaglock.h" +#include "singleton.h" \ No newline at end of file diff --git a/src/snmalloc/ds/flaglock.h b/src/snmalloc/ds_aal/flaglock.h similarity index 96% rename from src/snmalloc/ds/flaglock.h rename to src/snmalloc/ds_aal/flaglock.h index 8676ce9..f988799 100644 --- a/src/snmalloc/ds/flaglock.h +++ b/src/snmalloc/ds_aal/flaglock.h @@ -1,7 +1,7 @@ #pragma once #include "../aal/aal.h" -#include "../pal/pal.h" +#include "snmalloc/ds_core/ds_core.h" #include "snmalloc/stl/atomic.h" namespace snmalloc @@ -13,7 +13,7 @@ namespace snmalloc */ struct DebugFlagWord { - using ThreadIdentity = DefaultPal::ThreadIdentity; + using ThreadIdentity = size_t; /** * @brief flag @@ -69,7 +69,7 @@ namespace snmalloc */ static ThreadIdentity get_thread_identity() { - return DefaultPal::get_tid(); + return debug_get_tid(); } }; diff --git a/src/snmalloc/ds/singleton.h b/src/snmalloc/ds_aal/singleton.h similarity index 51% rename from src/snmalloc/ds/singleton.h rename to src/snmalloc/ds_aal/singleton.h index 6375c13..b2efbfa 100644 --- a/src/snmalloc/ds/singleton.h +++ b/src/snmalloc/ds_aal/singleton.h @@ -1,9 +1,6 @@ #pragma once -#include "../ds_core/ds_core.h" -#include "flaglock.h" #include "snmalloc/stl/atomic.h" -#include "snmalloc/stl/type_traits.h" namespace snmalloc { @@ -15,8 +12,14 @@ namespace snmalloc template class Singleton { - inline static FlagWord flag; - inline static stl::Atomic initialised{false}; + enum class State + { + Uninitialised, + Initialising, + Initialised + }; + + inline static stl::Atomic initialised{State::Uninitialised}; inline static Object obj; public: @@ -30,20 +33,26 @@ namespace snmalloc // If defined should be initially false; SNMALLOC_ASSERT(first == nullptr || *first == false); - if (SNMALLOC_UNLIKELY(!initialised.load(stl::memory_order_acquire))) + auto state = initialised.load(stl::memory_order_acquire); + if (SNMALLOC_UNLIKELY(state == State::Uninitialised)) { - with(flag, [&]() { - if (!initialised) - { - init(&obj); - initialised.store(true, stl::memory_order_release); - if (first != nullptr) - *first = true; - } - }); + if (initialised.compare_exchange_strong( + state, State::Initialising, stl::memory_order_relaxed)) + { + init(&obj); + initialised.store(State::Initialised, stl::memory_order_release); + if (first != nullptr) + *first = true; + } } + + while (SNMALLOC_UNLIKELY(state != State::Initialised)) + { + Aal::pause(); + state = initialised.load(stl::memory_order_acquire); + } + return obj; } }; - } // namespace snmalloc diff --git a/src/snmalloc/ds_core/ds_core.h b/src/snmalloc/ds_core/ds_core.h index 2083190..01121f5 100644 --- a/src/snmalloc/ds_core/ds_core.h +++ b/src/snmalloc/ds_core/ds_core.h @@ -15,3 +15,4 @@ #include "ptrwrap.h" #include "redblacktree.h" #include "seqset.h" +#include "tid.h" \ No newline at end of file diff --git a/src/snmalloc/ds_core/tid.h b/src/snmalloc/ds_core/tid.h new file mode 100644 index 0000000..771b585 --- /dev/null +++ b/src/snmalloc/ds_core/tid.h @@ -0,0 +1,26 @@ +#pragma once + +#include "snmalloc/stl/atomic.h" + +namespace snmalloc +{ + /** + * @brief Get the an id for the current thread. + * + * @return the thread id, this should never be the default of + * ThreadIdentity. Callers can assume it is a non-default value. + * + * Note, this is only for debug. We should not assume that this is unique. + */ + inline size_t debug_get_tid() noexcept + { + static thread_local size_t tid{0}; + static stl::Atomic tid_source{0}; + + if (tid == 0) + { + tid = ++tid_source; + } + return tid; + } +} // namespace snmalloc \ No newline at end of file diff --git a/src/snmalloc/pal/pal.h b/src/snmalloc/pal/pal.h index a8d45e2..a194e79 100644 --- a/src/snmalloc/pal/pal.h +++ b/src/snmalloc/pal/pal.h @@ -177,7 +177,7 @@ namespace snmalloc { MessageBuilder msg{std::forward(args)...}; MessageBuilder msg_tid{ - "{}: {}", DefaultPal::get_tid(), msg.get_message()}; + "{}: {}", debug_get_tid(), msg.get_message()}; DefaultPal::message(msg_tid.get_message()); } } // namespace snmalloc diff --git a/src/snmalloc/pal/pal_concept.h b/src/snmalloc/pal/pal_concept.h index b7ae57a..469c8f3 100644 --- a/src/snmalloc/pal/pal_concept.h +++ b/src/snmalloc/pal/pal_concept.h @@ -68,19 +68,6 @@ namespace snmalloc } noexcept -> ConceptSame; }; - /** - * The Pal must provide a thread id for debugging. It should not return - * the default value of ThreadIdentity, as that is used as not an tid in some - * places. - */ - template - concept IsPAL_tid = - requires() { - { - PAL::get_tid() - } noexcept -> ConceptSame; - }; - /** * Absent any feature flags, the PAL must support a crude primitive allocator */ @@ -137,7 +124,6 @@ namespace snmalloc IsPAL_static_sizes && IsPAL_error && IsPAL_memops && - IsPAL_tid && (!pal_supports || IsPAL_get_entropy64) && (!pal_supports || IsPAL_mem_low_notify) && (pal_supports || diff --git a/src/snmalloc/pal/pal_open_enclave.h b/src/snmalloc/pal/pal_open_enclave.h index 4966ecc..dbfd9ad 100644 --- a/src/snmalloc/pal/pal_open_enclave.h +++ b/src/snmalloc/pal/pal_open_enclave.h @@ -1,7 +1,6 @@ #pragma once #include "pal_noalloc.h" -#include "pal_tid_default.h" #ifdef OPEN_ENCLAVE extern "C" void* oe_memset_s(void* p, size_t p_size, int c, size_t size); @@ -27,7 +26,7 @@ namespace snmalloc using OpenEnclaveBasePAL = PALNoAlloc; - class PALOpenEnclave : public OpenEnclaveBasePAL, public PalTidDefault + class PALOpenEnclave : public OpenEnclaveBasePAL { public: /** diff --git a/src/snmalloc/pal/pal_posix.h b/src/snmalloc/pal/pal_posix.h index 1214ff3..2f3f4f9 100644 --- a/src/snmalloc/pal/pal_posix.h +++ b/src/snmalloc/pal/pal_posix.h @@ -1,7 +1,6 @@ #pragma once #include "../aal/aal.h" -#include "pal_tid_default.h" #include "pal_timer_default.h" #if defined(SNMALLOC_BACKTRACE_HEADER) # include SNMALLOC_BACKTRACE_HEADER @@ -40,8 +39,7 @@ namespace snmalloc * working when an early-malloc error appears. */ template - class PALPOSIX : public PalTimerDefaultImpl>, - public PalTidDefault + class PALPOSIX : public PalTimerDefaultImpl> { /** * Helper class to access the `default_mmap_flags` field of `OS` if one diff --git a/src/snmalloc/pal/pal_tid_default.h b/src/snmalloc/pal/pal_tid_default.h deleted file mode 100644 index c854159..0000000 --- a/src/snmalloc/pal/pal_tid_default.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "snmalloc/stl/atomic.h" - -namespace snmalloc -{ - class PalTidDefault - { - public: - using ThreadIdentity = size_t; - - /** - * @brief Get the an id for the current thread. - * - * @return the thread id, this should never be the default of - * ThreadIdentity. Callers can assume it is a non-default value. - */ - static inline ThreadIdentity get_tid() noexcept - { - static thread_local size_t tid{0}; - static stl::Atomic tid_source{0}; - - if (tid == 0) - { - tid = ++tid_source; - } - return tid; - } - }; -} // namespace snmalloc diff --git a/src/snmalloc/pal/pal_windows.h b/src/snmalloc/pal/pal_windows.h index dbe1b2b..1cbcd41 100644 --- a/src/snmalloc/pal/pal_windows.h +++ b/src/snmalloc/pal/pal_windows.h @@ -1,7 +1,6 @@ #pragma once #include "../aal/aal.h" -#include "pal_tid_default.h" #include "pal_timer_default.h" #ifdef _WIN32 @@ -26,8 +25,7 @@ namespace snmalloc { - class PALWindows : public PalTimerDefaultImpl, - public PalTidDefault + class PALWindows : public PalTimerDefaultImpl { /** * A flag indicating that we have tried to register for low-memory