[clang-tools-extra] ef9aa34 - Revert "Remove the ThreadLocal template from LLVM."
Roman Lebedev via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 10 06:15:53 PST 2023
Reminder to please always mention the reason for the revert/recommit
in the commit message.
On Tue, Jan 10, 2023 at 7:22 AM Owen Anderson via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
>
>
> 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
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list