Commit c63fe6c3 authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot 8

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
parent 9ab69bc7
...@@ -792,6 +792,17 @@ toAppend(const Ts&... vs) { ...@@ -792,6 +792,17 @@ toAppend(const Ts&... vs) {
::folly::detail::toAppendStrImpl(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 <class Tgt>
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 * Special version of the call that preallocates exaclty as much memory
* as need for arguments to be stored in target. This means we are * as need for arguments to be stored in target. This means we are
......
...@@ -275,6 +275,7 @@ nobase_follyinclude_HEADERS = \ ...@@ -275,6 +275,7 @@ nobase_follyinclude_HEADERS = \
portability/IOVec.h \ portability/IOVec.h \
portability/Malloc.h \ portability/Malloc.h \
portability/Memory.h \ portability/Memory.h \
portability/PThread.h \
portability/String.h \ portability/String.h \
portability/Strings.h \ portability/Strings.h \
portability/SysFile.h \ portability/SysFile.h \
......
...@@ -132,7 +132,7 @@ static std::mutex libevent_mutex_; ...@@ -132,7 +132,7 @@ static std::mutex libevent_mutex_;
EventBase::EventBase(bool enableTimeMeasurement) EventBase::EventBase(bool enableTimeMeasurement)
: runOnceCallbacks_(nullptr) : runOnceCallbacks_(nullptr)
, stop_(false) , stop_(false)
, loopThread_(0) , loopThread_()
, queue_(nullptr) , queue_(nullptr)
, fnRunner_(nullptr) , fnRunner_(nullptr)
, maxLatency_(0) , maxLatency_(0)
...@@ -177,7 +177,7 @@ EventBase::EventBase(bool enableTimeMeasurement) ...@@ -177,7 +177,7 @@ EventBase::EventBase(bool enableTimeMeasurement)
EventBase::EventBase(event_base* evb, bool enableTimeMeasurement) EventBase::EventBase(event_base* evb, bool enableTimeMeasurement)
: runOnceCallbacks_(nullptr) : runOnceCallbacks_(nullptr)
, stop_(false) , stop_(false)
, loopThread_(0) , loopThread_()
, evb_(evb) , evb_(evb)
, queue_(nullptr) , queue_(nullptr)
, fnRunner_(nullptr) , fnRunner_(nullptr)
...@@ -426,7 +426,7 @@ bool EventBase::loopBody(int flags) { ...@@ -426,7 +426,7 @@ bool EventBase::loopBody(int flags) {
return false; return false;
} }
loopThread_.store(0, std::memory_order_release); loopThread_.store({}, std::memory_order_release);
VLOG(5) << "EventBase(): Done with loop."; VLOG(5) << "EventBase(): Done with loop.";
return true; return true;
......
...@@ -240,11 +240,11 @@ class NotificationQueue { ...@@ -240,11 +240,11 @@ class NotificationQueue {
#else #else
FdType fdType = FdType::PIPE) FdType fdType = FdType::PIPE)
#endif #endif
: eventfd_(-1), : eventfd_(-1),
pipeFds_{-1, -1}, pipeFds_{-1, -1},
advisoryMaxQueueSize_(maxSize), advisoryMaxQueueSize_(maxSize),
pid_(getpid()), pid_(pid_t(getpid())),
queue_() { queue_() {
RequestContext::saveContext(); RequestContext::saveContext();
...@@ -438,9 +438,7 @@ class NotificationQueue { ...@@ -438,9 +438,7 @@ class NotificationQueue {
* check ensures that we catch the problem in the misbehaving child process * check ensures that we catch the problem in the misbehaving child process
* code, and crash before signalling the parent process. * code, and crash before signalling the parent process.
*/ */
void checkPid() const { void checkPid() const { CHECK_EQ(pid_, pid_t(getpid())); }
CHECK_EQ(pid_, getpid());
}
private: private:
// Forbidden copy constructor and assignment operator // Forbidden copy constructor and assignment operator
......
...@@ -696,6 +696,8 @@ static unsigned long callbackThreadID() { ...@@ -696,6 +696,8 @@ static unsigned long callbackThreadID() {
return static_cast<unsigned long>( return static_cast<unsigned long>(
#ifdef __APPLE__ #ifdef __APPLE__
pthread_mach_thread_np(pthread_self()) pthread_mach_thread_np(pthread_self())
#elif _MSC_VER
pthread_getw32threadid_np(pthread_self())
#else #else
pthread_self() pthread_self()
#endif #endif
......
/*
* 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 <pthread.h>
#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 <xstddef>
namespace std {
template <>
struct hash<pthread_t> {
std::size_t operator()(const pthread_t& k) const {
return 0 ^ std::hash<decltype(k.p)>(k.p) ^ std::hash<decltype(k.x)>(k.x);
}
};
}
#endif
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