Prevent waiting on semas while dispatch disabled.

Does relatively well on tests this way.
This commit is contained in:
Unknown W. Brackets 2013-03-24 23:30:32 -07:00
parent e133d33167
commit 276037675f
5 changed files with 30 additions and 10 deletions

View file

@ -443,7 +443,17 @@ void CallSyscall(u32 op)
HLEFunc func = moduleDB[modulenum].funcTable[funcnum].func; HLEFunc func = moduleDB[modulenum].funcTable[funcnum].func;
if (func) if (func)
{ {
func(); // TODO: Move to jit/interp.
u32 flags = moduleDB[modulenum].funcTable[funcnum].flags;
if (flags & HLE_NOT_DISPATCH_SUSPENDED)
{
if (!__KernelIsDispatchEnabled())
RETURN(SCE_KERNEL_ERROR_CAN_NOT_WAIT);
else
func();
}
else
func();
if (hleAfterSyscall != HLE_AFTER_NOTHING) if (hleAfterSyscall != HLE_AFTER_NOTHING)
hleFinishSyscall(modulenum, funcnum); hleFinishSyscall(modulenum, funcnum);

View file

@ -20,14 +20,17 @@
#include "../Globals.h" #include "../Globals.h"
#include "../MIPS/MIPS.h" #include "../MIPS/MIPS.h"
#define STACKTOP 0x09F00000
#define STACKSIZE 0x10000
typedef void (* HLEFunc)(); typedef void (* HLEFunc)();
enum { enum {
NOT_IN_INTERRUPT, // The low 8 bits are a value, indicating special jit handling.
NOT_DISPATCH_SUSPENDED, // Currently there are none.
// The remaining 24 bits are flags.
// Don't allow the call within an interrupt. Not yet implemented.
HLE_NOT_IN_INTERRUPT = 1 << 8,
// Don't allow the call if dispatch or interrupts are disabled.
HLE_NOT_DISPATCH_SUSPENDED = 1 << 9,
}; };
struct HLEFunction struct HLEFunction

View file

@ -610,8 +610,8 @@ const HLEFunction ThreadManForUser[] =
{0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"}, {0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"},
{0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"}, {0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"},
{0x3F53E640,&WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema"}, {0x3F53E640,&WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema"},
{0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema"}, {0x4E3A1105,&WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema", HLE_NOT_DISPATCH_SUSPENDED},
{0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB"}, {0x6d212bac,&WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB", HLE_NOT_DISPATCH_SUSPENDED},
{0x60107536,&WrapI_U<sceKernelDeleteLwMutex>, "sceKernelDeleteLwMutex"}, {0x60107536,&WrapI_U<sceKernelDeleteLwMutex>, "sceKernelDeleteLwMutex"},
{0x19CFF145,&WrapI_UCUIU<sceKernelCreateLwMutex>, "sceKernelCreateLwMutex"}, {0x19CFF145,&WrapI_UCUIU<sceKernelCreateLwMutex>, "sceKernelCreateLwMutex"},

View file

@ -1284,7 +1284,7 @@ Thread *__KernelNextThread() {
void __KernelReSchedule(const char *reason) void __KernelReSchedule(const char *reason)
{ {
// cancel rescheduling when in interrupt or callback, otherwise everything will be fucked up // cancel rescheduling when in interrupt or callback, otherwise everything will be fucked up
if (__IsInInterrupt() || __KernelInCallback() || !__InterruptsEnabled()) if (__IsInInterrupt() || __KernelInCallback() || !__KernelIsDispatchEnabled())
{ {
reason = "In Interrupt Or Callback"; reason = "In Interrupt Or Callback";
return; return;
@ -1299,7 +1299,7 @@ void __KernelReSchedule(const char *reason)
// Execute any pending events while we're doing scheduling. // Execute any pending events while we're doing scheduling.
CoreTiming::AdvanceQuick(); CoreTiming::AdvanceQuick();
if (__IsInInterrupt() || __KernelInCallback() || !__InterruptsEnabled()) if (__IsInInterrupt() || __KernelInCallback() || !__KernelIsDispatchEnabled())
{ {
reason = "In Interrupt Or Callback"; reason = "In Interrupt Or Callback";
return; return;
@ -1717,6 +1717,12 @@ u32 sceKernelResumeDispatchThread(u32 enabled)
return 0; return 0;
} }
bool __KernelIsDispatchEnabled()
{
// Dispatch can never be enabled when interrupts are disabled.
return dispatchEnabled && __InterruptsEnabled();
}
int sceKernelRotateThreadReadyQueue(int priority) int sceKernelRotateThreadReadyQueue(int priority)
{ {
DEBUG_LOG(HLE, "sceKernelRotateThreadReadyQueue(%x)", priority); DEBUG_LOG(HLE, "sceKernelRotateThreadReadyQueue(%x)", priority);

View file

@ -176,6 +176,7 @@ void __KernelStartIdleThreads();
void __KernelReturnFromThread(); // Called as HLE function void __KernelReturnFromThread(); // Called as HLE function
u32 __KernelGetThreadPrio(SceUID id); u32 __KernelGetThreadPrio(SceUID id);
bool __KernelThreadSortPriority(SceUID thread1, SceUID thread2); bool __KernelThreadSortPriority(SceUID thread1, SceUID thread2);
bool __KernelIsDispatchEnabled();
void __KernelIdle(); void __KernelIdle();