[threading linux] Implement TLS

Implement TLSHandle with pthread_key_t.

Test Alloc, Free, Get and Set.
This commit is contained in:
Sandy Carter 2018-03-12 00:03:52 -04:00 committed by Rick Gibbed
parent 634f87f63b
commit e9e269622b
2 changed files with 41 additions and 11 deletions

View File

@ -113,8 +113,35 @@ TEST_CASE("Sleep Current Thread in Alertable State", "Sleep") {
} }
TEST_CASE("TlsHandle") { TEST_CASE("TlsHandle") {
// TODO(bwrsandman): // Test Allocate
REQUIRE(true); 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<uintptr_t>(&value));
auto p_received_value = threading::GetTlsValue(handle);
REQUIRE(threading::GetTlsValue(handle) != 0);
auto received_value = *reinterpret_cast<uint32_t*>(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") { TEST_CASE("HighResolutionTimer") {

View File

@ -117,23 +117,26 @@ SleepResult AlertableSleep(std::chrono::microseconds duration) {
return SleepResult::kSuccess; 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() { TlsHandle AllocateTlsHandle() {
assert_always(); auto key = static_cast<pthread_key_t>(-1);
return 0; auto res = pthread_key_create(&key, nullptr);
assert_zero(res);
assert_true(key != static_cast<pthread_key_t>(-1));
return static_cast<TlsHandle>(key);
} }
bool FreeTlsHandle(TlsHandle handle) { return true; } bool FreeTlsHandle(TlsHandle handle) {
return pthread_key_delete(static_cast<pthread_key_t>(handle)) == 0;
}
uintptr_t GetTlsValue(TlsHandle handle) { uintptr_t GetTlsValue(TlsHandle handle) {
assert_always(); return reinterpret_cast<uintptr_t>(
return 0; pthread_getspecific(static_cast<pthread_key_t>(handle)));
} }
bool SetTlsValue(TlsHandle handle, uintptr_t value) { bool SetTlsValue(TlsHandle handle, uintptr_t value) {
assert_always(); return pthread_setspecific(static_cast<pthread_key_t>(handle),
return false; reinterpret_cast<void*>(value)) == 0;
} }
class PosixHighResolutionTimer : public HighResolutionTimer { class PosixHighResolutionTimer : public HighResolutionTimer {