diff options
author | Andrew Morrow <acm@mongodb.com> | 2017-02-26 15:15:08 -0500 |
---|---|---|
committer | Andrew Morrow <acm@mongodb.com> | 2017-08-02 23:29:55 -0400 |
commit | a8a1ea3b9367adb6d0b65a7da21fed89598ea093 (patch) | |
tree | 8e969ed54b88c2a9c4c2d45a6518d053ac9f4265 /src/mongo/util | |
parent | c02c14e30d75b02894da116f4bb1a71652ead2b4 (diff) | |
download | mongo-a8a1ea3b9367adb6d0b65a7da21fed89598ea093.tar.gz |
SERVER-26538 SERVER-26539 Detach from boost::thread
Also, use thread_local everywhere for our thread specific data needs
and remove the legacy support.
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/concurrency/idle_thread_block.cpp | 3 | ||||
-rw-r--r-- | src/mongo/util/concurrency/thread_name.cpp | 7 | ||||
-rw-r--r-- | src/mongo/util/concurrency/threadlocal.h | 138 | ||||
-rw-r--r-- | src/mongo/util/fail_point.cpp | 28 | ||||
-rw-r--r-- | src/mongo/util/log.cpp | 1 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 27 | ||||
-rw-r--r-- | src/mongo/util/signal_handlers_synchronous.cpp | 7 | ||||
-rw-r--r-- | src/mongo/util/time_support.cpp | 14 |
8 files changed, 36 insertions, 189 deletions
diff --git a/src/mongo/util/concurrency/idle_thread_block.cpp b/src/mongo/util/concurrency/idle_thread_block.cpp index d81bbdecd7a..d81f920f9cb 100644 --- a/src/mongo/util/concurrency/idle_thread_block.cpp +++ b/src/mongo/util/concurrency/idle_thread_block.cpp @@ -29,12 +29,11 @@ #include "mongo/util/assert_util.h" #include "mongo/util/concurrency/idle_thread_block.h" -#include "mongo/util/concurrency/threadlocal.h" namespace mongo { namespace for_debuggers { // This needs external linkage to ensure that debuggers can use it. -MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL const char* idleThreadLocation = nullptr; +thread_local const char* idleThreadLocation = nullptr; } using for_debuggers::idleThreadLocation; diff --git a/src/mongo/util/concurrency/thread_name.cpp b/src/mongo/util/concurrency/thread_name.cpp index 2c2470a5ad5..4bf6aa71f6c 100644 --- a/src/mongo/util/concurrency/thread_name.cpp +++ b/src/mongo/util/concurrency/thread_name.cpp @@ -31,8 +31,6 @@ #include "mongo/util/concurrency/thread_name.h" -#include <boost/thread/tss.hpp> - #if defined(__APPLE__) || defined(__linux__) #include <pthread.h> #endif @@ -52,7 +50,6 @@ #include "mongo/base/init.h" #include "mongo/config.h" #include "mongo/platform/atomic_word.h" -#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" @@ -110,13 +107,13 @@ MONGO_INITIALIZER(ThreadNameInitializer)(InitializerContext*) { // TODO consider making threadName std::string and removing the size limit once we get real // thread_local. constexpr size_t kMaxThreadNameSize = 63; -MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL char threadNameStorage[kMaxThreadNameSize + 1]; +thread_local char threadNameStorage[kMaxThreadNameSize + 1]; } // namespace namespace for_debuggers { // This needs external linkage to ensure that debuggers can use it. -MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL StringData threadName; +thread_local StringData threadName; } using for_debuggers::threadName; diff --git a/src/mongo/util/concurrency/threadlocal.h b/src/mongo/util/concurrency/threadlocal.h deleted file mode 100644 index d6190bffb0f..00000000000 --- a/src/mongo/util/concurrency/threadlocal.h +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -/** -* Copyright (C) 2011 10gen Inc. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License, version 3, -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects -* for all of the code used other than as permitted herein. If you modify -* file(s) with this exception, you may extend this exception to your -* version of the file(s), but you are not obligated to do so. If you do not -* wish to do so, delete this exception statement from your version. If you -* delete this exception statement from all source files in the program, -* then also delete it in the license file. -*/ - -#include <boost/thread/tss.hpp> - -#include "mongo/config.h" - -#include "mongo/base/disallow_copying.h" - -#if defined(MONGO_CONFIG_HAVE_THREAD_LOCAL) -#define MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL thread_local -#elif defined(MONGO_CONFIG_HAVE___THREAD) -#define MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL __thread -#elif defined(MONGO_CONFIG_HAVE___DECLSPEC_THREAD) -#define MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL __declspec(thread) -#else -#error "Compiler must support trivially constructible thread local variables" -#endif - -namespace mongo { - -using boost::thread_specific_ptr; - -/** - * DEPRECATED, DO NOT USE. - * - * thread local "value" rather than a pointer - * good for things which have copy constructors (and the copy constructor is fast enough) - * e.g. - * ThreadLocalValue<int> myint; - */ -template <class T> -class ThreadLocalValue { -public: - ThreadLocalValue(T def = 0) : _default(def) {} - - T get() const { - T* val = _val.get(); - if (val) - return *val; - return _default; - } - - void set(const T& i) { - T* v = _val.get(); - if (v) { - *v = i; - return; - } - v = new T(i); - _val.reset(v); - } - - T& getRef() { - T* v = _val.get(); - if (v) { - return *v; - } - v = new T(_default); - _val.reset(v); - return *v; - } - -private: - boost::thread_specific_ptr<T> _val; - const T _default; -}; - -/** - * Emulation of a thread local storage specifier used because not all supported - * compiler toolchains support the C++11 thread_local storage class keyword. - * - * Since all supported toolchains do support a thread local storage class for - * types that are trivially constructible and destructible, we perform the - * emulation using that storage type and the machinery of boost::thread_specific_ptr to - * handle deleting the objects on thread termination. - */ -template <class T> -class TSP { - MONGO_DISALLOW_COPYING(TSP); - -public: - TSP() = default; - T* get() const; - void reset(T* v); - T* getMake() { - T* t = get(); - if (t == nullptr) - reset(t = new T()); - return t; - } - -private: - boost::thread_specific_ptr<T> tsp; -}; - -#define TSP_DECLARE(T, p) extern TSP<T> p; - -#define TSP_DEFINE(T, p) \ - MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL T* _##p; \ - TSP<T> p; \ - template <> \ - T* TSP<T>::get() const { \ - return _##p; \ - } \ - template <> \ - void TSP<T>::reset(T* v) { \ - tsp.reset(v); \ - _##p = v; \ - } -} // namespace mongo diff --git a/src/mongo/util/fail_point.cpp b/src/mongo/util/fail_point.cpp index d4d53e36835..8f85ba18f17 100644 --- a/src/mongo/util/fail_point.cpp +++ b/src/mongo/util/fail_point.cpp @@ -32,8 +32,8 @@ #include "mongo/bson/util/bson_extract.h" #include "mongo/platform/random.h" +#include "mongo/stdx/memory.h" #include "mongo/stdx/thread.h" -#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/fail_point_service.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" @@ -43,8 +43,7 @@ namespace mongo { namespace { /** - * Type representing the per-thread PRNG used by fail-points. Required because TSP_* macros, - * below, only let you create one thread-specific object per type. + * Type representing the per-thread PRNG used by fail-points. */ class FailPointPRNG { public: @@ -58,26 +57,23 @@ public: return _prng.nextInt32() & ~(1 << 31); } + static FailPointPRNG* current() { + if (!_failPointPrng) + _failPointPrng = stdx::make_unique<FailPointPRNG>(); + return _failPointPrng.get(); + } + private: PseudoRandom _prng; + static thread_local std::unique_ptr<FailPointPRNG> _failPointPrng; }; -} // namespace - - -TSP_DECLARE(FailPointPRNG, failPointPrng); -TSP_DEFINE(FailPointPRNG, failPointPrng); - -namespace { - -int32_t prngNextPositiveInt32() { - return failPointPrng.getMake()->nextPositiveInt32(); -} +thread_local std::unique_ptr<FailPointPRNG> FailPointPRNG::_failPointPrng; } // namespace void FailPoint::setThreadPRNGSeed(int32_t seed) { - failPointPrng.getMake()->resetSeed(seed); + FailPointPRNG::current()->resetSeed(seed); } FailPoint::FailPoint() : _fpInfo(0), _mode(off), _timesOrPeriod(0) {} @@ -158,7 +154,7 @@ FailPoint::RetCode FailPoint::slowShouldFailOpenBlock() { case random: { const AtomicInt32::WordType maxActivationValue = _timesOrPeriod.load(); - if (prngNextPositiveInt32() < maxActivationValue) { + if (FailPointPRNG::current()->nextPositiveInt32() < maxActivationValue) { return slowOn; } return slowOff; diff --git a/src/mongo/util/log.cpp b/src/mongo/util/log.cpp index 76bc1ac8837..7c21dccd079 100644 --- a/src/mongo/util/log.cpp +++ b/src/mongo/util/log.cpp @@ -37,7 +37,6 @@ #include "mongo/logger/rotatable_file_manager.h" #include "mongo/util/assert_util.h" #include "mongo/util/concurrency/thread_name.h" -#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/stacktrace.h" #include "mongo/util/time_support.h" diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index c5b911ca6b2..b5b379ce31a 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -33,8 +33,6 @@ #include <boost/algorithm/string.hpp> #include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/thread/recursive_mutex.hpp> -#include <boost/thread/thread.hpp> #include <iostream> #include <sstream> #include <string> @@ -48,7 +46,6 @@ #include "mongo/stdx/memory.h" #include "mongo/transport/session.h" #include "mongo/util/concurrency/mutex.h" -#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/debug_util.h" #include "mongo/util/exit.h" #include "mongo/util/log.h" @@ -189,7 +186,20 @@ const STACK_OF(X509_EXTENSION) * X509_get0_extensions(const X509* peerCert) { class SSLThreadInfo { public: static unsigned long getID() { - enforceCleanupOnShutdown(); + // NOTE: This logic is fully intentional. Because ERR_remove_state (called within + // the destructor of the kRemoveStateFromThread object) re-enters this function, + // we must have a two phase protection, otherwise we would access a thread local + // during its destruction. + static thread_local bool firstCall = false; + if (!firstCall) { + firstCall = true; + + static const thread_local struct CallErrRemoveState { + ~CallErrRemoveState() { + ERR_remove_state(0); + }; + } kRemoveStateFromThread{}; + } #ifdef _WIN32 return GetCurrentThreadId(); @@ -221,15 +231,6 @@ public: private: SSLThreadInfo() = delete; - // When called, ensures that this thread will, on termination, call ERR_remove_state. - static void enforceCleanupOnShutdown() { - static MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL bool firstCall = true; - if (firstCall) { - boost::this_thread::at_thread_exit([] { ERR_remove_state(0); }); - firstCall = false; - } - } - // Note: see SERVER-8734 for why we are using a recursive mutex here. // Once the deadlock fix in OpenSSL is incorporated into most distros of // Linux, this can be changed back to a nonrecursive mutex. diff --git a/src/mongo/util/signal_handlers_synchronous.cpp b/src/mongo/util/signal_handlers_synchronous.cpp index 8107143ef55..2331190fabc 100644 --- a/src/mongo/util/signal_handlers_synchronous.cpp +++ b/src/mongo/util/signal_handlers_synchronous.cpp @@ -48,7 +48,6 @@ #include "mongo/platform/compiler.h" #include "mongo/stdx/thread.h" #include "mongo/util/concurrency/thread_name.h" -#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/debug_util.h" #include "mongo/util/debugger.h" #include "mongo/util/exception_filter_win32.h" @@ -156,12 +155,12 @@ public: private: static stdx::mutex _streamMutex; - static MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL int terminateDepth; + static thread_local int terminateDepth; stdx::unique_lock<stdx::mutex> _lk; }; + stdx::mutex MallocFreeOStreamGuard::_streamMutex; -MONGO_TRIVIALLY_CONSTRUCTIBLE_THREAD_LOCAL -int MallocFreeOStreamGuard::terminateDepth = 0; +thread_local int MallocFreeOStreamGuard::terminateDepth = 0; // must hold MallocFreeOStreamGuard to call void writeMallocFreeStreamToLog() { diff --git a/src/mongo/util/time_support.cpp b/src/mongo/util/time_support.cpp index 7ab7a03215d..eb318a2a6cd 100644 --- a/src/mongo/util/time_support.cpp +++ b/src/mongo/util/time_support.cpp @@ -29,7 +29,6 @@ #include "mongo/util/time_support.h" -#include <boost/thread/tss.hpp> #include <cstdint> #include <cstdio> #include <iostream> @@ -82,7 +81,7 @@ bool Date_t::isFormattable() const { // jsTime_virtual_skew is just for testing. a test command manipulates it. long long jsTime_virtual_skew = 0; -boost::thread_specific_ptr<long long> jsTime_virtual_thread_skew; +thread_local long long jsTime_virtual_thread_skew = 0; using std::string; @@ -770,9 +769,6 @@ int Backoff::getNextSleepMillis(int lastSleepMillis, return lastSleepMillis; } -extern long long jsTime_virtual_skew; -extern boost::thread_specific_ptr<long long> jsTime_virtual_thread_skew; - // DO NOT TOUCH except for testing void jsTimeVirtualSkew(long long skew) { jsTime_virtual_skew = skew; @@ -782,13 +778,11 @@ long long getJSTimeVirtualSkew() { } void jsTimeVirtualThreadSkew(long long skew) { - jsTime_virtual_thread_skew.reset(new long long(skew)); + jsTime_virtual_thread_skew = skew; } + long long getJSTimeVirtualThreadSkew() { - if (jsTime_virtual_thread_skew.get()) { - return *(jsTime_virtual_thread_skew.get()); - } else - return 0; + return jsTime_virtual_thread_skew; } /** Date_t is milliseconds since epoch */ |