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
This commit is contained in:
Asiri Rathnayake 2017-02-09 09:31:41 +00:00
parent 9987d98370
commit 54a987e1f1
2 changed files with 37 additions and 28 deletions

View File

@ -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*))

View File

@ -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);
}
}