Adding TLS abstraction.

This commit is contained in:
Ben Vanik 2015-07-15 22:20:33 -07:00
parent 48d5d76882
commit c3415e6332
3 changed files with 26 additions and 37 deletions

View File

@ -89,6 +89,14 @@ SleepResult AlertableSleep(std::chrono::duration<Rep, Period> duration) {
std::chrono::duration_cast<std::chrono::microseconds>(duration)); std::chrono::duration_cast<std::chrono::microseconds>(duration));
} }
typedef uint32_t TlsHandle;
constexpr TlsHandle kInvalidTlsHandle = UINT_MAX;
TlsHandle AllocateTlsHandle();
bool FreeTlsHandle(TlsHandle handle);
uintptr_t GetTlsValue(TlsHandle handle);
bool SetTlsValue(TlsHandle handle, uintptr_t value);
// Results for a WaitHandle operation. // Results for a WaitHandle operation.
enum class WaitResult { enum class WaitResult {
// The state of the specified object is signaled. // The state of the specified object is signaled.

View File

@ -96,6 +96,18 @@ SleepResult AlertableSleep(std::chrono::microseconds duration) {
return SleepResult::kSuccess; return SleepResult::kSuccess;
} }
TlsHandle AllocateTlsHandle() { return TlsAlloc(); }
bool FreeTlsHandle(TlsHandle handle) { return TlsFree(handle) ? true : false; }
uintptr_t GetTlsValue(TlsHandle handle) {
return reinterpret_cast<uintptr_t>(TlsGetValue(handle));
}
bool SetTlsValue(TlsHandle handle, uintptr_t value) {
return TlsSetValue(handle, reinterpret_cast<void*>(value)) ? true : false;
}
template <typename T> template <typename T>
class Win32Handle : public T { class Win32Handle : public T {
public: public:

View File

@ -11,7 +11,6 @@
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
#include "xenia/base/platform_win.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#include "xenia/kernel/dispatcher.h" #include "xenia/kernel/dispatcher.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
@ -371,18 +370,10 @@ SHIM_CALL KeQuerySystemTime_shim(PPCContext* ppc_context,
SHIM_CALL KeTlsAlloc_shim(PPCContext* ppc_context, KernelState* kernel_state) { SHIM_CALL KeTlsAlloc_shim(PPCContext* ppc_context, KernelState* kernel_state) {
XELOGD("KeTlsAlloc()"); XELOGD("KeTlsAlloc()");
uint32_t tls_index; auto tls_index = xe::threading::AllocateTlsHandle();
if (tls_index == xe::threading::kInvalidTlsHandle) {
#if XE_PLATFORM_WIN32
tls_index = TlsAlloc();
#else
pthread_key_t key;
if (pthread_key_create(&key, NULL)) {
tls_index = X_TLS_OUT_OF_INDEXES; tls_index = X_TLS_OUT_OF_INDEXES;
} else {
tls_index = (uint32_t)key;
} }
#endif // WIN32
SHIM_SET_RETURN_32(tls_index); SHIM_SET_RETURN_32(tls_index);
} }
@ -398,14 +389,7 @@ SHIM_CALL KeTlsFree_shim(PPCContext* ppc_context, KernelState* kernel_state) {
return; return;
} }
int result = 0; uint32_t result = xe::threading::FreeTlsHandle(tls_index) ? 1 : 0;
#if XE_PLATFORM_WIN32
result = TlsFree(tls_index);
#else
result = pthread_key_delete(tls_index) == 0;
#endif // WIN32
SHIM_SET_RETURN_32(result); SHIM_SET_RETURN_32(result);
} }
@ -419,17 +403,10 @@ SHIM_CALL KeTlsGetValue_shim(PPCContext* ppc_context,
// "KeTlsGetValue(%.8X)", // "KeTlsGetValue(%.8X)",
// tls_index); // tls_index);
uint64_t value = 0; uint32_t value = static_cast<uint32_t>(xe::threading::GetTlsValue(tls_index));
#if XE_PLATFORM_WIN32
value = (uint64_t)TlsGetValue(tls_index);
#else
value = (uint64_t)pthread_getspecific(tls_index);
#endif // WIN32
if (!value) { if (!value) {
// XELOGW("KeTlsGetValue should SetLastError if result is NULL"); // XELOGW("KeTlsGetValue should SetLastError if result is NULL");
// TODO(benvanik): SetLastError // TODO(benvanik): SetLastError? Or does user code do this?
} }
SHIM_SET_RETURN_32(value); SHIM_SET_RETURN_32(value);
@ -443,15 +420,7 @@ SHIM_CALL KeTlsSetValue_shim(PPCContext* ppc_context,
XELOGD("KeTlsSetValue(%.8X, %.8X)", tls_index, tls_value); XELOGD("KeTlsSetValue(%.8X, %.8X)", tls_index, tls_value);
int result = 0; uint32_t result = xe::threading::SetTlsValue(tls_index, tls_value) ? 1 : 0;
#if XE_PLATFORM_WIN32
result = TlsSetValue(
tls_index, reinterpret_cast<void*>(static_cast<uintptr_t>(tls_value)));
#else
result = pthread_setspecific(tls_index, (void*)tls_value) == 0;
#endif // WIN32
SHIM_SET_RETURN_32(result); SHIM_SET_RETURN_32(result);
} }