This has been obsoleted by C++ thread_local for a long time.
As far as I know, Xcode was the last supported toolchain to add
support for C++ thread_local in 2016.
As a precaution, use LLVM_THREAD_LOCAL which provides even greater
backwards compatibility, allowing this to function even pre-C++11
versions of GCC.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D141349
//===----------------------------------------------------------------------===//
#include "support/ThreadCrashReporter.h"
-#include "llvm/Support/ThreadLocal.h"
#include <atomic>
namespace clang {
+++ /dev/null
-//===- 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
Program.cpp
RWMutex.cpp
Signals.cpp
- ThreadLocal.cpp
Threading.cpp
Valgrind.cpp
Watchdog.cpp
#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 <cassert>
#include <mutex>
#include <setjmp.h>
namespace {
struct CrashRecoveryContextImpl;
-
-sys::ThreadLocal<const CrashRecoveryContextImpl> &getCurrentContext() {
- static sys::ThreadLocal<const CrashRecoveryContextImpl> CurrentContext;
- return CurrentContext;
-}
+static LLVM_THREAD_LOCAL const CrashRecoveryContextImpl *CurrentContext;
struct CrashRecoveryContextImpl {
// When threads are disabled, this links up all active
public:
CrashRecoveryContextImpl(CrashRecoveryContext *CRC) noexcept
: CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) {
- Next = getCurrentContext().get();
- getCurrentContext().set(this);
+ Next = CurrentContext;
+ CurrentContext = this;
}
~CrashRecoveryContextImpl() {
if (!SwitchedThread)
- getCurrentContext().set(Next);
+ CurrentContext = Next;
}
/// Called when the separate crash-recovery thread was finished, to
void HandleCrash(int RetCode, uintptr_t Context) {
// Eliminate the current context entry, to avoid re-entering in case the
// cleanup code crashes.
- getCurrentContext().set(Next);
+ CurrentContext = Next;
assert(!Failed && "Crash recovery context already failed!");
Failed = true;
static bool gCrashRecoveryEnabled = false;
-sys::ThreadLocal<const CrashRecoveryContext> &getIsRecoveringFromCrash() {
- static sys::ThreadLocal<const CrashRecoveryContext> IsRecoveringFromCrash;
- return IsRecoveringFromCrash;
-}
+static LLVM_THREAD_LOCAL const CrashRecoveryContext *IsRecoveringFromCrash;
} // namespace
CrashRecoveryContext::~CrashRecoveryContext() {
// Reclaim registered resources.
CrashRecoveryContextCleanup *i = head;
- const CrashRecoveryContext *PC = getIsRecoveringFromCrash().get();
- getIsRecoveringFromCrash().set(this);
+ const CrashRecoveryContext *PC = IsRecoveringFromCrash;
+ IsRecoveringFromCrash = this;
while (i) {
CrashRecoveryContextCleanup *tmp = i;
i = tmp->next;
tmp->recoverResources();
delete tmp;
}
- getIsRecoveringFromCrash().set(PC);
+ IsRecoveringFromCrash = PC;
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
delete CRCI;
}
bool CrashRecoveryContext::isRecoveringFromCrash() {
- return getIsRecoveringFromCrash().get() != nullptr;
+ return IsRecoveringFromCrash != nullptr;
}
CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
if (!gCrashRecoveryEnabled)
return nullptr;
- const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
+ const CrashRecoveryContextImpl *CRCI = CurrentContext;
if (!CRCI)
return nullptr;
// occur inside the __except evaluation block
static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
// Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
+ const CrashRecoveryContextImpl *CRCI = CurrentContext;
if (!CRCI) {
// Something has gone horribly wrong, so let's just tell everyone
}
// Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
+ const CrashRecoveryContextImpl *CRCI = CurrentContext;
if (!CRCI) {
// Something has gone horribly wrong, so let's just tell everyone
static void CrashRecoverySignalHandler(int Signal) {
// Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = getCurrentContext().get();
+ const CrashRecoveryContextImpl *CRCI = CurrentContext;
if (!CRCI) {
// We didn't find a crash recovery context -- this means either we got a
+++ /dev/null
-//===- 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
+++ /dev/null
-//=== 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
+++ /dev/null
-//= 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
SymbolRemappingReaderTest.cpp
TarWriterTest.cpp
TaskQueueTest.cpp
- ThreadLocalTest.cpp
ThreadPool.cpp
Threading.cpp
TimerTest.cpp
+++ /dev/null
-//===- 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());
-}
-
-}
#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