Commit 9c6832ee authored by Orvid King's avatar Orvid King Committed by Facebook Github Bot

Expand the pthread portability layer to basic pthread operations

Summary: The pthread library we were using is getting to be annoying so just implement things ourself.

Reviewed By: yfeldblum

Differential Revision: D9777661

fbshipit-source-id: fb53d0d369ed27a869e9f6285a548778c3492f2e
parent 95918c0f
...@@ -642,6 +642,7 @@ if (BUILD_TESTS) ...@@ -642,6 +642,7 @@ if (BUILD_TESTS)
TEST constexpr_test SOURCES ConstexprTest.cpp TEST constexpr_test SOURCES ConstexprTest.cpp
TEST libgen-test SOURCES LibgenTest.cpp TEST libgen-test SOURCES LibgenTest.cpp
TEST openssl_portability_test SOURCES OpenSSLPortabilityTest.cpp TEST openssl_portability_test SOURCES OpenSSLPortabilityTest.cpp
TEST pthread_test SOURCES PThreadTest.cpp
TEST time-test SOURCES TimeTest.cpp TEST time-test SOURCES TimeTest.cpp
DIRECTORY ssl/test/ DIRECTORY ssl/test/
......
This diff is collapsed.
...@@ -24,12 +24,78 @@ ...@@ -24,12 +24,78 @@
#elif !FOLLY_HAVE_PTHREAD #elif !FOLLY_HAVE_PTHREAD
#include <folly/portability/Windows.h> // nolint
#include <cstdint> #include <cstdint>
#include <memory>
#include <folly/portability/Sched.h>
#include <folly/portability/Time.h>
#include <folly/portability/Windows.h> // nolint
#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 1
#define PTHREAD_MUTEX_DEFAULT 0
#define PTHREAD_MUTEX_RECURSIVE 1
#define _POSIX_TIMEOUTS 200112L
namespace folly { namespace folly {
namespace portability { namespace portability {
namespace pthread { namespace pthread {
struct pthread_attr_t {
size_t stackSize;
bool detached;
};
int pthread_attr_init(pthread_attr_t* attr);
int pthread_attr_setdetachstate(pthread_attr_t* attr, int state);
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t kb);
namespace pthread_detail {
struct pthread_t {
HANDLE handle{INVALID_HANDLE_VALUE};
DWORD threadID{0};
bool detached{false};
~pthread_t() noexcept;
};
} // namespace pthread_detail
using pthread_t = std::shared_ptr<pthread_detail::pthread_t>;
int pthread_equal(pthread_t threadA, pthread_t threadB);
int pthread_create(
pthread_t* thread,
const pthread_attr_t* attr,
void* (*start_routine)(void*),
void* arg);
pthread_t pthread_self();
int pthread_join(pthread_t thread, void** exitCode);
HANDLE pthread_getw32threadhandle_np(pthread_t thread);
DWORD pthread_getw32threadid_np(pthread_t thread);
int pthread_setschedparam(
pthread_t thread,
int policy,
const sched_param* param);
struct pthread_mutexattr_t {
int type;
};
int pthread_mutexattr_init(pthread_mutexattr_t* attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);
int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type);
using pthread_mutex_t = struct pthread_mutex_t_*;
int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);
int pthread_mutex_destroy(pthread_mutex_t* mutex);
int pthread_mutex_lock(pthread_mutex_t* mutex);
int pthread_mutex_trylock(pthread_mutex_t* mutex);
int pthread_mutex_unlock(pthread_mutex_t* mutex);
int pthread_mutex_timedlock(
pthread_mutex_t* mutex,
const timespec* abs_timeout);
// In reality, this is boost::thread_specific_ptr*, but we're attempting // In reality, this is boost::thread_specific_ptr*, but we're attempting
// to avoid introducing boost into a portability header. // to avoid introducing boost into a portability header.
using pthread_key_t = void*; using pthread_key_t = void*;
......
/*
* Copyright 2017-present 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.
*/
#include <folly/portability/Sched.h>
#if _WIN32
#include <thread>
namespace folly {
namespace portability {
namespace sched {
int sched_yield() {
std::this_thread::yield();
return 0;
}
// There is only 1 scheduling policy on Windows
int sched_get_priority_min(int policy) {
return -15;
}
int sched_get_priority_max(int policy) {
return 15;
}
} // namespace sched
} // namespace portability
} // namespace folly
#endif
/*
* Copyright 2017-present 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
#ifndef _WIN32
#include <sched.h>
#else
#define SCHED_OTHER 0
#define SCHED_FIFO 1
#define SCHED_RR 2
namespace folly {
namespace portability {
namespace sched {
struct sched_param {
int sched_priority;
};
int sched_yield();
int sched_get_priority_min(int policy);
int sched_get_priority_max(int policy);
} // namespace sched
} // namespace portability
} // namespace folly
/* using override */ using namespace folly::portability::sched;
#endif
/*
* Copyright 2016-present 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.
*/
#include <folly/portability/PThread.h>
#include <folly/portability/GTest.h>
#include <atomic>
TEST(PThreadTest, pthread_create_and_join) {
static std::atomic<bool> hasRun{false};
static std::atomic<int32_t> argPassedIn{0};
auto mainFunc = [](void* arg) -> void* {
hasRun = true;
argPassedIn = (int32_t) reinterpret_cast<uintptr_t>(arg);
return nullptr;
};
pthread_t thread;
EXPECT_EQ(pthread_create(&thread, nullptr, mainFunc, (void*)53), 0);
EXPECT_EQ(pthread_join(thread, nullptr), 0);
EXPECT_TRUE(hasRun);
EXPECT_EQ(argPassedIn, 53);
}
TEST(PThreadTest, pthread_join_return_value) {
static std::atomic<bool> hasRun{false};
auto mainFunc = [](void*) -> void* {
hasRun = true;
return (void*)5;
};
pthread_t thread;
EXPECT_EQ(pthread_create(&thread, nullptr, mainFunc, nullptr), 0);
void* exitCode = nullptr;
EXPECT_EQ(pthread_join(thread, &exitCode), 0);
EXPECT_EQ(exitCode, (void*)5);
EXPECT_TRUE(hasRun);
}
TEST(PThreadTest, pthread_equal) {
auto self = pthread_self();
EXPECT_NE(pthread_equal(self, self), 0);
auto mainFunc = [](void*) -> void* { return nullptr; };
pthread_t thread;
EXPECT_EQ(pthread_create(&thread, nullptr, mainFunc, nullptr), 0);
EXPECT_EQ(pthread_equal(thread, self), 0);
}
TEST(PThreadTest, pthread_self_on_pthread_thread) {
static std::atomic<bool> hasRun{false};
static pthread_t otherSelf;
auto mainFunc = [](void*) -> void* {
hasRun = true;
otherSelf = pthread_self();
return nullptr;
};
pthread_t thread;
EXPECT_EQ(pthread_create(&thread, nullptr, mainFunc, nullptr), 0);
EXPECT_EQ(pthread_join(thread, nullptr), 0);
EXPECT_NE(pthread_equal(otherSelf, thread), 0);
EXPECT_TRUE(hasRun);
}
...@@ -169,7 +169,6 @@ bool setThreadName(std::thread::id tid, StringPiece name) { ...@@ -169,7 +169,6 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
#endif #endif
} }
#if FOLLY_HAVE_PTHREAD
bool setThreadName(pthread_t pid, StringPiece name) { bool setThreadName(pthread_t pid, StringPiece name) {
#if _WIN32 #if _WIN32
static_assert( static_assert(
...@@ -199,7 +198,6 @@ bool setThreadName(pthread_t pid, StringPiece name) { ...@@ -199,7 +198,6 @@ bool setThreadName(pthread_t pid, StringPiece name) {
return setThreadName(id, name); return setThreadName(id, name);
#endif #endif
} }
#endif
bool setThreadName(StringPiece name) { bool setThreadName(StringPiece name) {
return setThreadName(std::this_thread::get_id(), name); return setThreadName(std::this_thread::get_id(), name);
......
...@@ -55,9 +55,7 @@ Optional<std::string> getCurrentThreadName(); ...@@ -55,9 +55,7 @@ Optional<std::string> getCurrentThreadName();
* is not available. * is not available.
*/ */
bool setThreadName(std::thread::id tid, StringPiece name); bool setThreadName(std::thread::id tid, StringPiece name);
#if FOLLY_HAVE_PTHREAD
bool setThreadName(pthread_t pid, StringPiece name); bool setThreadName(pthread_t pid, StringPiece name);
#endif
/** /**
* Equivalent to setThreadName(std::this_thread::get_id(), name); * Equivalent to setThreadName(std::this_thread::get_id(), name);
......
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