Merge pull request #3020 from unknownbrackets/tls-wait

Implement TLS waits, fix allocation bug
This commit is contained in:
Henrik Rydgård 2013-07-31 08:18:52 -07:00
commit aa07ab8c4c
3 changed files with 49 additions and 27 deletions

View File

@ -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;

View File

@ -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)

View File

@ -92,6 +92,7 @@ enum WaitType
WAITTYPE_GELISTSYNC = 18,
WAITTYPE_MODULE = 19,
WAITTYPE_HLEDELAY = 20,
WAITTYPE_TLS = 21,
NUM_WAITTYPES
};