mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #6822 from unknownbrackets/thread-funcs
Improve some timing / thread funcs
This commit is contained in:
commit
b2f5efaa50
7 changed files with 56 additions and 28 deletions
|
@ -326,7 +326,7 @@ s64 UnscheduleEvent(int event_type, u64 userdata)
|
|||
{
|
||||
if (first->type == event_type && first->userdata == userdata)
|
||||
{
|
||||
result = first->time - globalTimer;
|
||||
result = first->time - GetTicks();
|
||||
|
||||
Event *next = first->next;
|
||||
FreeEvent(first);
|
||||
|
@ -345,7 +345,7 @@ s64 UnscheduleEvent(int event_type, u64 userdata)
|
|||
{
|
||||
if (ptr->type == event_type && ptr->userdata == userdata)
|
||||
{
|
||||
result = ptr->time - globalTimer;
|
||||
result = ptr->time - GetTicks();
|
||||
|
||||
prev->next = ptr->next;
|
||||
FreeEvent(ptr);
|
||||
|
@ -371,7 +371,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
|
|||
{
|
||||
if (tsFirst->type == event_type && tsFirst->userdata == userdata)
|
||||
{
|
||||
result = tsFirst->time - globalTimer;
|
||||
result = tsFirst->time - GetTicks();
|
||||
|
||||
Event *next = tsFirst->next;
|
||||
FreeTsEvent(tsFirst);
|
||||
|
@ -394,7 +394,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
|
|||
{
|
||||
if (ptr->type == event_type && ptr->userdata == userdata)
|
||||
{
|
||||
result = ptr->time - globalTimer;
|
||||
result = ptr->time - GetTicks();
|
||||
|
||||
prev->next = ptr->next;
|
||||
if (ptr == tsLast)
|
||||
|
|
|
@ -57,7 +57,7 @@ struct Alarm : public KernelObject
|
|||
NativeAlarm alm;
|
||||
};
|
||||
|
||||
void __KernelScheduleAlarm(Alarm *alarm, u64 ticks);
|
||||
void __KernelScheduleAlarm(Alarm *alarm, u64 micro);
|
||||
|
||||
class AlarmIntrHandler : public IntrHandler
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ public:
|
|||
DEBUG_LOG(SCEKERNEL, "Rescheduling alarm %08x for +%dms", alarmID, result);
|
||||
u32 error;
|
||||
Alarm *alarm = kernelObjects.Get<Alarm>(alarmID, error);
|
||||
__KernelScheduleAlarm(alarm, (u64) usToCycles(result));
|
||||
__KernelScheduleAlarm(alarm, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -150,13 +150,13 @@ KernelObject *__KernelAlarmObject()
|
|||
return new Alarm;
|
||||
}
|
||||
|
||||
void __KernelScheduleAlarm(Alarm *alarm, u64 ticks)
|
||||
void __KernelScheduleAlarm(Alarm *alarm, u64 micro)
|
||||
{
|
||||
alarm->alm.schedule = CoreTiming::GetGlobalTimeUs() + ticks / (u64) CoreTiming::GetClockFrequencyMHz();
|
||||
CoreTiming::ScheduleEvent((int) ticks, alarmTimer, alarm->GetUID());
|
||||
alarm->alm.schedule = CoreTiming::GetGlobalTimeUs() + micro;
|
||||
CoreTiming::ScheduleEvent(usToCycles(micro), alarmTimer, alarm->GetUID());
|
||||
}
|
||||
|
||||
SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr)
|
||||
SceUID __KernelSetAlarm(u64 micro, u32 handlerPtr, u32 commonPtr)
|
||||
{
|
||||
if (!Memory::IsValidAddress(handlerPtr))
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
|
||||
|
@ -168,14 +168,14 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr)
|
|||
alarm->alm.handlerPtr = handlerPtr;
|
||||
alarm->alm.commonPtr = commonPtr;
|
||||
|
||||
__KernelScheduleAlarm(alarm, ticks);
|
||||
__KernelScheduleAlarm(alarm, micro);
|
||||
return uid;
|
||||
}
|
||||
|
||||
SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr)
|
||||
{
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr);
|
||||
return __KernelSetAlarm(usToCycles((u64) micro), handlerPtr, commonPtr);
|
||||
return __KernelSetAlarm((u64) micro, handlerPtr, commonPtr);
|
||||
}
|
||||
|
||||
SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr)
|
||||
|
@ -188,7 +188,7 @@ SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr)
|
|||
return -1;
|
||||
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelSetSysClockAlarm(%lld, %08x, %08x)", micro, handlerPtr, commonPtr);
|
||||
return __KernelSetAlarm(usToCycles(micro), handlerPtr, commonPtr);
|
||||
return __KernelSetAlarm(micro, handlerPtr, commonPtr);
|
||||
}
|
||||
|
||||
int sceKernelCancelAlarm(SceUID uid)
|
||||
|
|
|
@ -653,6 +653,7 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32
|
|||
|
||||
int sceKernelDeleteFpl(SceUID uid)
|
||||
{
|
||||
hleEatCycles(600);
|
||||
u32 error;
|
||||
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
|
||||
if (fpl)
|
||||
|
@ -833,6 +834,8 @@ retry:
|
|||
|
||||
int sceKernelCancelFpl(SceUID uid, u32 numWaitThreadsPtr)
|
||||
{
|
||||
hleEatCycles(600);
|
||||
|
||||
u32 error;
|
||||
FPL *fpl = kernelObjects.Get<FPL>(uid, error);
|
||||
if (fpl)
|
||||
|
|
|
@ -729,6 +729,8 @@ int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size,
|
|||
|
||||
int sceKernelDeleteMsgPipe(SceUID uid)
|
||||
{
|
||||
hleEatCycles(900);
|
||||
|
||||
u32 error;
|
||||
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
|
||||
if (!m)
|
||||
|
@ -737,6 +739,10 @@ int sceKernelDeleteMsgPipe(SceUID uid)
|
|||
return error;
|
||||
}
|
||||
|
||||
hleEatCycles(3100);
|
||||
if (!m->sendWaitingThreads.empty() || !m->receiveWaitingThreads.empty())
|
||||
hleEatCycles(4000);
|
||||
|
||||
for (size_t i = 0; i < m->sendWaitingThreads.size(); i++)
|
||||
m->sendWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_DELETE);
|
||||
for (size_t i = 0; i < m->receiveWaitingThreads.size(); i++)
|
||||
|
@ -785,6 +791,8 @@ int __KernelValidateSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, int w
|
|||
|
||||
int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
|
||||
{
|
||||
hleEatCycles(2400);
|
||||
|
||||
bool needsResched = false;
|
||||
bool needsWait = false;
|
||||
|
||||
|
@ -962,6 +970,8 @@ int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize,
|
|||
|
||||
int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr)
|
||||
{
|
||||
hleEatCycles(900);
|
||||
|
||||
u32 error;
|
||||
MsgPipe *m = kernelObjects.Get<MsgPipe>(uid, error);
|
||||
if (!m)
|
||||
|
@ -970,6 +980,10 @@ int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThr
|
|||
return error;
|
||||
}
|
||||
|
||||
hleEatCycles(1100);
|
||||
if (!m->sendWaitingThreads.empty() || !m->receiveWaitingThreads.empty())
|
||||
hleEatCycles(4000);
|
||||
|
||||
if (Memory::IsValidAddress(numSendThreadsAddr))
|
||||
Memory::Write_U32((u32) m->sendWaitingThreads.size(), numSendThreadsAddr);
|
||||
if (Memory::IsValidAddress(numReceiveThreadsAddr))
|
||||
|
|
|
@ -320,6 +320,7 @@ retry:
|
|||
if (wokeThreads)
|
||||
hleReSchedule("semaphore signaled");
|
||||
|
||||
hleEatCycles(900);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -359,9 +360,9 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr)
|
|||
|
||||
// This happens to be how the hardware seems to time things.
|
||||
if (micro <= 3)
|
||||
micro = 25;
|
||||
micro = 24;
|
||||
else if (micro <= 249)
|
||||
micro = 250;
|
||||
micro = 245;
|
||||
|
||||
// This should call __KernelSemaTimeout() later, unless we cancel it.
|
||||
CoreTiming::ScheduleEvent(usToCycles(micro), semaWaitTimer, __KernelGetCurThread());
|
||||
|
@ -369,11 +370,18 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr)
|
|||
|
||||
int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool processCallbacks)
|
||||
{
|
||||
hleEatCycles(900);
|
||||
|
||||
if (wantedCount <= 0)
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_COUNT;
|
||||
|
||||
hleEatCycles(500);
|
||||
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
if (wantedCount > s->ns.maxCount || wantedCount <= 0)
|
||||
if (wantedCount > s->ns.maxCount)
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_COUNT;
|
||||
|
||||
// If there are any callbacks, we always wait, and wake after the callbacks.
|
||||
|
|
|
@ -2275,6 +2275,7 @@ int sceKernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr)
|
|||
}
|
||||
|
||||
INFO_LOG(SCEKERNEL, "sceKernelStartThread(thread=%i, argSize=%i, argPtr=%08x)", threadToStartID, argSize, argBlockPtr);
|
||||
hleEatCycles(3400);
|
||||
return __KernelStartThread(threadToStartID, argSize, argBlockPtr);
|
||||
}
|
||||
|
||||
|
|
|
@ -99,15 +99,15 @@ void __KernelScheduleVTimer(VTimer *vt, u64 schedule) {
|
|||
// The "real" base is base + current. But when setting the time, base is important.
|
||||
// The schedule is relative to those.
|
||||
u64 cyclesIntoFuture;
|
||||
// It seems like the minimum is approximately 200us?
|
||||
if (schedule < __getVTimerCurrentTime(vt))
|
||||
cyclesIntoFuture = usToCycles(200);
|
||||
else {
|
||||
u64 goalUs = vt->nvt.base + schedule - vt->nvt.current;
|
||||
if (goalUs < CoreTiming::GetGlobalTimeUs())
|
||||
cyclesIntoFuture = usToCycles(200);
|
||||
else
|
||||
cyclesIntoFuture = usToCycles(goalUs - CoreTiming::GetGlobalTimeUs());
|
||||
if (schedule < 250) {
|
||||
schedule = 250;
|
||||
}
|
||||
s64 goalUs = (u64)vt->nvt.base + schedule - (u64)vt->nvt.current;
|
||||
s64 minGoalUs = CoreTiming::GetGlobalTimeUs() + 250;
|
||||
if (goalUs < minGoalUs) {
|
||||
cyclesIntoFuture = usToCycles(250);
|
||||
} else {
|
||||
cyclesIntoFuture = usToCycles(goalUs - CoreTiming::GetGlobalTimeUs());
|
||||
}
|
||||
|
||||
CoreTiming::ScheduleEvent(cyclesIntoFuture, vtimerTimer, vt->GetUID());
|
||||
|
@ -121,9 +121,6 @@ void __rescheduleVTimer(SceUID id, u32 delay) {
|
|||
if (error)
|
||||
return;
|
||||
|
||||
if (delay < 100)
|
||||
delay = 100;
|
||||
|
||||
__KernelScheduleVTimer(vt, vt->nvt.schedule + delay);
|
||||
}
|
||||
|
||||
|
@ -377,6 +374,8 @@ void __startVTimer(VTimer *vt) {
|
|||
}
|
||||
|
||||
u32 sceKernelStartVTimer(SceUID uid) {
|
||||
hleEatCycles(12200);
|
||||
|
||||
if (uid == runningVTimer) {
|
||||
WARN_LOG(SCEKERNEL, "sceKernelStartVTimer(%08x): invalid vtimer", uid);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_VTID;
|
||||
|
@ -427,6 +426,7 @@ u32 sceKernelStopVTimer(SceUID uid) {
|
|||
}
|
||||
|
||||
u32 sceKernelSetVTimerHandler(SceUID uid, u32 scheduleAddr, u32 handlerFuncAddr, u32 commonAddr) {
|
||||
hleEatCycles(900);
|
||||
if (uid == runningVTimer) {
|
||||
WARN_LOG(SCEKERNEL, "sceKernelSetVTimerHandler(%08x, %08x, %08x, %08x): invalid vtimer", uid, scheduleAddr, handlerFuncAddr, commonAddr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_VTID;
|
||||
|
@ -441,6 +441,7 @@ u32 sceKernelSetVTimerHandler(SceUID uid, u32 scheduleAddr, u32 handlerFuncAddr,
|
|||
}
|
||||
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelSetVTimerHandler(%08x, %08x, %08x, %08x)", uid, scheduleAddr, handlerFuncAddr, commonAddr);
|
||||
hleEatCycles(2000);
|
||||
|
||||
u64 schedule = Memory::Read_U64(scheduleAddr);
|
||||
vt->nvt.handlerAddr = handlerFuncAddr;
|
||||
|
@ -455,6 +456,7 @@ u32 sceKernelSetVTimerHandler(SceUID uid, u32 scheduleAddr, u32 handlerFuncAddr,
|
|||
}
|
||||
|
||||
u32 sceKernelSetVTimerHandlerWide(SceUID uid, u64 schedule, u32 handlerFuncAddr, u32 commonAddr) {
|
||||
hleEatCycles(900);
|
||||
if (uid == runningVTimer) {
|
||||
WARN_LOG(SCEKERNEL, "sceKernelSetVTimerHandlerWide(%08x, %llu, %08x, %08x): invalid vtimer", uid, schedule, handlerFuncAddr, commonAddr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_VTID;
|
||||
|
|
Loading…
Add table
Reference in a new issue