mirror of
https://github.com/izzy2lost/ppsspp.git
synced 2026-03-10 12:43:04 -07:00
Update the value when mutexes timeout.
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user