Squashed 'third_party/marl/' changes from a47a3a5c5..9c689c9a8 9c689c9a8 Add MARL_USE_PTHREAD_THREAD_LOCAL option abd033696 Explicitly #include <utility> in finally.h 2e82e6999 Fix build issue with GetModuleHandle when using UNICODE 40b9a1c47 gcc -Wshadow warning fixes git-subtree-dir: third_party/marl git-subtree-split: 9c689c9a88bd8c6a8fe48b01d5ec6b71974282a6 Change-Id: I03c1b559c7c3fc8d5afde198543d6e5eb6100af6
diff --git a/CMakeLists.txt b/CMakeLists.txt index c84076d..5f17ee8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -46,6 +46,7 @@ option_if_not_defined(MARL_BUILD_TESTS "Build tests" OFF) option_if_not_defined(MARL_BUILD_BENCHMARKS "Build benchmarks" OFF) option_if_not_defined(MARL_BUILD_SHARED "Build marl as a shared / dynamic library (default static)" OFF) +option_if_not_defined(MARL_USE_PTHREAD_THREAD_LOCAL "Use pthreads for thread local storage" OFF) option_if_not_defined(MARL_ASAN "Build marl with address sanitizer" OFF) option_if_not_defined(MARL_MSAN "Build marl with memory sanitizer" OFF) option_if_not_defined(MARL_TSAN "Build marl with thread sanitizer" OFF) @@ -224,6 +225,11 @@ endif() endif(MARL_WARNINGS_AS_ERRORS) + if(MARL_USE_PTHREAD_THREAD_LOCAL) + target_compile_definitions(${target} PRIVATE "MARL_USE_PTHREAD_THREAD_LOCAL=1") + target_link_libraries(${target} PUBLIC pthread) + endif() + if(MARL_ASAN) target_compile_options(${target} PUBLIC "-fsanitize=address") target_link_libraries(${target} PUBLIC "-fsanitize=address")
diff --git a/include/marl/containers.h b/include/marl/containers.h index da5b4c4..5410a7f 100644 --- a/include/marl/containers.h +++ b/include/marl/containers.h
@@ -145,15 +145,15 @@ template <typename T, int BASE_CAPACITY> vector<T, BASE_CAPACITY>::vector( - Allocator* allocator /* = Allocator::Default */) - : allocator(allocator) {} + Allocator* allocator_ /* = Allocator::Default */) + : allocator(allocator_) {} template <typename T, int BASE_CAPACITY> template <int BASE_CAPACITY_2> vector<T, BASE_CAPACITY>::vector( const vector<T, BASE_CAPACITY_2>& other, - Allocator* allocator /* = Allocator::Default */) - : allocator(allocator) { + Allocator* allocator_ /* = Allocator::Default */) + : allocator(allocator_) { *this = other; } @@ -161,8 +161,8 @@ template <int BASE_CAPACITY_2> vector<T, BASE_CAPACITY>::vector( vector<T, BASE_CAPACITY_2>&& other, - Allocator* allocator /* = Allocator::Default */) - : allocator(allocator) { + Allocator* allocator_ /* = Allocator::Default */) + : allocator(allocator_) { *this = std::move(other); } @@ -417,7 +417,7 @@ }; template <typename T> -list<T>::iterator::iterator(Entry* entry) : entry(entry) {} +list<T>::iterator::iterator(Entry* entry_) : entry(entry_) {} template <typename T> T* list<T>::iterator::operator->() { @@ -446,8 +446,8 @@ } template <typename T> -list<T>::list(Allocator* allocator /* = Allocator::Default */) - : allocator(allocator) {} +list<T>::list(Allocator* allocator_ /* = Allocator::Default */) + : allocator(allocator_) {} template <typename T> list<T>::~list() {
diff --git a/include/marl/event.h b/include/marl/event.h index afe11cc..92e1ef8 100644 --- a/include/marl/event.h +++ b/include/marl/event.h
@@ -128,8 +128,8 @@ const std::shared_ptr<Shared> shared; }; -Event::Shared::Shared(Allocator* allocator, Mode mode, bool initialState) - : cv(allocator), mode(mode), signalled(initialState) {} +Event::Shared::Shared(Allocator* allocator, Mode mode_, bool initialState) + : cv(allocator), mode(mode_), signalled(initialState) {} void Event::Shared::signal() { marl::lock lock(mutex);
diff --git a/include/marl/finally.h b/include/marl/finally.h index b8b00a5..17c9b2b 100644 --- a/include/marl/finally.h +++ b/include/marl/finally.h
@@ -28,6 +28,7 @@ #include <functional> #include <memory> +#include <utility> namespace marl { @@ -58,10 +59,10 @@ }; template <typename F> -FinallyImpl<F>::FinallyImpl(const F& func) : func(func) {} +FinallyImpl<F>::FinallyImpl(const F& func_) : func(func_) {} template <typename F> -FinallyImpl<F>::FinallyImpl(F&& func) : func(std::move(func)) {} +FinallyImpl<F>::FinallyImpl(F&& func_) : func(std::move(func_)) {} template <typename F> FinallyImpl<F>::FinallyImpl(FinallyImpl<F>&& other)
diff --git a/include/marl/memory.h b/include/marl/memory.h index d645ccb..46c67ff 100644 --- a/include/marl/memory.h +++ b/include/marl/memory.h
@@ -154,8 +154,8 @@ // Allocator::Deleter /////////////////////////////////////////////////////////////////////////////// Allocator::Deleter::Deleter() : allocator(nullptr) {} -Allocator::Deleter::Deleter(Allocator* allocator, size_t count) - : allocator(allocator), count(count) {} +Allocator::Deleter::Deleter(Allocator* allocator_, size_t count_) + : allocator(allocator_), count(count_) {} template <typename T> void Allocator::Deleter::operator()(T* object) { @@ -289,8 +289,8 @@ return out; } -TrackedAllocator::TrackedAllocator(Allocator* allocator) - : allocator(allocator) {} +TrackedAllocator::TrackedAllocator(Allocator* allocator_) + : allocator(allocator_) {} TrackedAllocator::Stats TrackedAllocator::stats() { std::unique_lock<std::mutex> lock(mutex); @@ -388,7 +388,7 @@ }; template <typename T> -StlAllocator<T>::StlAllocator(Allocator* allocator) : allocator(allocator) {} +StlAllocator<T>::StlAllocator(Allocator* allocator_) : allocator(allocator_) {} template <typename T> template <typename U>
diff --git a/include/marl/sanitizers.h b/include/marl/sanitizers.h index 6993066..3f26d4a 100644 --- a/include/marl/sanitizers.h +++ b/include/marl/sanitizers.h
@@ -78,14 +78,4 @@ #define THREAD_SANITIZER_ONLY(x) #endif // THREAD_SANITIZER_ENABLED -// The MSAN_UNPOISON macro marks uninitialized memory as initialized for MSAN. -// It can be used to suppress false-positive MSAN errors before reading -// thread-local variables. See https://github.com/google/sanitizers/issues/1265 -#if MEMORY_SANITIZER_ENABLED -#include <sanitizer/msan_interface.h> -#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size) -#else -#define MSAN_UNPOISON(p, size) -#endif - #endif // marl_sanitizers_h
diff --git a/include/marl/scheduler.h b/include/marl/scheduler.h index 48acf02..b3159b8 100644 --- a/include/marl/scheduler.h +++ b/include/marl/scheduler.h
@@ -24,6 +24,7 @@ #include "sanitizers.h" #include "task.h" #include "thread.h" +#include "thread_local.h" #include <array> #include <atomic> @@ -464,7 +465,7 @@ }; // The current worker bound to the current thread. - static thread_local Worker* current; + MARL_DECLARE_THREAD_LOCAL(Worker*, current); Mode const mode; Scheduler* const scheduler; @@ -492,7 +493,7 @@ static void setBound(Scheduler* scheduler); // The scheduler currently bound to the current thread. - static thread_local Scheduler* bound; + MARL_DECLARE_THREAD_LOCAL(Scheduler*, bound); // The immutable configuration used to build the scheduler. const Config cfg; @@ -574,7 +575,6 @@ } Scheduler::Worker* Scheduler::Worker::getCurrent() { - MSAN_UNPOISON(¤t, sizeof(Worker*)); return Worker::current; }
diff --git a/include/marl/task.h b/include/marl/task.h index b60547f..1e7d3f4 100644 --- a/include/marl/task.h +++ b/include/marl/task.h
@@ -64,10 +64,10 @@ Task::Task() {} Task::Task(const Task& o) : function(o.function), flags(o.flags) {} Task::Task(Task&& o) : function(std::move(o.function)), flags(o.flags) {} -Task::Task(const Function& function, Flags flags /* = Flags::None */) - : function(function), flags(flags) {} -Task::Task(Function&& function, Flags flags /* = Flags::None */) - : function(std::move(function)), flags(flags) {} +Task::Task(const Function& function_, Flags flags_ /* = Flags::None */) + : function(function_), flags(flags_) {} +Task::Task(Function&& function_, Flags flags_ /* = Flags::None */) + : function(std::move(function_)), flags(flags_) {} Task& Task::operator=(const Task& o) { function = o.function; flags = o.flags;
diff --git a/include/marl/thread_local.h b/include/marl/thread_local.h new file mode 100644 index 0000000..375ba5f --- /dev/null +++ b/include/marl/thread_local.h
@@ -0,0 +1,67 @@ +// Copyright 2023 The Marl Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// A wrapper around a thread_local variable, or a pthread key + +#ifndef marl_thread_local_h +#define marl_thread_local_h + +#ifdef MARL_USE_PTHREAD_THREAD_LOCAL +#include "debug.h" + +#include <pthread.h> +#include <type_traits> + +template <typename T> +class ThreadLocal { + static_assert(std::is_pointer<T>::value, + "The current implementation of ThreadLocal requires that T " + "must be a pointer"); + + public: + inline ThreadLocal(T v) { + pthread_key_create(&key, NULL); + pthread_setspecific(key, v); + } + inline ~ThreadLocal() { pthread_key_delete(key); } + inline operator T() const { return static_cast<T>(pthread_getspecific(key)); } + inline ThreadLocal& operator=(T v) { + pthread_setspecific(key, v); + return *this; + } + + private: + ThreadLocal(const ThreadLocal&) = delete; + ThreadLocal& operator=(const ThreadLocal&) = delete; + + pthread_key_t key; +}; + +#define MARL_DECLARE_THREAD_LOCAL(TYPE, NAME) static ThreadLocal<TYPE> NAME +#define MARL_INSTANTIATE_THREAD_LOCAL(TYPE, NAME, VALUE) \ + ThreadLocal<TYPE> NAME { \ + VALUE \ + } + +#else + +#define MARL_DECLARE_THREAD_LOCAL(TYPE, NAME) static thread_local TYPE NAME +#define MARL_INSTANTIATE_THREAD_LOCAL(TYPE, NAME, VALUE) \ + thread_local TYPE NAME { \ + VALUE \ + } + +#endif + +#endif // marl_thread_local_h
diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 2f32582..f5e9df0 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp
@@ -84,15 +84,13 @@ //////////////////////////////////////////////////////////////////////////////// // Scheduler //////////////////////////////////////////////////////////////////////////////// -thread_local Scheduler* Scheduler::bound = nullptr; +MARL_INSTANTIATE_THREAD_LOCAL(Scheduler*, Scheduler::bound, nullptr); Scheduler* Scheduler::get() { - MSAN_UNPOISON(&bound, sizeof(Scheduler*)); return bound; } void Scheduler::setBound(Scheduler* scheduler) { - MSAN_UNPOISON(&bound, sizeof(Scheduler*)); bound = scheduler; } @@ -354,7 +352,9 @@ //////////////////////////////////////////////////////////////////////////////// // Scheduler::Worker //////////////////////////////////////////////////////////////////////////////// -thread_local Scheduler::Worker* Scheduler::Worker::current = nullptr; +MARL_INSTANTIATE_THREAD_LOCAL(Scheduler::Worker*, + Scheduler::Worker::current, + nullptr); Scheduler::Worker::Worker(Scheduler* scheduler, Mode mode, uint32_t id) : id(id),
diff --git a/src/thread.cpp b/src/thread.cpp index 30897f0..6851d07 100644 --- a/src/thread.cpp +++ b/src/thread.cpp
@@ -332,7 +332,7 @@ void Thread::setName(const char* fmt, ...) { static auto setThreadDescription = reinterpret_cast<HRESULT(WINAPI*)(HANDLE, PCWSTR)>(GetProcAddress( - GetModuleHandle("kernelbase.dll"), "SetThreadDescription")); + GetModuleHandleA("kernelbase.dll"), "SetThreadDescription")); if (setThreadDescription == nullptr) { return; }