Add TLS handling to os specific layer

This commit is contained in:
baldurk
2015-10-05 21:25:41 +02:00
parent 8b595f5f43
commit 360d845ce0
7 changed files with 172 additions and 1 deletions
+4
View File
@@ -189,6 +189,8 @@ void RenderDoc::Initialise()
Network::Init();
Threading::Init();
m_RemoteIdent = 0;
if(!IsReplayApp())
@@ -298,6 +300,8 @@ RenderDoc::~RenderDoc()
Network::Shutdown();
Threading::Shutdown();
FileIO::Delete(m_LoggingFilename.c_str());
}
+21 -1
View File
@@ -412,7 +412,27 @@ const char * WrappedVulkan::GetChunkName(uint32_t idx)
Serialiser *WrappedVulkan::GetThreadSerialiser()
{
return m_pSerialiser;
Serialiser *ser = (Serialiser *)Threading::GetTLSValue(threadSerialiserTLSSlot);
if(ser) return ser;
// slow path, but rare
#if defined(RELEASE)
const bool debugSerialiser = false;
#else
const bool debugSerialiser = true;
#endif
ser = new Serialiser(NULL, Serialiser::WRITING, debugSerialiser);
Threading::SetTLSValue(threadSerialiserTLSSlot, (void *)ser);
{
SCOPED_LOCK(m_ThreadSerialisersLock);
m_ThreadSerialisers.push_back(ser);
}
return ser;
}
void WrappedVulkan::Serialise_CaptureScope(uint64_t offset)
+5
View File
@@ -111,6 +111,11 @@ private:
Serialiser *m_pSerialiser;
LogState m_State;
uint64_t threadSerialiserTLSSlot;
Threading::CriticalSection m_ThreadSerialisersLock;
vector<Serialiser *> m_ThreadSerialisers;
VulkanReplay m_Replay;
@@ -39,6 +39,11 @@ VkResult WrappedVulkan::vkCreateInstance(
VkResult ret = GetInstanceDispatchTable(*pInstance)->CreateInstance(pCreateInfo, &inst);
// VKTODOHIGH need to deallocate this
threadSerialiserTLSSlot = Threading::AllocateTLSSlot();
// VKTODOHIGH need to deallocate m_ThreadSerialisers
GetResourceManager()->WrapResource(inst, inst);
if(ret != VK_SUCCESS)
+65
View File
@@ -122,6 +122,71 @@ namespace Threading
return NULL;
}
// to not exhaust OS slots, we only allocate one that points
// to our own array
pthread_key_t OSTLSHandle;
int64_t nextTLSSlot = 0;
struct TLSData
{
vector<void *> data;
};
void Init()
{
int err = pthread_key_create(&OSTLSHandle, NULL);
if(err != 0)
RDCFATAL("Can't allocate OS TLS slot");
}
void Shutdown()
{
// let the TLS data leak. It's not great, but it's only a few kb per thread
// that we actually use (ie. not short-lived threads that don't use our TLS).
// We don't have a realistic alternative as the threads aren't ours when in-app
// and there may not be a way to have something call on thread death.
pthread_key_delete(OSTLSHandle);
}
// allocate a TLS slot in our per-thread vectors with an atomic increment.
// Note this is going to be 1-indexed because Inc64 returns the post-increment
// value
uint64_t AllocateTLSSlot()
{
return Atomic::Inc64(&nextTLSSlot);
}
// look up our per-thread vector.
void *GetTLSValue(uint64_t slot)
{
TLSData *slots = (TLSData *)pthread_getspecific(OSTLSHandle);
if(slots == NULL || slot-1 >= slots->data.size())
return NULL;
return slots->data[slot-1];
}
void SetTLSValue(uint64_t slot, void *value)
{
TLSData *slots = (TLSData *)pthread_getspecific(OSTLSHandle);
// resize or allocate slot data if needed.
// We don't need to lock this, as it is by definition thread local so we are
// blocking on the only possible concurrent access.
if(slots == NULL || slot-1 >= slots->data.size())
{
if(slots == NULL)
{
slots = new TLSData;
pthread_setspecific(OSTLSHandle, slots);
}
if(slot-1 >= slots->data.size())
slots->data.resize(slot);
}
slots->data[slot-1] = value;
}
ThreadHandle CreateThread(ThreadEntry entryFunc, void *userData)
{
pthread_t thread;
+7
View File
@@ -82,6 +82,13 @@ namespace Threading
data m_Data;
};
void Init();
void Shutdown();
uint64_t AllocateTLSSlot();
void *GetTLSValue(uint64_t slot);
void SetTLSValue(uint64_t slot, void *value);
// must typedef CriticalSectionTemplate<X> CriticalSection
typedef void (*ThreadEntry)(void *);
+65
View File
@@ -116,6 +116,71 @@ namespace Threading
return 0;
}
// to not exhaust OS slots, we only allocate one that points
// to our own array
DWORD OSTLSHandle;
int64_t nextTLSSlot = 0;
struct TLSData
{
vector<void *> data;
};
void Init()
{
OSTLSHandle = TlsAlloc();
if(OSTLSHandle == TLS_OUT_OF_INDEXES)
RDCFATAL("Can't allocate OS TLS slot");
}
void Shutdown()
{
// let the TLS data leak. It's not great, but it's only a few kb per thread
// that we actually use (ie. not short-lived threads that don't use our TLS).
// We don't have a realistic alternative as the threads aren't ours when in-app
// and there may not be a way to have something call on thread death.
TlsFree(OSTLSHandle);
}
// allocate a TLS slot in our per-thread vectors with an atomic increment.
// Note this is going to be 1-indexed because Inc64 returns the post-increment
// value
uint64_t AllocateTLSSlot()
{
return Atomic::Inc64(&nextTLSSlot);
}
// look up our per-thread vector.
void *GetTLSValue(uint64_t slot)
{
TLSData *slots = (TLSData *)TlsGetValue(OSTLSHandle);
if(slots == NULL || slot-1 >= slots->data.size())
return NULL;
return slots->data[slot-1];
}
void SetTLSValue(uint64_t slot, void *value)
{
TLSData *slots = (TLSData *)TlsGetValue(OSTLSHandle);
// resize or allocate slot data if needed.
// We don't need to lock this, as it is by definition thread local so we are
// blocking on the only possible concurrent access.
if(slots == NULL || slot-1 >= slots->data.size())
{
if(slots == NULL)
{
slots = new TLSData;
TlsSetValue(OSTLSHandle, slots);
}
if(slot-1 >= slots->data.size())
slots->data.resize(slot);
}
slots->data[slot-1] = value;
}
ThreadHandle CreateThread(ThreadEntry entryFunc, void *userData)
{