From 54a987e1f16c90a0c6164145df6ef19a3764e120 Mon Sep 17 00:00:00 2001 From: Asiri Rathnayake <asiri.rathnayake@arm.com> Date: Thu, 9 Feb 2017 09:31:41 +0000 Subject: [PATCH] Threading support: externalize sleep_for() function. Different platforms implement the wait/sleep functions in difrerent ways. It makes sense to externalize this into the threading API. Differential revision: https://reviews.llvm.org/D29630 Reviewers: EricWF, joerg llvm-svn: 294573 --- libcxx/include/__threading_support | 37 ++++++++++++++++++++++++++++-- libcxx/src/thread.cpp | 28 ++-------------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index 53a956ed9809..ac0544dfb368 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -12,6 +12,8 @@ #define _LIBCPP_THREADING_SUPPORT #include <__config> +#include <chrono> +#include <errno.h> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header @@ -28,8 +30,6 @@ #include <Windows.h> #include <process.h> #include <fibersapi.h> - -#include <chrono> #endif #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ @@ -183,6 +183,9 @@ int __libcpp_thread_detach(__libcpp_thread_t *__t); _LIBCPP_THREAD_ABI_VISIBILITY void __libcpp_thread_yield(); +_LIBCPP_THREAD_ABI_VISIBILITY +void __libcpp_thread_sleep_for(const chrono::nanoseconds& ns); + // Thread local storage _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_create(__libcpp_tls_key* __key, @@ -345,6 +348,28 @@ void __libcpp_thread_yield() sched_yield(); } +void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) +{ + using namespace chrono; + seconds __s = duration_cast<seconds>(__ns); + timespec __ts; + typedef decltype(__ts.tv_sec) ts_sec; + _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max(); + + if (__s.count() < __ts_sec_max) + { + __ts.tv_sec = static_cast<ts_sec>(__s.count()); + __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count()); + } + else + { + __ts.tv_sec = __ts_sec_max; + __ts.tv_nsec = 999999999; // (10^9 - 1) + } + + while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR); +} + // Thread local storage int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *)) { @@ -562,6 +587,14 @@ void __libcpp_thread_yield() SwitchToThread(); } +void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) +{ + using namespace chrono; + // round-up to the nearest milisecond + milliseconds __ms = duration_cast<milliseconds>(__ns + 999999); + Sleep(__ms.count()); +} + // Thread Local Storage int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp index afa8e163bec9..6fa549d9b599 100644 --- a/libcxx/src/thread.cpp +++ b/libcxx/src/thread.cpp @@ -114,33 +114,9 @@ namespace this_thread void sleep_for(const chrono::nanoseconds& ns) { - using namespace chrono; - if (ns > nanoseconds::zero()) + if (ns > chrono::nanoseconds::zero()) { -#if defined(_LIBCPP_WIN32API) - milliseconds ms = duration_cast<milliseconds>(ns); - if (ms.count() == 0 || ns > duration_cast<nanoseconds>(ms)) - ++ms; - Sleep(ms.count()); -#else - seconds s = duration_cast<seconds>(ns); - timespec ts; - typedef decltype(ts.tv_sec) ts_sec; - _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); - if (s.count() < ts_sec_max) - { - ts.tv_sec = static_cast<ts_sec>(s.count()); - ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count()); - } - else - { - ts.tv_sec = ts_sec_max; - ts.tv_nsec = giga::num - 1; - } - - while (nanosleep(&ts, &ts) == -1 && errno == EINTR) - ; -#endif + __libcpp_thread_sleep_for(ns); } }