kernel: Improve GetInfo readability and update to 13.0.0 (#2900)

* kernel: Define InfoTYpe and make it less obscure when reading GetInfo

Also map ThreadTickCount to 25 instead of 0xF0000002 like 13.x kernel.

* kernel: Implement GetInfo IsApplication

* kernel: Implement GetInfo FreeThreadCount
This commit is contained in:
Mary 2021-12-05 00:23:26 +01:00 committed by GitHub
parent f39fce8f54
commit 2ab777885b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 47 deletions

View file

@ -404,7 +404,7 @@ namespace Ryujinx.HLE.HOS
lock (KernelContext.Processes) lock (KernelContext.Processes)
{ {
// Terminate application. // Terminate application.
foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.IsApplication))
{ {
process.Terminate(); process.Terminate();
process.DecrementReferenceCount(); process.DecrementReferenceCount();
@ -415,7 +415,7 @@ namespace Ryujinx.HLE.HOS
// Terminate HLE services (must be done after the application is already terminated, // Terminate HLE services (must be done after the application is already terminated,
// otherwise the application will receive errors due to service termination). // otherwise the application will receive errors due to service termination).
foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.IsApplication))
{ {
process.Terminate(); process.Terminate();
process.DecrementReferenceCount(); process.DecrementReferenceCount();
@ -461,7 +461,7 @@ namespace Ryujinx.HLE.HOS
{ {
foreach (KProcess process in KernelContext.Processes.Values) foreach (KProcess process in KernelContext.Processes.Values)
{ {
if (process.Flags.HasFlag(ProcessCreationFlags.IsApplication)) if (process.IsApplication)
{ {
// Only game process should be paused. // Only game process should be paused.
process.SetActivity(pause); process.SetActivity(pause);

View file

@ -60,6 +60,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KProcessCapabilities Capabilities { get; private set; } public KProcessCapabilities Capabilities { get; private set; }
public ulong TitleId { get; private set; } public ulong TitleId { get; private set; }
public bool IsApplication { get; private set; }
public long Pid { get; private set; } public long Pid { get; private set; }
private long _creationTimestamp; private long _creationTimestamp;
@ -193,6 +194,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_memRegion = memRegion; _memRegion = memRegion;
_contextFactory = contextFactory ?? new ProcessContextFactory(); _contextFactory = contextFactory ?? new ProcessContextFactory();
_customThreadStart = customThreadStart; _customThreadStart = customThreadStart;
IsApplication = creationInfo.Flags.HasFlag(ProcessCreationFlags.IsApplication);
ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.SystemResourcePagesCount, memRegion); ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.SystemResourcePagesCount, memRegion);

View file

@ -0,0 +1,33 @@
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{
enum InfoType : uint
{
CoreMask,
PriorityMask,
AliasRegionAddress,
AliasRegionSize,
HeapRegionAddress,
HeapRegionSize,
TotalMemorySize,
UsedMemorySize,
DebuggerAttached,
ResourceLimit,
IdleTickCount,
RandomEntropy,
AslrRegionAddress,
AslrRegionSize,
StackRegionAddress,
StackRegionSize,
SystemResourceSizeTotal,
SystemResourceSizeUsed,
ProgramId,
// NOTE: Added in 4.0.0, removed in 5.0.0.
InitialProcessIdRange,
UserExceptionContextAddress,
TotalNonSystemMemorySize,
UsedNonSystemMemorySize,
IsApplication,
FreeThreadCount,
ThreadTickCount
}
}

View file

@ -1575,30 +1575,32 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Logger.Warning?.Print(LogClass.KernelSvc, str); Logger.Warning?.Print(LogClass.KernelSvc, str);
} }
public KernelResult GetInfo(uint id, int handle, long subId, out long value) public KernelResult GetInfo(InfoType id, int handle, long subId, out long value)
{ {
value = 0; value = 0;
switch (id) switch (id)
{ {
case 0: case InfoType.CoreMask:
case 1: case InfoType.PriorityMask:
case 2: case InfoType.AliasRegionAddress:
case 3: case InfoType.AliasRegionSize:
case 4: case InfoType.HeapRegionAddress:
case 5: case InfoType.HeapRegionSize:
case 6: case InfoType.TotalMemorySize:
case 7: case InfoType.UsedMemorySize:
case 12: case InfoType.AslrRegionAddress:
case 13: case InfoType.AslrRegionSize:
case 14: case InfoType.StackRegionAddress:
case 15: case InfoType.StackRegionSize:
case 16: case InfoType.SystemResourceSizeTotal:
case 17: case InfoType.SystemResourceSizeUsed:
case 18: case InfoType.ProgramId:
case 20: case InfoType.UserExceptionContextAddress:
case 21: case InfoType.TotalNonSystemMemorySize:
case 22: case InfoType.UsedNonSystemMemorySize:
case InfoType.IsApplication:
case InfoType.FreeThreadCount:
{ {
if (subId != 0) if (subId != 0)
{ {
@ -1616,35 +1618,35 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
switch (id) switch (id)
{ {
case 0: value = process.Capabilities.AllowedCpuCoresMask; break; case InfoType.CoreMask: value = process.Capabilities.AllowedCpuCoresMask; break;
case 1: value = process.Capabilities.AllowedThreadPriosMask; break; case InfoType.PriorityMask: value = process.Capabilities.AllowedThreadPriosMask; break;
case 2: value = (long)process.MemoryManager.AliasRegionStart; break; case InfoType.AliasRegionAddress: value = (long)process.MemoryManager.AliasRegionStart; break;
case 3: case InfoType.AliasRegionSize:
value = (long)(process.MemoryManager.AliasRegionEnd - value = (long)(process.MemoryManager.AliasRegionEnd -
process.MemoryManager.AliasRegionStart); break; process.MemoryManager.AliasRegionStart); break;
case 4: value = (long)process.MemoryManager.HeapRegionStart; break; case InfoType.HeapRegionAddress: value = (long)process.MemoryManager.HeapRegionStart; break;
case 5: case InfoType.HeapRegionSize:
value = (long)(process.MemoryManager.HeapRegionEnd - value = (long)(process.MemoryManager.HeapRegionEnd -
process.MemoryManager.HeapRegionStart); break; process.MemoryManager.HeapRegionStart); break;
case 6: value = (long)process.GetMemoryCapacity(); break; case InfoType.TotalMemorySize: value = (long)process.GetMemoryCapacity(); break;
case 7: value = (long)process.GetMemoryUsage(); break; case InfoType.UsedMemorySize: value = (long)process.GetMemoryUsage(); break;
case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; case InfoType.AslrRegionAddress: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break;
case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; case InfoType.AslrRegionSize: value = (long)process.MemoryManager.GetAddrSpaceSize(); break;
case 14: value = (long)process.MemoryManager.StackRegionStart; break; case InfoType.StackRegionAddress: value = (long)process.MemoryManager.StackRegionStart; break;
case 15: case InfoType.StackRegionSize:
value = (long)(process.MemoryManager.StackRegionEnd - value = (long)(process.MemoryManager.StackRegionEnd -
process.MemoryManager.StackRegionStart); break; process.MemoryManager.StackRegionStart); break;
case 16: value = (long)process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break; case InfoType.SystemResourceSizeTotal: value = (long)process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break;
case 17: case InfoType.SystemResourceSizeUsed:
if (process.PersonalMmHeapPagesCount != 0) if (process.PersonalMmHeapPagesCount != 0)
{ {
value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize; value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize;
@ -1652,19 +1654,33 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
break; break;
case 18: value = (long)process.TitleId; break; case InfoType.ProgramId: value = (long)process.TitleId; break;
case 20: value = (long)process.UserExceptionContextAddress; break; case InfoType.UserExceptionContextAddress: value = (long)process.UserExceptionContextAddress; break;
case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; case InfoType.TotalNonSystemMemorySize: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break;
case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; case InfoType.UsedNonSystemMemorySize: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break;
case InfoType.IsApplication: value = process.IsApplication ? 1 : 0; break;
case InfoType.FreeThreadCount:
if (process.ResourceLimit != null)
{
value = process.ResourceLimit.GetLimitValue(LimitableResource.Thread) - process.ResourceLimit.GetCurrentValue(LimitableResource.Thread);
}
else
{
value = 0;
}
break;
} }
break; break;
} }
case 8: case InfoType.DebuggerAttached:
{ {
if (handle != 0) if (handle != 0)
{ {
@ -1681,7 +1697,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
break; break;
} }
case 9: case InfoType.ResourceLimit:
{ {
if (handle != 0) if (handle != 0)
{ {
@ -1713,7 +1729,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
break; break;
} }
case 10: case InfoType.IdleTickCount:
{ {
if (handle != 0) if (handle != 0)
{ {
@ -1732,7 +1748,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
break; break;
} }
case 11: case InfoType.RandomEntropy:
{ {
if (handle != 0) if (handle != 0)
{ {
@ -1751,7 +1767,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
break; break;
} }
case 0xf0000002u: case InfoType.ThreadTickCount:
{ {
if (subId < -1 || subId > 3) if (subId < -1 || subId > 3)
{ {

View file

@ -257,7 +257,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
public KernelResult GetInfo32( public KernelResult GetInfo32(
[R(0)] uint subIdLow, [R(0)] uint subIdLow,
[R(1)] uint id, [R(1)] InfoType id,
[R(2)] int handle, [R(2)] int handle,
[R(3)] uint subIdHigh, [R(3)] uint subIdHigh,
[R(1)] out uint valueLow, [R(1)] out uint valueLow,

View file

@ -247,7 +247,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
_syscall.OutputDebugString(strPtr, size); _syscall.OutputDebugString(strPtr, size);
} }
public KernelResult GetInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) public KernelResult GetInfo64([R(1)] InfoType id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value)
{ {
return _syscall.GetInfo(id, handle, subId, out value); return _syscall.GetInfo(id, handle, subId, out value);
} }