mirror of
https://github.com/libretro/ppsspp.git
synced 2024-12-04 07:00:51 +00:00
Merge pull request #3020 from unknownbrackets/tls-wait
Implement TLS waits, fix allocation bug
This commit is contained in:
commit
aa07ab8c4c
@ -1343,6 +1343,7 @@ struct TLS : public KernelObject
|
||||
{
|
||||
p.Do(ntls);
|
||||
p.Do(address);
|
||||
p.Do(waitingThreads);
|
||||
p.Do(next);
|
||||
p.Do(usage);
|
||||
p.DoMarker("TLS");
|
||||
@ -1350,7 +1351,7 @@ struct TLS : public KernelObject
|
||||
|
||||
NativeTls ntls;
|
||||
u32 address;
|
||||
// TODO: Waiting threads.
|
||||
std::vector<SceUID> waitingThreads;
|
||||
int next;
|
||||
std::vector<SceUID> usage;
|
||||
};
|
||||
@ -1489,7 +1490,7 @@ int sceKernelAllocateTls(SceUID uid)
|
||||
// The PSP doesn't give the same block out twice in a row, even if freed.
|
||||
if (tls->usage[tls->next] == 0)
|
||||
allocBlock = tls->next;
|
||||
tls->next = (tls->next + 1) % tls->ntls.blockSize;
|
||||
tls->next = (tls->next + 1) % tls->ntls.totalBlocks;
|
||||
}
|
||||
|
||||
if (allocBlock != -1)
|
||||
@ -1501,8 +1502,8 @@ int sceKernelAllocateTls(SceUID uid)
|
||||
|
||||
if (allocBlock == -1)
|
||||
{
|
||||
// TODO: Wait here, wake when one is free.
|
||||
ERROR_LOG_REPORT(HLE, "sceKernelAllocateTls: should wait");
|
||||
tls->waitingThreads.push_back(threadID);
|
||||
__KernelWaitCurThread(WAITTYPE_TLS, uid, 1, 0, false, "allocate tls");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1522,7 +1523,7 @@ int sceKernelFreeTls(SceUID uid)
|
||||
{
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
|
||||
// If the thread already has one, return it.
|
||||
// Find the current thread's block.
|
||||
int freeBlock = -1;
|
||||
for (size_t i = 0; i < tls->ntls.totalBlocks; ++i)
|
||||
{
|
||||
@ -1535,7 +1536,26 @@ int sceKernelFreeTls(SceUID uid)
|
||||
|
||||
if (freeBlock != -1)
|
||||
{
|
||||
// TODO: Free anyone waiting for a free block.
|
||||
u32 error2;
|
||||
while (!tls->waitingThreads.empty())
|
||||
{
|
||||
// TODO: What order do they wake in?
|
||||
SceUID waitingThreadID = tls->waitingThreads[0];
|
||||
tls->waitingThreads.erase(tls->waitingThreads.begin());
|
||||
|
||||
// This thread must've been woken up.
|
||||
if (__KernelGetWaitID(waitingThreadID, WAITTYPE_TLS, error2) != uid)
|
||||
continue;
|
||||
|
||||
// Otherwise, if there was a thread waiting, we were full, so this newly freed one is theirs.
|
||||
// TODO: Is the block wiped or anything?
|
||||
tls->usage[freeBlock] = waitingThreadID;
|
||||
__KernelResumeThreadFromWait(waitingThreadID, freeBlock);
|
||||
// No need to continue or free it, we're done.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// No one was waiting, so now we can really free it.
|
||||
tls->usage[freeBlock] = 0;
|
||||
++tls->ntls.freeBlocks;
|
||||
return 0;
|
||||
|
@ -46,27 +46,28 @@ typedef struct
|
||||
} WaitTypeNames;
|
||||
|
||||
const WaitTypeNames waitTypeNames[] = {
|
||||
{ WAITTYPE_NONE, "None" },
|
||||
{ WAITTYPE_SLEEP, "Sleep" },
|
||||
{ WAITTYPE_DELAY, "Delay" },
|
||||
{ WAITTYPE_SEMA, "Semaphore" },
|
||||
{ WAITTYPE_EVENTFLAG, "Event flag", },
|
||||
{ WAITTYPE_MBX, "MBX" },
|
||||
{ WAITTYPE_VPL, "VPL" },
|
||||
{ WAITTYPE_FPL, "FPL" },
|
||||
{ WAITTYPE_MSGPIPE, "Message pipe" },
|
||||
{ WAITTYPE_THREADEND, "Thread end" },
|
||||
{ WAITTYPE_AUDIOCHANNEL, "Audio channel" },
|
||||
{ WAITTYPE_UMD, "UMD" },
|
||||
{ WAITTYPE_VBLANK, "VBlank" },
|
||||
{ WAITTYPE_MUTEX, "Mutex" },
|
||||
{ WAITTYPE_LWMUTEX, "LwMutex" },
|
||||
{ WAITTYPE_CTRL, "Control" },
|
||||
{ WAITTYPE_IO, "IO" },
|
||||
{ WAITTYPE_GEDRAWSYNC, "GeDrawSync" },
|
||||
{ WAITTYPE_GELISTSYNC, "GeListSync" },
|
||||
{ WAITTYPE_MODULE, "Module" },
|
||||
{ WAITTYPE_HLEDELAY, "HleDelay" }
|
||||
{ WAITTYPE_NONE, "None" },
|
||||
{ WAITTYPE_SLEEP, "Sleep" },
|
||||
{ WAITTYPE_DELAY, "Delay" },
|
||||
{ WAITTYPE_SEMA, "Semaphore" },
|
||||
{ WAITTYPE_EVENTFLAG, "Event flag", },
|
||||
{ WAITTYPE_MBX, "MBX" },
|
||||
{ WAITTYPE_VPL, "VPL" },
|
||||
{ WAITTYPE_FPL, "FPL" },
|
||||
{ WAITTYPE_MSGPIPE, "Message pipe" },
|
||||
{ WAITTYPE_THREADEND, "Thread end" },
|
||||
{ WAITTYPE_AUDIOCHANNEL, "Audio channel" },
|
||||
{ WAITTYPE_UMD, "UMD" },
|
||||
{ WAITTYPE_VBLANK, "VBlank" },
|
||||
{ WAITTYPE_MUTEX, "Mutex" },
|
||||
{ WAITTYPE_LWMUTEX, "LwMutex" },
|
||||
{ WAITTYPE_CTRL, "Control" },
|
||||
{ WAITTYPE_IO, "IO" },
|
||||
{ WAITTYPE_GEDRAWSYNC, "GeDrawSync" },
|
||||
{ WAITTYPE_GELISTSYNC, "GeListSync" },
|
||||
{ WAITTYPE_MODULE, "Module" },
|
||||
{ WAITTYPE_HLEDELAY, "HleDelay" },
|
||||
{ WAITTYPE_TLS, "TLS" },
|
||||
};
|
||||
|
||||
const char *getWaitTypeName(WaitType type)
|
||||
|
@ -92,6 +92,7 @@ enum WaitType
|
||||
WAITTYPE_GELISTSYNC = 18,
|
||||
WAITTYPE_MODULE = 19,
|
||||
WAITTYPE_HLEDELAY = 20,
|
||||
WAITTYPE_TLS = 21,
|
||||
|
||||
NUM_WAITTYPES
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user