Update the value when mutexes timeout.

This commit is contained in:
Unknown W. Brackets
2012-11-18 19:13:39 -08:00
parent aad7e48a1a
commit 4d71e32193
5 changed files with 55 additions and 17 deletions

View File

@@ -249,14 +249,18 @@ void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata)
AddEventToQueue(ne);
}
void UnscheduleEvent(int event_type, u64 userdata)
// Returns cycles left in timer.
int UnscheduleEvent(int event_type, u64 userdata)
{
int result = 0;
if (!first)
return;
return result;
while(first)
{
if (first->type == event_type && first->userdata == userdata)
{
result = (int)(first->time - globalTimer);
Event *next = first->next;
FreeEvent(first);
first = next;
@@ -267,13 +271,15 @@ void UnscheduleEvent(int event_type, u64 userdata)
}
}
if (!first)
return;
return result;
Event *prev = first;
Event *ptr = prev->next;
while (ptr)
{
if (ptr->type == event_type && ptr->userdata == userdata)
{
result = (int)(ptr->time - globalTimer);
prev->next = ptr->next;
FreeEvent(ptr);
ptr = prev->next;
@@ -284,6 +290,8 @@ void UnscheduleEvent(int event_type, u64 userdata)
ptr = ptr->next;
}
}
return result;
}
void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted))

View File

@@ -58,6 +58,10 @@ inline int usToCycles(int us) {
return (int)(CPU_HZ / 1000000 * us);
}
inline int cyclesToUs(int cycles) {
return cycles / (CPU_HZ / 1000000);
}
namespace CoreTiming
{
void Init();
@@ -77,7 +81,7 @@ namespace CoreTiming
void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata=0);
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata=0);
void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata=0);
void UnscheduleEvent(int event_type, u64 userdata);
int UnscheduleEvent(int event_type, u64 userdata);
void RemoveEvent(int event_type);
void RemoveThreadsafeEvent(int event_type);

View File

@@ -116,22 +116,25 @@ void sceKernelDeleteMutex(SceUID id)
Mutex *mutex = kernelObjects.Get<Mutex>(id, error);
if (mutex)
{
// Kill the timer, they're waking up now.
if (mutex->waitTimer != 0)
{
CoreTiming::RemoveEvent(mutex->waitTimer);
mutex->waitTimer = 0;
}
std::vector<SceUID>::iterator iter, end;
for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter)
{
SceUID threadID = *iter;
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
if (timeoutPtr != 0 && mutex->waitTimer != 0)
{
// Remove any event for this thread.
int cyclesLeft = CoreTiming::UnscheduleEvent(mutex->waitTimer, threadID);
Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr);
}
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE);
// TODO: set timeoutPtr.
}
mutex->waitingThreads.empty();
// TODO: Any way to erase the CoreTiming event type? We leak.
RETURN(kernelObjects.Destroy<Mutex>(id));
__KernelReSchedule("mutex deleted");
}
@@ -184,7 +187,12 @@ bool __KernelLockMutex(Mutex *mutex, int count, u32 &error)
void __KernelMutexTimeout(u64 userdata, int cyclesLate)
{
SceUID threadID = (SceUID)userdata;
// TODO: set timeoutPtr.
u32 error;
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
if (timeoutPtr != 0)
Memory::Write_U32(0, timeoutPtr);
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
}
@@ -310,14 +318,17 @@ void sceKernelUnlockMutex(SceUID id, int count)
SceUID threadID = *iter;
int wVal = (int)__KernelGetWaitValue(threadID, error);
u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
mutex->nm.lockThread = threadID;
mutex->nm.lockLevel = wVal;
// Remove any event for this thread.
// TODO: Only if timeoutPtr?
if (mutex->waitTimer != 0)
CoreTiming::UnscheduleEvent(mutex->waitTimer, threadID);
if (timeoutPtr != 0 && mutex->waitTimer != 0)
{
// Remove any event for this thread.
int cyclesLeft = CoreTiming::UnscheduleEvent(mutex->waitTimer, threadID);
Memory::Write_U32(cyclesToUs(cyclesLeft), timeoutPtr);
}
__KernelResumeThreadFromWait(threadID, 0);
wokeThreads = true;

View File

@@ -393,6 +393,20 @@ u32 __KernelGetWaitValue(SceUID threadID, u32 &error)
}
}
u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error)
{
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
{
return t->waitInfo.timeoutPtr;
}
else
{
ERROR_LOG(HLE, "__KernelGetWaitValue ERROR: thread %i", threadID);
return 0;
}
}
void sceKernelReferThreadStatus()
{
SceUID threadID = PARAM(0);

View File

@@ -106,6 +106,7 @@ u32 __KernelResumeThreadFromWait(SceUID threadID); // can return an error value
u32 __KernelResumeThreadFromWait(SceUID threadID, int retval);
u32 __KernelGetWaitValue(SceUID threadID, u32 &error);
u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error);
void __KernelWaitCurThread(WaitType type, SceUID waitId, u32 waitValue, u32 timeoutPtr, bool processCallbacks);
void __KernelReSchedule(const char *reason = "no reason");
void __KernelReSchedule(bool doCallbacks, const char *reason);