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(&current, 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;
   }