Files
MinecraftConsoles/Minecraft.Client/PSVita/PSVitaExtras/PSVitaTLSStorage.cpp
2026-03-01 12:16:08 +08:00

237 lines
4.8 KiB
C++

#include "stdafx.h"
#include "PSVitaTLSStorage.h"
#if 1
static PSVitaTLSStorage Singleton;
#define MAX_THREADS 64
typedef struct
{
int ThreadID;
LPVOID Value;
} TLSInfo;
typedef struct
{
TLSInfo *Array;
int Size;
} TLSArray;
static std::vector<TLSArray *> PSVitaTLSStorage_ActiveInfos;
void PSVitaTLSStorage::Init()
{
}
PSVitaTLSStorage *PSVitaTLSStorage::Instance()
{
return &Singleton;
}
DWORD PSVitaTLSStorage::Alloc()
{
TLSArray* Array = new TLSArray;
Array->Array = new TLSInfo[MAX_THREADS];
Array->Size = 0;
for( int i = 0;i < MAX_THREADS;i += 1 )
{
Array->Array[i].ThreadID = -1;
}
// add to the active infos
PSVitaTLSStorage_ActiveInfos.push_back(Array);
return (DWORD) Array;
}
BOOL PSVitaTLSStorage::Free(DWORD dwTlsIndex)
{
// remove from the active infos
std::vector<TLSArray *>::iterator iter = std::find(PSVitaTLSStorage_ActiveInfos.begin(), PSVitaTLSStorage_ActiveInfos.end(), (TLSArray *) dwTlsIndex);
PSVitaTLSStorage_ActiveInfos.erase(iter);
delete []((TLSInfo*)dwTlsIndex);
return 0;
}
void PSVitaTLSStorage::RemoveThread(int threadID)
{
// remove this thread from all the active Infos
std::vector<TLSArray *>::iterator iter = PSVitaTLSStorage_ActiveInfos.begin();
for( ; iter != PSVitaTLSStorage_ActiveInfos.end(); ++iter )
{
TLSArray* Array = ((TLSArray*)*iter);
for( int i = 0;i < Array->Size;i += 1 )
{
if( Array->Array[i].ThreadID == threadID )
{
// shift all the other entries down
for( ;i < MAX_THREADS - 1;i += 1 )
{
Array->Array[i].ThreadID = Array->Array[i+1].ThreadID;
Array->Array[i].Value = Array->Array[i+1].Value;
if( Array->Array[i].ThreadID != -1 )
{
Array->Size = i + 1;
}
}
// mark the top one as unused
Array->Array[i].ThreadID = -1;
break;
}
}
}
}
LPVOID PSVitaTLSStorage::GetValue(DWORD dwTlsIndex)
{
if( !dwTlsIndex )
{
return 0;
}
TLSArray* Array = ((TLSArray*)dwTlsIndex);
SceUID threadID = sceKernelGetThreadId();
for( int i = 0;i < Array->Size;i += 1 )
{
if( Array->Array[i].ThreadID == threadID )
{
return Array->Array[i].Value;
}
}
//assert(0);
return 0;
}
BOOL PSVitaTLSStorage::SetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
{
if( !dwTlsIndex )
{
return 0;
}
TLSArray* Array = ((TLSArray*)dwTlsIndex);
SceUID threadID = sceKernelGetThreadId();
for( int i = 0;i < Array->Size;i += 1 )
{
if( Array->Array[i].ThreadID == threadID || Array->Array[i].ThreadID == -1 )
{
Array->Array[i].ThreadID = threadID;
Array->Array[i].Value = lpTlsValue;
return 0;
}
}
if( Array->Size < MAX_THREADS )
{
Array->Array[Array->Size].ThreadID = threadID;
Array->Array[Array->Size].Value = lpTlsValue;
Array->Size++;
return 0;
}
assert(0);
return 0;
}
#else
PSVitaTLSStorage* m_pInstance = NULL;
#define sc_maxSlots 64
BOOL m_activeList[sc_maxSlots];
//__thread void* m_values[64];
// AP - Oh my. It seems __thread doesn't like cpp files. I couldn't get it to be thread sensitive as it would always return a shared value.
// For now I've stuck m_values and accessor functions into user_malloc.c. Cheap cheap hack.
extern "C"
{
void user_setValue( unsigned int _index, void* _val );
void* user_getValue( unsigned int _index );
}
void PSVitaTLSStorage::Init()
{
for(int i=0;i<sc_maxSlots; i++)
{
m_activeList[i] = false;
// m_values[i] = NULL;
}
}
PSVitaTLSStorage* PSVitaTLSStorage::Instance()
{
if ( m_pInstance == 0 ) // Is this the first time?
{
m_pInstance = new PSVitaTLSStorage; // Create the singleton instance.
m_pInstance->Init();
}
return m_pInstance;
}
DWORD PSVitaTLSStorage::Alloc()
{
for(int i=0; i<sc_maxSlots; i++)
{
if(m_activeList[i] == false)
{
m_activeList[i] = true;
// m_values[i] = NULL;
return i;
}
}
assert(0); // we've ran out of slots
return -1;
}
BOOL PSVitaTLSStorage::Free( DWORD _index )
{
if(m_activeList[_index] == false)
return false; // not been allocated
m_activeList[_index] = false;
// m_values[_index] = NULL;
return true;
}
BOOL PSVitaTLSStorage::SetValue( DWORD _index, LPVOID _val )
{
if(m_activeList[_index] == false)
return false;
user_setValue(_index, _val);
// m_values[_index] = _val;
return true;
}
LPVOID PSVitaTLSStorage::GetValue( DWORD _index )
{
if(m_activeList[_index] == false)
return NULL;
return user_getValue(_index);
// return m_values[_index];
}
void PSVitaTLSStorage::RemoveThread(int threadID)
{
for(int i=0; i<sc_maxSlots; i++)
{
//m_values[i] = NULL;
user_setValue(i, NULL);
}
}
// AP - Oh my. It seems __thread doesn't like cpp files. I couldn't get it to be thread sensitive as it would always return a shared value.
// For now I've stuck m_values and accessor functions into user_malloc.c. Cheap cheap hack.
__thread void* m_values[64];
void user_setValue( unsigned int _index, void* _val )
{
m_values[_index] = _val;
}
void* user_getValue( unsigned int _index )
{
return m_values[_index];
}
#endif