[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