Merge pull request #6822 from unknownbrackets/thread-funcs

Improve some timing / thread funcs
This commit is contained in:
Henrik Rydgård 2014-09-02 09:49:46 +02:00
commit b2f5efaa50
7 changed files with 56 additions and 28 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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