From e9e269622b449ac64e5734c04a3f039f94f20d7b Mon Sep 17 00:00:00 2001 From: Sandy Carter Date: Mon, 12 Mar 2018 00:03:52 -0400 Subject: [PATCH] [threading linux] Implement TLS Implement TLSHandle with pthread_key_t. Test Alloc, Free, Get and Set. --- src/xenia/base/testing/threading_test.cc | 31 ++++++++++++++++++++++-- src/xenia/base/threading_posix.cc | 21 +++++++++------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc index 03d58111c..0c8454f64 100644 --- a/src/xenia/base/testing/threading_test.cc +++ b/src/xenia/base/testing/threading_test.cc @@ -113,8 +113,35 @@ TEST_CASE("Sleep Current Thread in Alertable State", "Sleep") { } TEST_CASE("TlsHandle") { - // TODO(bwrsandman): - REQUIRE(true); + // Test Allocate + auto handle = threading::AllocateTlsHandle(); + + // Test Free + REQUIRE(threading::FreeTlsHandle(handle)); + REQUIRE(!threading::FreeTlsHandle(handle)); + REQUIRE(!threading::FreeTlsHandle(threading::kInvalidTlsHandle)); + + // Test setting values + handle = threading::AllocateTlsHandle(); + REQUIRE(threading::GetTlsValue(handle) == 0); + uint32_t value = 0xDEADBEEF; + threading::SetTlsValue(handle, reinterpret_cast(&value)); + auto p_received_value = threading::GetTlsValue(handle); + REQUIRE(threading::GetTlsValue(handle) != 0); + auto received_value = *reinterpret_cast(p_received_value); + REQUIRE(received_value == value); + + uintptr_t non_thread_local_value = 0; + auto thread = Thread::Create({}, [&non_thread_local_value, &handle] { + non_thread_local_value = threading::GetTlsValue(handle); + }); + + auto result = Wait(thread.get(), false, 50ms); + REQUIRE(result == WaitResult::kSuccess); + REQUIRE(non_thread_local_value == 0); + + // Cleanup + REQUIRE(threading::FreeTlsHandle(handle)); } TEST_CASE("HighResolutionTimer") { diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 29580eb20..2afe4ebfc 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -117,23 +117,26 @@ SleepResult AlertableSleep(std::chrono::microseconds duration) { return SleepResult::kSuccess; } -// TODO(dougvj) We can probably wrap this with pthread_key_t but the type of -// TlsHandle probably needs to be refactored TlsHandle AllocateTlsHandle() { - assert_always(); - return 0; + auto key = static_cast(-1); + auto res = pthread_key_create(&key, nullptr); + assert_zero(res); + assert_true(key != static_cast(-1)); + return static_cast(key); } -bool FreeTlsHandle(TlsHandle handle) { return true; } +bool FreeTlsHandle(TlsHandle handle) { + return pthread_key_delete(static_cast(handle)) == 0; +} uintptr_t GetTlsValue(TlsHandle handle) { - assert_always(); - return 0; + return reinterpret_cast( + pthread_getspecific(static_cast(handle))); } bool SetTlsValue(TlsHandle handle, uintptr_t value) { - assert_always(); - return false; + return pthread_setspecific(static_cast(handle), + reinterpret_cast(value)) == 0; } class PosixHighResolutionTimer : public HighResolutionTimer {