X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fdetail%2FThreadLocalDetail.h;h=6769410be67e6ff3b4d6317abc5727330f488963;hb=320a9600f9cb11bbfd3f17dc99cb7b252132eb37;hp=0c05802c63804b1d75419ee082282cbc7b7d5be8;hpb=81fa7fd7ac3de80e645dae5243987f05049627b5;p=folly.git diff --git a/folly/detail/ThreadLocalDetail.h b/folly/detail/ThreadLocalDetail.h index 0c05802c..6769410b 100644 --- a/folly/detail/ThreadLocalDetail.h +++ b/folly/detail/ThreadLocalDetail.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,18 @@ #include #include +// 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 !__APPLE__ && !__ANDROID__ +#define FOLLY_TLD_USE_FOLLY_TLS 1 +#else +#undef FOLLY_TLD_USE_FOLLY_TLS +#endif + namespace folly { namespace threadlocal_detail { @@ -166,8 +178,8 @@ struct StaticMeta { return *inst_; } - int nextId_; - std::vector freeIds_; + uint32_t nextId_; + std::vector freeIds_; std::mutex lock_; pthread_key_t pthreadKey_; ThreadEntry head_; @@ -185,7 +197,7 @@ struct StaticMeta { t->next = t->prev = t; } -#if !__APPLE__ +#ifdef FOLLY_TLD_USE_FOLLY_TLS static FOLLY_TLS ThreadEntry threadEntry_; #endif static StaticMeta* inst_; @@ -195,14 +207,18 @@ struct StaticMeta { int ret = pthread_key_create(&pthreadKey_, &onThreadExit); checkPosixError(ret, "pthread_key_create failed"); - // pthread_atfork is not part of the Android NDK at least as of n9d. If - // something is trying to call native fork() directly at all with Android's - // process management model, this is probably the least of the problems. -#if !__ANDROID__ +#if FOLLY_HAVE_PTHREAD_ATFORK ret = pthread_atfork(/*prepare*/ &StaticMeta::preFork, /*parent*/ &StaticMeta::onForkParent, /*child*/ &StaticMeta::onForkChild); checkPosixError(ret, "pthread_atfork failed"); +#elif !__ANDROID__ + // pthread_atfork is not part of the Android NDK at least as of n9d. If + // something is trying to call native fork() directly at all with Android's + // process management model, this is probably the least of the problems. + // + // But otherwise, this is a problem. + #warning pthread_atfork unavailable #endif } ~StaticMeta() { @@ -210,7 +226,7 @@ struct StaticMeta { } static ThreadEntry* getThreadEntry() { -#if !__APPLE__ +#ifdef FOLLY_TLD_USE_FOLLY_TLS return &threadEntry_; #else ThreadEntry* threadEntry = @@ -245,7 +261,7 @@ struct StaticMeta { static void onThreadExit(void* ptr) { auto& meta = instance(); -#if !__APPLE__ +#ifdef FOLLY_TLD_USE_FOLLY_TLS ThreadEntry* threadEntry = getThreadEntry(); DCHECK_EQ(ptr, &meta); @@ -275,14 +291,14 @@ struct StaticMeta { threadEntry->elements = nullptr; pthread_setspecific(meta.pthreadKey_, nullptr); -#if __APPLE__ - // Allocated in getThreadEntry(); free it +#ifndef FOLLY_TLD_USE_FOLLY_TLS + // Allocated in getThreadEntry() when not using folly TLS; free it delete threadEntry; #endif } - static int create() { - int id; + static uint32_t create() { + uint32_t id; auto & meta = instance(); std::lock_guard g(meta.lock_); if (!meta.freeIds_.empty()) { @@ -294,7 +310,7 @@ struct StaticMeta { return id; } - static void destroy(size_t id) { + static void destroy(uint32_t id) { try { auto & meta = instance(); // Elements in other threads that use this id. @@ -336,7 +352,7 @@ struct StaticMeta { * Reserve enough space in the ThreadEntry::elements for the item * @id to fit in. */ - static void reserve(int id) { + static void reserve(uint32_t id) { auto& meta = instance(); ThreadEntry* threadEntry = getThreadEntry(); size_t prevCapacity = threadEntry->elementsCapacity; @@ -415,14 +431,14 @@ struct StaticMeta { free(reallocated); -#if !__APPLE__ +#ifdef FOLLY_TLD_USE_FOLLY_TLS if (prevCapacity == 0) { pthread_setspecific(meta.pthreadKey_, &meta); } #endif } - static ElementWrapper& get(size_t id) { + static ElementWrapper& get(uint32_t id) { ThreadEntry* threadEntry = getThreadEntry(); if (UNLIKELY(threadEntry->elementsCapacity <= id)) { reserve(id); @@ -432,7 +448,7 @@ struct StaticMeta { } }; -#if !__APPLE__ +#ifdef FOLLY_TLD_USE_FOLLY_TLS template FOLLY_TLS ThreadEntry StaticMeta::threadEntry_{nullptr, 0, nullptr, nullptr};