Kernel: Kernel threads can beget kernel threads.

Fixes #7687.
This commit is contained in:
Unknown W. Brackets 2019-03-23 12:05:06 -07:00
parent 737be61f9a
commit f244b390ae
4 changed files with 12 additions and 9 deletions

View file

@ -1934,7 +1934,8 @@ static void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 ret
if (module->nm.module_start_func != 0 && module->nm.module_start_func != (u32)-1)
{
entryAddr = module->nm.module_start_func;
attribute = module->nm.module_start_thread_attr;
if (module->nm.module_start_thread_attr != 0)
attribute = module->nm.module_start_thread_attr;
}
else if ((entryAddr == (u32)-1) || entryAddr == module->memoryBlockAddr - 1)
{
@ -1967,7 +1968,7 @@ static void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 ret
stacksize = module->nm.module_start_thread_stacksize;
}
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0);
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0, (module->nm.attribute & 0x1000) != 0);
__KernelStartThreadValidate(threadID, argsize, argAddr);
__KernelSetThreadRA(threadID, NID_MODULERETURN);
__KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "started module");
@ -2049,7 +2050,7 @@ static u32 sceKernelStopModule(u32 moduleId, u32 argSize, u32 argAddr, u32 retur
if (Memory::IsValidAddress(stopFunc))
{
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, stopFunc, priority, stacksize, attr, 0);
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, stopFunc, priority, stacksize, attr, 0, (module->nm.attribute & 0x1000) != 0);
__KernelStartThreadValidate(threadID, argSize, argAddr);
__KernelSetThreadRA(threadID, NID_MODULERETURN);
__KernelWaitCurThread(WAITTYPE_MODULE, moduleId, 1, 0, false, "stopped module");
@ -2132,7 +2133,7 @@ u32 hleKernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize,
}
if (Memory::IsValidAddress(stopFunc)) {
SceUID threadID = __KernelCreateThread(module->nm.name, moduleID, stopFunc, priority, stacksize, attr, 0);
SceUID threadID = __KernelCreateThread(module->nm.name, moduleID, stopFunc, priority, stacksize, attr, 0, (module->nm.attribute & 0x1000) != 0);
__KernelStartThreadValidate(threadID, argSize, argp);
__KernelSetThreadRA(threadID, NID_MODULERETURN);
__KernelWaitCurThread(WAITTYPE_MODULE, moduleID, 1, 0, false, "unloadstopped module");

View file

@ -1943,7 +1943,7 @@ SceUID __KernelCreateThreadInternal(const char *threadName, SceUID moduleID, u32
return id;
}
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) {
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr, bool allowKernel) {
if (threadName == nullptr)
return hleReportError(SCEKERNEL, SCE_KERNEL_ERROR_ERROR, "NULL thread name");
@ -1960,7 +1960,7 @@ int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32
if (entry != 0)
return hleReportError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "invalid thread entry %08x", entry);
}
if ((attr & ~PSP_THREAD_ATTR_USER_MASK) != 0)
if ((attr & ~PSP_THREAD_ATTR_USER_MASK) != 0 && !allowKernel)
return hleReportWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ATTR, "illegal thread attributes %08x", attr);
if ((attr & ~PSP_THREAD_ATTR_SUPPORTED) != 0)
@ -1996,7 +1996,9 @@ int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32
}
int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) {
return __KernelCreateThread(threadName, __KernelGetCurThreadModuleId(), entry, prio, stacksize, attr, optionAddr);
Thread *cur = __GetCurrentThread();
bool allowKernel = cur ? (cur->nt.attr & PSP_THREAD_ATTR_KERNEL) != 0 : false;
return __KernelCreateThread(threadName, __KernelGetCurThreadModuleId(), entry, prio, stacksize, attr, optionAddr, allowKernel);
}
int __KernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr, bool forceArgs) {

View file

@ -31,7 +31,7 @@ class DebugInterface;
int sceKernelChangeThreadPriority(SceUID threadID, int priority);
SceUID __KernelCreateThreadInternal(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr);
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr);
int __KernelCreateThread(const char *threadName, SceUID moduleID, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr, bool allowKernel);
int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr);
int sceKernelDelayThread(u32 usec);
int sceKernelDelayThreadCB(u32 usec);

View file

@ -174,7 +174,7 @@ u32 sceNetAdhocInit() {
// TODO: Should use a separated threads for friendFinder, matchingEvent, and matchingInput and created on AdhocctlInit & AdhocMatchingStart instead of here
#define PSP_THREAD_ATTR_KERNEL 0x00001000 // PSP_THREAD_ATTR_KERNEL is located in sceKernelThread.cpp instead of sceKernelThread.h :(
//threadAdhocID = __KernelCreateThreadInternal("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x30, 4096, PSP_THREAD_ATTR_KERNEL);
threadAdhocID = __KernelCreateThread("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x10, 0x1000, 0, 0);
threadAdhocID = __KernelCreateThread("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x10, 0x1000, 0, 0, false);
if (threadAdhocID > 0) {
__KernelStartThread(threadAdhocID, 0, 0);
}