Commit 64484582 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

assume thread_local in StaticMeta

Reviewed By: Orvid

Differential Revision: D27671636

fbshipit-source-id: 82cab152ecb606235ee66c026ecafecfe52a88a5
parent 94d0da77
......@@ -76,37 +76,37 @@ StaticMetaBase::StaticMetaBase(ThreadEntry* (*threadEntry)(), bool strict)
}
ThreadEntryList* StaticMetaBase::getThreadEntryList() {
#ifdef FOLLY_TLD_USE_FOLLY_TLS
static thread_local ThreadEntryList threadEntryListSingleton;
return &threadEntryListSingleton;
#else
class PthreadKey {
public:
PthreadKey() {
int ret = pthread_key_create(&pthreadKey_, nullptr);
checkPosixError(ret, "pthread_key_create failed");
PthreadKeyUnregister::registerKey(pthreadKey_);
}
if (kUseThreadLocal) {
static thread_local ThreadEntryList threadEntryListSingleton;
return &threadEntryListSingleton;
} else {
class PthreadKey {
public:
PthreadKey() {
int ret = pthread_key_create(&pthreadKey_, nullptr);
checkPosixError(ret, "pthread_key_create failed");
PthreadKeyUnregister::registerKey(pthreadKey_);
}
FOLLY_ALWAYS_INLINE pthread_key_t get() const { return pthreadKey_; }
FOLLY_ALWAYS_INLINE pthread_key_t get() const { return pthreadKey_; }
private:
pthread_key_t pthreadKey_;
};
private:
pthread_key_t pthreadKey_;
};
auto& instance = detail::createGlobal<PthreadKey, void>();
auto& instance = detail::createGlobal<PthreadKey, void>();
ThreadEntryList* threadEntryList =
static_cast<ThreadEntryList*>(pthread_getspecific(instance.get()));
ThreadEntryList* threadEntryList =
static_cast<ThreadEntryList*>(pthread_getspecific(instance.get()));
if (UNLIKELY(!threadEntryList)) {
threadEntryList = new ThreadEntryList();
int ret = pthread_setspecific(instance.get(), threadEntryList);
checkPosixError(ret, "pthread_setspecific failed");
}
if (UNLIKELY(!threadEntryList)) {
threadEntryList = new ThreadEntryList();
int ret = pthread_setspecific(instance.get(), threadEntryList);
checkPosixError(ret, "pthread_setspecific failed");
}
return threadEntryList;
#endif
return threadEntryList;
}
}
bool StaticMetaBase::dying() {
......@@ -207,14 +207,14 @@ void StaticMetaBase::onThreadExit(void* ptr) {
tmp->setElementsCapacity(0);
}
#ifndef FOLLY_TLD_USE_FOLLY_TLS
delete tmp;
#endif
if (!kUseThreadLocal) {
delete tmp;
}
}
#ifndef FOLLY_TLD_USE_FOLLY_TLS
delete threadEntryList;
#endif
if (!kUseThreadLocal) {
delete threadEntryList;
}
}
uint32_t StaticMetaBase::elementsCapacity() const {
......
......@@ -41,18 +41,6 @@
#include <folly/synchronization/MicroSpinLock.h>
#include <folly/system/ThreadId.h>
// In general, emutls cleanup is not guaranteed to play nice with the way
// StaticMeta mixes direct pthread calls and the use of __thread. This has
// caused problems on multiple platforms so don't use __thread there.
//
// XXX: Ideally we would instead determine if emutls is in use at runtime as it
// is possible to configure glibc on Linux to use emutls regardless.
#if !FOLLY_MOBILE && !defined(__APPLE__) && !defined(_MSC_VER)
#define FOLLY_TLD_USE_FOLLY_TLS 1
#else
#undef FOLLY_TLD_USE_FOLLY_TLS
#endif
namespace folly {
enum class TLPDestructionMode { THIS_THREAD, ALL_THREADS };
......@@ -299,6 +287,14 @@ class PthreadKeyUnregister {
};
struct StaticMetaBase {
// In general, emutls cleanup is not guaranteed to play nice with the way
// StaticMeta mixes direct pthread calls and the use of __thread. This has
// caused problems on multiple platforms so don't use __thread there.
//
// XXX: Ideally we would instead determine if emutls is in use at runtime as
// it is possible to configure glibc on Linux to use emutls regardless.
static constexpr bool kUseThreadLocal = !kIsMobile && !kIsApple && !kMscVer;
// Represents an ID of a thread local object. Initially set to the maximum
// uint. This representation allows us to avoid a branch in accessing TLS data
// (because if you test capacity > id if id = maxint then the test will always
......@@ -415,13 +411,15 @@ struct FOLLY_EXPORT StaticMeta final : StaticMetaBase {
// Eliminate as many branches and as much extra code as possible in the
// cached fast path, leaving only one branch here and one indirection below.
uint32_t id = ent->getOrInvalid();
#ifdef FOLLY_TLD_USE_FOLLY_TLS
static thread_local ThreadEntry* threadEntry{};
static thread_local size_t capacity{};
#else
ThreadEntry* threadEntry{};
size_t capacity{};
#endif
static thread_local ThreadEntry* threadEntryTL{};
ThreadEntry* threadEntryNonTL{};
auto& threadEntry = kUseThreadLocal ? threadEntryTL : threadEntryNonTL;
static thread_local size_t capacityTL{};
size_t capacityNonTL{};
auto& capacity = kUseThreadLocal ? capacityTL : capacityNonTL;
if (FOLLY_UNLIKELY(capacity <= id)) {
getSlowReserveAndCache(ent, id, threadEntry, capacity);
}
......@@ -447,12 +445,12 @@ struct FOLLY_EXPORT StaticMeta final : StaticMetaBase {
static_cast<ThreadEntry*>(pthread_getspecific(key));
if (!threadEntry) {
ThreadEntryList* threadEntryList = StaticMeta::getThreadEntryList();
#ifdef FOLLY_TLD_USE_FOLLY_TLS
static thread_local ThreadEntry threadEntrySingleton;
threadEntry = &threadEntrySingleton;
#else
threadEntry = new ThreadEntry();
#endif
if (kUseThreadLocal) {
static thread_local ThreadEntry threadEntrySingleton;
threadEntry = &threadEntrySingleton;
} else {
threadEntry = new ThreadEntry();
}
// if the ThreadEntry already exists
// but pthread_getspecific returns NULL
// do not add the same entry twice to the list
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment