From d8d8a7dbb81b7ce1a254c1148f8ffd93b8b5fafe Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Sun, 11 Mar 2018 14:48:55 -0400 Subject: [PATCH] [threading linux] Fix nanosleep using microseconds Add Sleep Test for 50ms. Fix Sleep under linux that was using microseconds as nanoseconds. Factor timespec creation to template function using div/mod and nanoseconds from duration cast. --- src/xenia/base/testing/threading_test.cc | 8 ++++++-- src/xenia/base/threading_posix.cc | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc index 53aece5ae..18c39899b 100644 --- a/src/xenia/base/testing/threading_test.cc +++ b/src/xenia/base/testing/threading_test.cc @@ -15,6 +15,7 @@ namespace xe { namespace base { namespace test { using namespace threading; +using namespace std::chrono_literals; TEST_CASE("Fence") { // TODO(bwrsandman): @@ -43,8 +44,11 @@ TEST_CASE("Sync with Memory Barrier", "SyncMemory") { } TEST_CASE("Sleep Current Thread", "Sleep") { - // TODO(bwrsandman): - REQUIRE(true); + auto wait_time = 50ms; + auto start = std::chrono::steady_clock::now(); + Sleep(wait_time); + auto duration = std::chrono::steady_clock::now() - start; + REQUIRE(duration >= wait_time); } TEST_CASE("Sleep Current Thread in Alertable State", "Sleep") { diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 28597e608..1ee68795c 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -23,6 +23,15 @@ namespace xe { namespace threading { +template +inline timespec DurationToTimeSpec( + std::chrono::duration<_Rep, _Period> duration) { + auto nanoseconds = + std::chrono::duration_cast(duration); + auto div = ldiv(nanoseconds.count(), 1000000000L); + return timespec{div.quot, div.rem}; +} + // TODO(dougvj) void EnableAffinityConfiguration() {} @@ -47,8 +56,7 @@ void MaybeYield() { void SyncMemory() { __sync_synchronize(); } void Sleep(std::chrono::microseconds duration) { - timespec rqtp = {time_t(duration.count() / 1000000), - time_t(duration.count() % 1000)}; + timespec rqtp = DurationToTimeSpec(duration); nanosleep(&rqtp, nullptr); // TODO(benvanik): spin while rmtp >0? }