pm: fix critical bugs where 1.0(?) titles not in the list have scheduling mode misconfigured
Also fix the comments. Thanks @fincs
This commit is contained in:
parent
3a0418e279
commit
4e12453fff
@ -4,6 +4,9 @@
|
|||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "luma.h"
|
#include "luma.h"
|
||||||
|
|
||||||
|
#define CPUTIME_MULTI_MASK BIT(7)
|
||||||
|
#define CPUTIME_SINGLE_MASK 0
|
||||||
|
|
||||||
typedef s64 ReslimitValues[10];
|
typedef s64 ReslimitValues[10];
|
||||||
|
|
||||||
static const ResourceLimitType g_reslimitInitOrder[10] = {
|
static const ResourceLimitType g_reslimitInitOrder[10] = {
|
||||||
@ -189,20 +192,23 @@ static ReslimitValues g_n3dsReslimitValues[4] = {
|
|||||||
Both modes pause threads they don't want to run in thread selection, and unpause them when needed.
|
Both modes pause threads they don't want to run in thread selection, and unpause them when needed.
|
||||||
If the threads that are intended to be paused is running an SVC, the pause will happen *after* SVC return.
|
If the threads that are intended to be paused is running an SVC, the pause will happen *after* SVC return.
|
||||||
|
|
||||||
Mode0 (unsure)
|
Mode0 "multi"
|
||||||
|
|
||||||
Starting by "sysmodule" threads, alternatively allow (if preemptible) only sysmodule threads,
|
Starting by "sysmodule" threads, alternatively allow (if preemptible) only sysmodule threads,
|
||||||
and then only application threads to run.
|
and then only application threads to run.
|
||||||
The latter has an exception; if "sysmodule" threads have run for less than 2usec, they
|
The latter has an exception; if "sysmodule" threads have run for less than 8usec (value is a kernel bug), they
|
||||||
are unpaused an allowed to run instead.
|
are unpaused an allowed to run instead.
|
||||||
|
|
||||||
This happens at a rate of 1ms * (cpuTime/100).
|
This happens at a rate of 2ms * (cpuTime/100).
|
||||||
|
|
||||||
Mode1
|
|
||||||
|
Mode1 "single"
|
||||||
|
|
||||||
|
This mode is half-broken due to a kernel bug (when "current thread" is the priority 0 kernel thread).
|
||||||
|
|
||||||
When this mode is enabled, only one application thread is allowed to be created on core1.
|
When this mode is enabled, only one application thread is allowed to be created on core1.
|
||||||
|
|
||||||
This divides the core1 time into slices of 12.5ms.
|
This divides the core1 time into slices of 25ms.
|
||||||
|
|
||||||
The "application" thread is given cpuTime% of the slice.
|
The "application" thread is given cpuTime% of the slice.
|
||||||
The "sysmodules" threads are given a total of (90 - cpuTime)% of the slice.
|
The "sysmodules" threads are given a total of (90 - cpuTime)% of the slice.
|
||||||
@ -318,22 +324,23 @@ void setAppCpuTimeLimitAndSchedModeFromDescriptor(u64 titleId, u16 descriptor)
|
|||||||
- app has a non-0 cputime descriptor in exhdr: maximum core1 cputime reslimit and scheduling
|
- app has a non-0 cputime descriptor in exhdr: maximum core1 cputime reslimit and scheduling
|
||||||
mode are set according to it. Current reslimit is set to 0. SetAppResourceLimit *is* needed
|
mode are set according to it. Current reslimit is set to 0. SetAppResourceLimit *is* needed
|
||||||
to use core1.
|
to use core1.
|
||||||
- app has a 0 cputime descriptor: maximum is set to 80.
|
- app has a 0 cputime descriptor: maximum is set to 80, scheduling mode to "single" (broken).
|
||||||
Current reslimit is set to 0, and SetAppResourceLimit *is* needed
|
Current reslimit is set to 0, and SetAppResourceLimit *is* also needed
|
||||||
to use core1, **EXCEPT** for an hardcoded set of titles.
|
to use core1, **EXCEPT** for an hardcoded set of titles.
|
||||||
*/
|
*/
|
||||||
u8 cpuTime = (u8)descriptor;
|
u8 cpuTime = (u8)descriptor;
|
||||||
assertSuccess(setAppCpuTimeLimit(0)); // remove preemption first.
|
assertSuccess(setAppCpuTimeLimit(0)); // remove preemption first.
|
||||||
|
|
||||||
g_manager.cpuTimeBase = 0;
|
g_manager.cpuTimeBase = 0;
|
||||||
|
u32 currentValueToSet = g_manager.cpuTimeBase; // 0
|
||||||
|
|
||||||
if (cpuTime != 0) {
|
if (cpuTime == 0) {
|
||||||
// Set core1 scheduling mode
|
// 2.0 apps have this exheader field correctly filled, very often to 0x9E (1.0 titles don't).
|
||||||
g_manager.maxAppCpuTime = cpuTime & 0x7F;
|
|
||||||
assertSuccess(svcKernelSetState(6, 3, (cpuTime & 0x80) ? 0LL : 1LL));
|
|
||||||
} else {
|
|
||||||
u32 titleUid = ((u32)titleId >> 8) & 0xFFFFF;
|
u32 titleUid = ((u32)titleId >> 8) & 0xFFFFF;
|
||||||
g_manager.maxAppCpuTime = 80;
|
|
||||||
|
// Default setting is 80% max "single", with a current value of 0
|
||||||
|
cpuTime = CPUTIME_SINGLE_MASK | 80;
|
||||||
|
|
||||||
static const u32 numOverrides = sizeof(g_startCpuTimeOverrides) / sizeof(g_startCpuTimeOverrides[0]);
|
static const u32 numOverrides = sizeof(g_startCpuTimeOverrides) / sizeof(g_startCpuTimeOverrides[0]);
|
||||||
|
|
||||||
if (titleUid >= g_startCpuTimeOverrides[0].titleUid && titleUid <= g_startCpuTimeOverrides[numOverrides - 1].titleUid) {
|
if (titleUid >= g_startCpuTimeOverrides[0].titleUid && titleUid <= g_startCpuTimeOverrides[numOverrides - 1].titleUid) {
|
||||||
@ -341,15 +348,26 @@ void setAppCpuTimeLimitAndSchedModeFromDescriptor(u64 titleId, u16 descriptor)
|
|||||||
for (u32 i = 0; i < numOverrides && titleUid < g_startCpuTimeOverrides[i].titleUid; i++);
|
for (u32 i = 0; i < numOverrides && titleUid < g_startCpuTimeOverrides[i].titleUid; i++);
|
||||||
if (i < numOverrides) {
|
if (i < numOverrides) {
|
||||||
if (g_startCpuTimeOverrides[i].value > 100 && g_startCpuTimeOverrides[i].value < 200) {
|
if (g_startCpuTimeOverrides[i].value > 100 && g_startCpuTimeOverrides[i].value < 200) {
|
||||||
assertSuccess(svcKernelSetState(6, 3, 0LL));
|
cpuTime = CPUTIME_MULTI_MASK | 80; // "multi", max 80%
|
||||||
assertSuccess(setAppCpuTimeLimit(g_startCpuTimeOverrides[i].value - 100));
|
currentValueToSet = g_startCpuTimeOverrides[i].value - 100;
|
||||||
} else {
|
} else {
|
||||||
assertSuccess(svcKernelSetState(6, 3, 1LL));
|
cpuTime = CPUTIME_SINGLE_MASK | 80; // "single", max 80%
|
||||||
assertSuccess(setAppCpuTimeLimit(g_startCpuTimeOverrides[i].value));
|
currentValueToSet = g_startCpuTimeOverrides[i].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set core1 scheduling mode
|
||||||
|
assertSuccess(svcKernelSetState(6, 3, (cpuTime & CPUTIME_MULTI_MASK) ? 0LL : 1LL));
|
||||||
|
|
||||||
|
// Set max value (limit)
|
||||||
|
g_manager.maxAppCpuTime = cpuTime & 0x7F;
|
||||||
|
|
||||||
|
// Set current value (for 1.0 apps)
|
||||||
|
if (currentValueToSet != 0) {
|
||||||
|
assertSuccess(setAppCpuTimeLimit(currentValueToSet));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SetAppResourceLimit(u32 mbz, ResourceLimitType category, u32 value, u64 mbz2)
|
Result SetAppResourceLimit(u32 mbz, ResourceLimitType category, u32 value, u64 mbz2)
|
||||||
|
Reference in New Issue
Block a user