201 lines
4.4 KiB
C
201 lines
4.4 KiB
C
|
#ifdef HX_TLS_H_OVERRIDE
|
||
|
// Users can define their own header to use here, but there is no API
|
||
|
// compatibility gaurantee for future changes.
|
||
|
#include HX_TLS_H_OVERRIDE
|
||
|
#else
|
||
|
|
||
|
#ifndef HX_TLS_INCLUDED
|
||
|
#define HX_TLS_INCLUDED
|
||
|
|
||
|
#if defined(HX_WINDOWS) || defined(KORE_CONSOLE)
|
||
|
|
||
|
#if defined(HX_WINRT)
|
||
|
// Nothing
|
||
|
#elif defined(KORE_CONSOLE)
|
||
|
|
||
|
#include <kinc/threads/threadlocal.h>
|
||
|
|
||
|
namespace hx {
|
||
|
template<typename DATA, bool FAST = false> struct TLSData {
|
||
|
TLSData() {
|
||
|
kinc_thread_local_init(&tls);
|
||
|
}
|
||
|
|
||
|
~TLSData() {
|
||
|
kinc_thread_local_destroy(&tls);
|
||
|
}
|
||
|
|
||
|
DATA *Get() {
|
||
|
return (DATA*)kinc_thread_local_get(&tls);
|
||
|
}
|
||
|
|
||
|
void Set(DATA *inData) {
|
||
|
kinc_thread_local_set(&tls, inData);
|
||
|
}
|
||
|
|
||
|
inline DATA *operator=(DATA *inData) {
|
||
|
kinc_thread_local_set(&tls, inData);
|
||
|
return inData;
|
||
|
}
|
||
|
|
||
|
inline operator DATA*() {
|
||
|
return (DATA*)kinc_thread_local_get(&tls);
|
||
|
}
|
||
|
private:
|
||
|
kinc_thread_local_t tls;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
#if ! defined(__GNUC__) && !defined(__BORLANDC__)
|
||
|
#include <intrin.h>
|
||
|
#endif
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
__declspec(dllimport)
|
||
|
int __stdcall TlsSetValue(unsigned long dwTlsIndex, void *lpTlsValue);
|
||
|
|
||
|
__declspec(dllimport)
|
||
|
void * __stdcall TlsGetValue(unsigned long dwTlsIndex);
|
||
|
|
||
|
__declspec(dllimport)
|
||
|
unsigned long __stdcall TlsAlloc(void);
|
||
|
}
|
||
|
|
||
|
|
||
|
namespace hx {
|
||
|
|
||
|
template<typename DATA,bool FAST=false>
|
||
|
struct TLSData
|
||
|
{
|
||
|
static const size_t kMaxInlineSlots = 64;
|
||
|
|
||
|
TLSData()
|
||
|
{
|
||
|
mSlot = TlsAlloc();
|
||
|
TlsSetValue(mSlot,0);
|
||
|
#ifdef HXCPP_M64
|
||
|
mFastOffset = mSlot*sizeof(void *) + 0x1480;
|
||
|
#else
|
||
|
if (FAST || mSlot < kMaxInlineSlots)
|
||
|
mFastOffset = mSlot*sizeof(void *) + 0xE10;
|
||
|
else
|
||
|
mFastOffset = mSlot - kMaxInlineSlots;
|
||
|
#endif
|
||
|
}
|
||
|
inline DATA *operator=(DATA *inData)
|
||
|
{
|
||
|
TlsSetValue(mSlot,inData);
|
||
|
return inData;
|
||
|
}
|
||
|
|
||
|
inline operator DATA *()
|
||
|
{
|
||
|
#if !defined(HXCPP_M64) && (_MSC_VER >= 1400)
|
||
|
const size_t kTibExtraTlsOffset = 0xF94;
|
||
|
|
||
|
if (FAST || mSlot < kMaxInlineSlots)
|
||
|
return (DATA *)__readfsdword(mFastOffset);
|
||
|
|
||
|
DATA **extra = (DATA **)(__readfsdword(kTibExtraTlsOffset));
|
||
|
return extra[mFastOffset];
|
||
|
#elif (_MSC_VER >= 1400) & !defined(HXCPP_DEBUG) && !defined(HXCPP_ARM64)// 64 bit version...
|
||
|
if (mSlot < 64)
|
||
|
return (DATA *)__readgsqword(mFastOffset);
|
||
|
else
|
||
|
return (DATA *)TlsGetValue(mSlot);
|
||
|
#else
|
||
|
return (DATA *)TlsGetValue(mSlot);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int mSlot;
|
||
|
int mFastOffset;
|
||
|
};
|
||
|
|
||
|
} // end namespace hx
|
||
|
|
||
|
|
||
|
#define DECLARE_TLS_DATA(TYPE,NAME) \
|
||
|
hx::TLSData<TYPE> NAME;
|
||
|
#define DECLARE_FAST_TLS_DATA(TYPE,NAME) \
|
||
|
hx::TLSData<TYPE,true> NAME;
|
||
|
#define EXTERN_TLS_DATA(TYPE,NAME) \
|
||
|
extern hx::TLSData<TYPE> NAME;
|
||
|
#define EXTERN_FAST_TLS_DATA(TYPE,NAME) \
|
||
|
extern hx::TLSData<TYPE,true> NAME;
|
||
|
|
||
|
|
||
|
#endif
|
||
|
#else // not HX_WINDOWS
|
||
|
|
||
|
#include <pthread.h>
|
||
|
|
||
|
namespace hx
|
||
|
{
|
||
|
|
||
|
template<typename DATA,bool FAST=false>
|
||
|
struct TLSData
|
||
|
{
|
||
|
TLSData()
|
||
|
{
|
||
|
pthread_key_create(&mSlot, 0);
|
||
|
}
|
||
|
DATA *Get()
|
||
|
{
|
||
|
return (DATA *)pthread_getspecific(mSlot);
|
||
|
}
|
||
|
void Set(DATA *inData)
|
||
|
{
|
||
|
pthread_setspecific(mSlot,inData);
|
||
|
}
|
||
|
inline DATA *operator=(DATA *inData)
|
||
|
{
|
||
|
pthread_setspecific(mSlot,inData);
|
||
|
return inData;
|
||
|
}
|
||
|
inline operator DATA *() { return (DATA *)pthread_getspecific(mSlot); }
|
||
|
|
||
|
pthread_key_t mSlot;
|
||
|
};
|
||
|
|
||
|
} // end namespace hx
|
||
|
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef HX_WINRT
|
||
|
|
||
|
#define DECLARE_TLS_DATA(TYPE,NAME) \
|
||
|
__declspec(thread) TYPE * NAME = nullptr;
|
||
|
#define DECLARE_FAST_TLS_DATA(TYPE,NAME) \
|
||
|
__declspec(thread) TYPE * NAME = nullptr;
|
||
|
#define EXTERN_TLS_DATA(TYPE,NAME) \
|
||
|
__declspec(thread) extern TYPE * NAME;
|
||
|
#define EXTERN_FAST_TLS_DATA(TYPE,NAME) \
|
||
|
__declspec(thread) extern TYPE * NAME;
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define DECLARE_TLS_DATA(TYPE,NAME) \
|
||
|
hx::TLSData<TYPE> NAME;
|
||
|
#define DECLARE_FAST_TLS_DATA(TYPE,NAME) \
|
||
|
hx::TLSData<TYPE,true> NAME;
|
||
|
#define EXTERN_TLS_DATA(TYPE,NAME) \
|
||
|
extern hx::TLSData<TYPE> NAME;
|
||
|
#define EXTERN_FAST_TLS_DATA(TYPE,NAME) \
|
||
|
extern hx::TLSData<TYPE,true> NAME;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#endif
|