[llvm] ef9aa34 - Revert "Remove the ThreadLocal template from LLVM."
Owen Anderson via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 9 20:22:16 PST 2023
Author: Owen Anderson
Date: 2023-01-09T21:21:38-07:00
New Revision: ef9aa34f0274cdbfa82c47f8ab99f02679fd0d13
URL: https://github.com/llvm/llvm-project/commit/ef9aa34f0274cdbfa82c47f8ab99f02679fd0d13
DIFF: https://github.com/llvm/llvm-project/commit/ef9aa34f0274cdbfa82c47f8ab99f02679fd0d13.diff
LOG: Revert "Remove the ThreadLocal template from LLVM."
This reverts commit 54d78b639b9c18b42abd4fac5c6e76105f06b3ef.
Added:
llvm/include/llvm/Support/ThreadLocal.h
llvm/lib/Support/ThreadLocal.cpp
llvm/lib/Support/Unix/ThreadLocal.inc
llvm/lib/Support/Windows/ThreadLocal.inc
llvm/unittests/Support/ThreadLocalTest.cpp
Modified:
clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
llvm/lib/Support/CMakeLists.txt
llvm/lib/Support/CrashRecoveryContext.cpp
llvm/unittests/Support/CMakeLists.txt
mlir/include/mlir/Support/ThreadLocalCache.h
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/support/ThreadCrashReporter.cpp b/clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
index 9551bbfda43c1..05afb3b25f28e 100644
--- a/clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
+++ b/clang-tools-extra/clangd/support/ThreadCrashReporter.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "support/ThreadCrashReporter.h"
+#include "llvm/Support/ThreadLocal.h"
#include <atomic>
namespace clang {
diff --git a/llvm/include/llvm/Support/ThreadLocal.h b/llvm/include/llvm/Support/ThreadLocal.h
new file mode 100644
index 0000000000000..d6838c15fc345
--- /dev/null
+++ b/llvm/include/llvm/Support/ThreadLocal.h
@@ -0,0 +1,62 @@
+//===- llvm/Support/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_THREADLOCAL_H
+#define LLVM_SUPPORT_THREADLOCAL_H
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Threading.h"
+#include <cassert>
+
+namespace llvm {
+ namespace sys {
+ // ThreadLocalImpl - Common base class of all ThreadLocal instantiations.
+ // YOU SHOULD NEVER USE THIS DIRECTLY.
+ class ThreadLocalImpl {
+ typedef uint64_t ThreadLocalDataTy;
+ /// Platform-specific thread local data.
+ ///
+ /// This is embedded in the class and we avoid malloc'ing/free'ing it,
+ /// to make this class more safe for use along with CrashRecoveryContext.
+ union {
+ char data[sizeof(ThreadLocalDataTy)];
+ ThreadLocalDataTy align_data;
+ };
+ public:
+ ThreadLocalImpl();
+ virtual ~ThreadLocalImpl();
+ void setInstance(const void* d);
+ void *getInstance();
+ void removeInstance();
+ };
+
+ /// ThreadLocal - A class used to abstract thread-local storage. It holds,
+ /// for each thread, a pointer a single object of type T.
+ template<class T>
+ class ThreadLocal : public ThreadLocalImpl {
+ public:
+ ThreadLocal() : ThreadLocalImpl() { }
+
+ /// get - Fetches a pointer to the object associated with the current
+ /// thread. If no object has yet been associated, it returns NULL;
+ T* get() { return static_cast<T*>(getInstance()); }
+
+ // set - Associates a pointer to an object with the current thread.
+ void set(T* d) { setInstance(d); }
+
+ // erase - Removes the pointer associated with the current thread.
+ void erase() { removeInstance(); }
+ };
+ }
+}
+
+#endif
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 9b5402fa54f0f..46469c6e9e624 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -260,6 +260,7 @@ add_llvm_component_library(LLVMSupport
Program.cpp
RWMutex.cpp
Signals.cpp
+ ThreadLocal.cpp
Threading.cpp
Valgrind.cpp
Watchdog.cpp
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index 9e792d1f51777..c7c384c9edc22 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -11,6 +11,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ExitCodes.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/ThreadLocal.h"
#include "llvm/Support/thread.h"
#include <mutex>
#include <setjmp.h>
@@ -20,7 +21,11 @@ using namespace llvm;
namespace {
struct CrashRecoveryContextImpl;
-LLVM_THREAD_LOCAL static const CrashRecoveryContextImpl *CurrentContext;
+
+sys::ThreadLocal<const CrashRecoveryContextImpl> &getCurrentContext() {
+ static sys::ThreadLocal<const CrashRecoveryContextImpl> CurrentContext;
+ return CurrentContext;
+}
struct CrashRecoveryContextImpl {
// When threads are disabled, this links up all active
@@ -38,12 +43,12 @@ struct CrashRecoveryContextImpl {
public:
CrashRecoveryContextImpl(CrashRecoveryContext *CRC) noexcept
: CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) {
- Next = CurrentContext;
- CurrentContext = this;
+ Next = getCurrentContext().get();
+ getCurrentContext().set(this);
}
~CrashRecoveryContextImpl() {
if (!SwitchedThread)
- CurrentContext = Next;
+ getCurrentContext().set(Next);
}
/// Called when the separate crash-recovery thread was finished, to
@@ -61,7 +66,7 @@ struct CrashRecoveryContextImpl {
void HandleCrash(int RetCode, uintptr_t Context) {
// Eliminate the current context entry, to avoid re-entering in case the
// cleanup code crashes.
- CurrentContext = Next;
+ getCurrentContext().set(Next);
assert(!Failed && "Crash recovery context already failed!");
Failed = true;
@@ -87,7 +92,10 @@ std::mutex &getCrashRecoveryContextMutex() {
static bool gCrashRecoveryEnabled = false;
-LLVM_THREAD_LOCAL static const CrashRecoveryContext *IsRecoveringFromCrash;
+sys::ThreadLocal<const CrashRecoveryContext> &getIsRecoveringFromCrash() {
+ static sys::ThreadLocal<const CrashRecoveryContext> IsRecoveringFromCrash;
+ return IsRecoveringFromCrash;
+}
} // namespace
@@ -106,8 +114,8 @@ CrashRecoveryContext::CrashRecoveryContext() {
CrashRecoveryContext::~CrashRecoveryContext() {
// Reclaim registered resources.
CrashRecoveryContextCleanup *i = head;
- const CrashRecoveryContext *PC = IsRecoveringFromCrash;
- IsRecoveringFromCrash = this;
+ const CrashRecoveryContext *PC = getIsRecoveringFromCrash().get();
+ getIsRecoveringFromCrash().set(this);
while (i) {
CrashRecoveryContextCleanup *tmp = i;
i = tmp->next;
@@ -115,21 +123,21 @@ CrashRecoveryContext::~CrashRecoveryContext() {
tmp->recoverResources();
delete tmp;
}
- IsRecoveringFromCrash = PC;
+ getIsRecoveringFromCrash().set(PC);
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
delete CRCI;
}
bool CrashRecoveryContext::isRecoveringFromCrash() {
- return IsRecoveringFromCrash != nullptr;
+ return getIsRecoveringFromCrash().get() != nullptr;
}
CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
if (!gCrashRecoveryEnabled)
return nullptr;
- const CrashRecoveryContextImpl *CRCI = CurrentContext;
+ const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
if (!CRCI)
return nullptr;
@@ -199,7 +207,7 @@ static void uninstallExceptionOrSignalHandlers() {}
// occur inside the __except evaluation block
static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
// Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = CurrentContext;
+ const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
if (!CRCI) {
// Something has gone horribly wrong, so let's just tell everyone
@@ -276,7 +284,7 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
}
// Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = CurrentContext;
+ const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
if (!CRCI) {
// Something has gone horribly wrong, so let's just tell everyone
@@ -350,7 +358,7 @@ static struct sigaction PrevActions[NumSignals];
static void CrashRecoverySignalHandler(int Signal) {
// Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = CurrentContext;
+ const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
if (!CRCI) {
// We didn't find a crash recovery context -- this means either we got a
diff --git a/llvm/lib/Support/ThreadLocal.cpp b/llvm/lib/Support/ThreadLocal.cpp
new file mode 100644
index 0000000000000..44e6223cf17b6
--- /dev/null
+++ b/llvm/lib/Support/ThreadLocal.cpp
@@ -0,0 +1,47 @@
+//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the llvm::sys::ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadLocal.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Compiler.h"
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+// Define all methods as no-ops if threading is explicitly disabled
+namespace llvm {
+using namespace sys;
+ThreadLocalImpl::ThreadLocalImpl() : data() { }
+ThreadLocalImpl::~ThreadLocalImpl() { }
+void ThreadLocalImpl::setInstance(const void* d) {
+ static_assert(sizeof(d) <= sizeof(data), "size too big");
+ void **pd = reinterpret_cast<void**>(&data);
+ *pd = const_cast<void*>(d);
+}
+void *ThreadLocalImpl::getInstance() {
+ void **pd = reinterpret_cast<void**>(&data);
+ return *pd;
+}
+void ThreadLocalImpl::removeInstance() {
+ setInstance(nullptr);
+}
+}
+#elif defined(LLVM_ON_UNIX)
+#include "Unix/ThreadLocal.inc"
+#elif defined( _WIN32)
+#include "Windows/ThreadLocal.inc"
+#else
+#warning Neither LLVM_ON_UNIX nor _WIN32 set in Support/ThreadLocal.cpp
+#endif
diff --git a/llvm/lib/Support/Unix/ThreadLocal.inc b/llvm/lib/Support/Unix/ThreadLocal.inc
new file mode 100644
index 0000000000000..483c5b0d324e1
--- /dev/null
+++ b/llvm/lib/Support/Unix/ThreadLocal.inc
@@ -0,0 +1,57 @@
+//=== llvm/Support/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Unix specific (non-pthread) ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace llvm {
+using namespace sys;
+
+ThreadLocalImpl::ThreadLocalImpl() : data() {
+ static_assert(sizeof(pthread_key_t) <= sizeof(data), "size too big");
+ pthread_key_t *key = reinterpret_cast<pthread_key_t *>(&data);
+ int errorcode = pthread_key_create(key, nullptr);
+ assert(errorcode == 0);
+ (void)errorcode;
+}
+
+ThreadLocalImpl::~ThreadLocalImpl() {
+ pthread_key_t *key = reinterpret_cast<pthread_key_t *>(&data);
+ int errorcode = pthread_key_delete(*key);
+ assert(errorcode == 0);
+ (void)errorcode;
+}
+
+void ThreadLocalImpl::setInstance(const void *d) {
+ pthread_key_t *key = reinterpret_cast<pthread_key_t *>(&data);
+ int errorcode = pthread_setspecific(*key, d);
+ assert(errorcode == 0);
+ (void)errorcode;
+}
+
+void *ThreadLocalImpl::getInstance() {
+ pthread_key_t *key = reinterpret_cast<pthread_key_t *>(&data);
+ return pthread_getspecific(*key);
+}
+
+void ThreadLocalImpl::removeInstance() { setInstance(nullptr); }
+
+} // namespace llvm
diff --git a/llvm/lib/Support/Windows/ThreadLocal.inc b/llvm/lib/Support/Windows/ThreadLocal.inc
new file mode 100644
index 0000000000000..900444d11b25c
--- /dev/null
+++ b/llvm/lib/Support/Windows/ThreadLocal.inc
@@ -0,0 +1,50 @@
+//= llvm/Support/Win32/ThreadLocal.inc - Win32 Thread Local Data -*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 specific (non-pthread) ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadLocal.h"
+#include "llvm/Support/Windows/WindowsSupport.h"
+
+namespace llvm {
+
+sys::ThreadLocalImpl::ThreadLocalImpl() : data() {
+ static_assert(sizeof(DWORD) <= sizeof(data), "size too big");
+ DWORD *tls = reinterpret_cast<DWORD *>(&data);
+ *tls = TlsAlloc();
+ assert(*tls != TLS_OUT_OF_INDEXES);
+}
+
+sys::ThreadLocalImpl::~ThreadLocalImpl() {
+ DWORD *tls = reinterpret_cast<DWORD *>(&data);
+ TlsFree(*tls);
+}
+
+void *sys::ThreadLocalImpl::getInstance() {
+ DWORD *tls = reinterpret_cast<DWORD *>(&data);
+ return TlsGetValue(*tls);
+}
+
+void sys::ThreadLocalImpl::setInstance(const void *d) {
+ DWORD *tls = reinterpret_cast<DWORD *>(&data);
+ int errorcode = TlsSetValue(*tls, const_cast<void *>(d));
+ assert(errorcode != 0);
+ (void)errorcode;
+}
+
+void sys::ThreadLocalImpl::removeInstance() { setInstance(0); }
+
+} // namespace llvm
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index d987d65db13ea..ccffb42e267eb 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -80,6 +80,7 @@ add_llvm_unittest(SupportTests
SymbolRemappingReaderTest.cpp
TarWriterTest.cpp
TaskQueueTest.cpp
+ ThreadLocalTest.cpp
ThreadPool.cpp
Threading.cpp
TimerTest.cpp
diff --git a/llvm/unittests/Support/ThreadLocalTest.cpp b/llvm/unittests/Support/ThreadLocalTest.cpp
new file mode 100644
index 0000000000000..454e4f21a05fe
--- /dev/null
+++ b/llvm/unittests/Support/ThreadLocalTest.cpp
@@ -0,0 +1,54 @@
+//===- llvm/unittest/Support/ThreadLocalTest.cpp - ThreadLocal tests ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadLocal.h"
+#include "gtest/gtest.h"
+#include <type_traits>
+
+using namespace llvm;
+using namespace sys;
+
+namespace {
+
+class ThreadLocalTest : public ::testing::Test {
+};
+
+struct S {
+ int i;
+};
+
+TEST_F(ThreadLocalTest, Basics) {
+ ThreadLocal<const S> x;
+
+ static_assert(std::is_const_v<std::remove_pointer_t<decltype(x.get())>>,
+ "ThreadLocal::get didn't return a pointer to const object");
+
+ EXPECT_EQ(nullptr, x.get());
+
+ S s;
+ x.set(&s);
+ EXPECT_EQ(&s, x.get());
+
+ x.erase();
+ EXPECT_EQ(nullptr, x.get());
+
+ ThreadLocal<S> y;
+
+ static_assert(!std::is_const_v<std::remove_pointer_t<decltype(y.get())>>,
+ "ThreadLocal::get returned a pointer to const object");
+
+ EXPECT_EQ(nullptr, y.get());
+
+ y.set(&s);
+ EXPECT_EQ(&s, y.get());
+
+ y.erase();
+ EXPECT_EQ(nullptr, y.get());
+}
+
+}
diff --git a/mlir/include/mlir/Support/ThreadLocalCache.h b/mlir/include/mlir/Support/ThreadLocalCache.h
index e98fae6b117ae..083956b717422 100644
--- a/mlir/include/mlir/Support/ThreadLocalCache.h
+++ b/mlir/include/mlir/Support/ThreadLocalCache.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/ThreadLocal.h"
namespace mlir {
/// This class provides support for defining a thread local object with non
More information about the llvm-commits
mailing list