From c63fe6c3e358c81a3e5458c16410191e93ceb6f5 Mon Sep 17 00:00:00 2001 From: Christopher Dykes Date: Fri, 1 Apr 2016 11:16:57 -0700 Subject: [PATCH] Create the pthread.h portability header Summary: The primary issue is that the pthread implementation we use for Windows defines `pthread_t` as a struct (yes, it is allowed to do this), which breaks a lot of things. Reviewed By: yfeldblum Differential Revision: D2862671 fb-gh-sync-id: 551569b6a9e2e374cf77e186e148b6b397f8f25f fbshipit-source-id: 551569b6a9e2e374cf77e186e148b6b397f8f25f --- folly/Conv.h | 11 ++++ folly/Makefile.am | 1 + folly/io/async/EventBase.cpp | 6 +- folly/io/async/NotificationQueue.h | 14 ++--- folly/io/async/SSLContext.cpp | 2 + folly/portability/PThread.h | 94 ++++++++++++++++++++++++++++++ 6 files changed, 117 insertions(+), 11 deletions(-) create mode 100755 folly/portability/PThread.h diff --git a/folly/Conv.h b/folly/Conv.h index eeeb3847..b730857b 100644 --- a/folly/Conv.h +++ b/folly/Conv.h @@ -792,6 +792,17 @@ toAppend(const Ts&... vs) { ::folly::detail::toAppendStrImpl(vs...); } +#ifdef _MSC_VER +// Special case pid_t on MSVC, because it's a void* rather than an +// integral type. We can't do a global special case because this is already +// dangerous enough (as most pointers will implicitly convert to a void*) +// just doing it for MSVC. +template +void toAppend(const pid_t a, Tgt* res) { + toAppend(uint64_t(a), res); +} +#endif + /** * Special version of the call that preallocates exaclty as much memory * as need for arguments to be stored in target. This means we are diff --git a/folly/Makefile.am b/folly/Makefile.am index 44d109c3..3ea8c30a 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -275,6 +275,7 @@ nobase_follyinclude_HEADERS = \ portability/IOVec.h \ portability/Malloc.h \ portability/Memory.h \ + portability/PThread.h \ portability/String.h \ portability/Strings.h \ portability/SysFile.h \ diff --git a/folly/io/async/EventBase.cpp b/folly/io/async/EventBase.cpp index 5dcc9967..1e0c808d 100644 --- a/folly/io/async/EventBase.cpp +++ b/folly/io/async/EventBase.cpp @@ -132,7 +132,7 @@ static std::mutex libevent_mutex_; EventBase::EventBase(bool enableTimeMeasurement) : runOnceCallbacks_(nullptr) , stop_(false) - , loopThread_(0) + , loopThread_() , queue_(nullptr) , fnRunner_(nullptr) , maxLatency_(0) @@ -177,7 +177,7 @@ EventBase::EventBase(bool enableTimeMeasurement) EventBase::EventBase(event_base* evb, bool enableTimeMeasurement) : runOnceCallbacks_(nullptr) , stop_(false) - , loopThread_(0) + , loopThread_() , evb_(evb) , queue_(nullptr) , fnRunner_(nullptr) @@ -426,7 +426,7 @@ bool EventBase::loopBody(int flags) { return false; } - loopThread_.store(0, std::memory_order_release); + loopThread_.store({}, std::memory_order_release); VLOG(5) << "EventBase(): Done with loop."; return true; diff --git a/folly/io/async/NotificationQueue.h b/folly/io/async/NotificationQueue.h index 5afba047..58a3a821 100644 --- a/folly/io/async/NotificationQueue.h +++ b/folly/io/async/NotificationQueue.h @@ -240,11 +240,11 @@ class NotificationQueue { #else FdType fdType = FdType::PIPE) #endif - : eventfd_(-1), - pipeFds_{-1, -1}, - advisoryMaxQueueSize_(maxSize), - pid_(getpid()), - queue_() { + : eventfd_(-1), + pipeFds_{-1, -1}, + advisoryMaxQueueSize_(maxSize), + pid_(pid_t(getpid())), + queue_() { RequestContext::saveContext(); @@ -438,9 +438,7 @@ class NotificationQueue { * check ensures that we catch the problem in the misbehaving child process * code, and crash before signalling the parent process. */ - void checkPid() const { - CHECK_EQ(pid_, getpid()); - } + void checkPid() const { CHECK_EQ(pid_, pid_t(getpid())); } private: // Forbidden copy constructor and assignment operator diff --git a/folly/io/async/SSLContext.cpp b/folly/io/async/SSLContext.cpp index ac032da2..c4f052b8 100644 --- a/folly/io/async/SSLContext.cpp +++ b/folly/io/async/SSLContext.cpp @@ -696,6 +696,8 @@ static unsigned long callbackThreadID() { return static_cast( #ifdef __APPLE__ pthread_mach_thread_np(pthread_self()) +#elif _MSC_VER + pthread_getw32threadid_np(pthread_self()) #else pthread_self() #endif diff --git a/folly/portability/PThread.h b/folly/portability/PThread.h new file mode 100755 index 00000000..4bfecef7 --- /dev/null +++ b/folly/portability/PThread.h @@ -0,0 +1,94 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#ifdef _WIN32 +// We implement a sane comparison operand for +// pthread_t and an integer so that it may be +// compared against 0. + +inline bool operator==(pthread_t ptA, unsigned int b) { + if (ptA.p == nullptr) { + return b == 0; + } + return pthread_getw32threadid_np(ptA) == b; +} + +inline bool operator!=(pthread_t ptA, unsigned int b) { + if (ptA.p == nullptr) { + return b != 0; + } + return pthread_getw32threadid_np(ptA) != b; +} + +inline bool operator==(pthread_t ptA, pthread_t ptB) { + return pthread_equal(ptA, ptB) != 0; +} + +inline bool operator!=(pthread_t ptA, pthread_t ptB) { + return pthread_equal(ptA, ptB) == 0; +} + +inline bool operator<(pthread_t ptA, pthread_t ptB) { + return ptA.p < ptB.p; +} + +inline bool operator!(pthread_t ptA) { + return ptA == 0; +} + +inline int pthread_attr_getstack( + pthread_attr_t* attr, + void** stackaddr, + size_t* stacksize) { + if (pthread_attr_getstackaddr(attr, stackaddr) != 0) { + return -1; + } + if (pthread_attr_getstacksize(attr, stacksize) != 0) { + return -1; + } + return 0; +} + +inline int +pthread_attr_setstack(pthread_attr_t* attr, void* stackaddr, size_t stacksize) { + if (pthread_attr_setstackaddr(attr, stackaddr) != 0) { + return -1; + } + if (pthread_attr_setstacksize(attr, stacksize) != 0) { + return -1; + } + return 0; +} + +inline int pthread_attr_getguardsize(pthread_attr_t* attr, size_t* guardsize) { + *guardsize = 0; + return 0; +} + +#include +namespace std { +template <> +struct hash { + std::size_t operator()(const pthread_t& k) const { + return 0 ^ std::hash(k.p) ^ std::hash(k.x); + } +}; +} +#endif -- 2.34.1