[Ryujinx.HLE] Address dotnet-format issues (#5380)
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address or silence dotnet format IDE1006 warnings * Address dotnet format CA1816 warnings * Address or silence dotnet format CA2208 warnings * Address or silence dotnet format CA1806 and a few CA1854 warnings * Address dotnet format CA2211 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Make dotnet format succeed in style mode * Address or silence dotnet format CA2211 warnings * Address review comments * Address dotnet format CA2208 warnings properly * Make ProcessResult readonly * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add previously silenced warnings back I have no clue how these disappeared * Revert formatting changes for while and for-loops * Format if-blocks correctly * Run dotnet format style after rebase * Run dotnet format whitespace after rebase * Run dotnet format style after rebase * Run dotnet format analyzers after rebase * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Fix a few disabled warnings * Fix naming rule violation, Convert shader properties to auto-property and convert values to const * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Run dotnet format after rebase * Use using declaration instead of block syntax * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Fix naming rule violations * Fix typo * Add trailing commas, use targeted new and use array initializer * Fix build issues * Fix remaining build issues * Remove SuppressMessage for CA1069 where possible * Address dotnet format issues * Address formatting issues Co-authored-by: Ac_K <acoustik666@gmail.com> * Add GetHashCode implementation for RenderingSurfaceInfo * Explicitly silence CA1822 for every affected method in Syscall * Address formatting issues in Demangler.cs * Address review feedback Co-authored-by: Ac_K <acoustik666@gmail.com> * Revert marking service methods as static * Next dotnet format pass * Address review feedback --------- Co-authored-by: Ac_K <acoustik666@gmail.com>
This commit is contained in:
parent
fec8291c17
commit
326749498b
1015 changed files with 8173 additions and 7615 deletions
|
@ -4,4 +4,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
{
|
||||
void TimeUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
|
||||
public KResourceLimit(KernelContext context) : base(context)
|
||||
{
|
||||
_current = new long[(int)LimitableResource.Count];
|
||||
_limit = new long[(int)LimitableResource.Count];
|
||||
_current = new long[(int)LimitableResource.Count];
|
||||
_limit = new long[(int)LimitableResource.Count];
|
||||
_current2 = new long[(int)LimitableResource.Count];
|
||||
_peak = new long[(int)LimitableResource.Count];
|
||||
_peak = new long[(int)LimitableResource.Count];
|
||||
|
||||
_lock = new object();
|
||||
|
||||
|
@ -185,4 +185,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
return (int)resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,4 +32,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
MemoryArrange.MemoryArrange4GiBAppletDev => 2048 * MiB,
|
||||
MemoryArrange.MemoryArrange6GiB or
|
||||
MemoryArrange.MemoryArrange8GiB => 4916 * MiB,
|
||||
_ => throw new ArgumentException($"Invalid memory arrange \"{arrange}\".")
|
||||
_ => throw new ArgumentException($"Invalid memory arrange \"{arrange}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
MemoryArrange.MemoryArrange6GiB => 562 * MiB,
|
||||
MemoryArrange.MemoryArrange6GiBAppletDev or
|
||||
MemoryArrange.MemoryArrange8GiB => 2193 * MiB,
|
||||
_ => throw new ArgumentException($"Invalid memory arrange \"{arrange}\".")
|
||||
_ => throw new ArgumentException($"Invalid memory arrange \"{arrange}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
MemorySize.MemorySize4GiB => 4 * GiB,
|
||||
MemorySize.MemorySize6GiB => 6 * GiB,
|
||||
MemorySize.MemorySize8GiB => 8 * GiB,
|
||||
_ => throw new ArgumentException($"Invalid memory size \"{size}\".")
|
||||
_ => throw new ArgumentException($"Invalid memory size \"{size}\"."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
_waitingObjects = new List<WaitingObject>();
|
||||
_keepRunning = true;
|
||||
|
||||
Thread work = new Thread(WaitAndCheckScheduledObjects)
|
||||
Thread work = new(WaitAndCheckScheduledObjects)
|
||||
{
|
||||
Name = "HLE.TimeManager"
|
||||
Name = "HLE.TimeManager",
|
||||
};
|
||||
|
||||
work.Start();
|
||||
|
@ -83,7 +83,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
|
||||
private void WaitAndCheckScheduledObjects()
|
||||
{
|
||||
SpinWait spinWait = new SpinWait();
|
||||
SpinWait spinWait = new();
|
||||
WaitingObject next;
|
||||
|
||||
using (_waitEvent = new AutoResetEvent(false))
|
||||
|
@ -215,4 +215,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
_waitEvent?.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,20 +9,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
private readonly struct MemoryRegion
|
||||
{
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
public ulong Size { get; }
|
||||
|
||||
public ulong EndAddress => Address + Size;
|
||||
|
||||
public MemoryRegion(ulong address, ulong size)
|
||||
{
|
||||
Address = address;
|
||||
Size = size;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitializeResourceLimit(KResourceLimit resourceLimit, MemorySize size)
|
||||
{
|
||||
void EnsureSuccess(Result result)
|
||||
static void EnsureSuccess(Result result)
|
||||
{
|
||||
if (result != Result.Success)
|
||||
{
|
||||
|
@ -32,11 +32,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
|
||||
ulong ramSize = KSystemControl.GetDramSize(size);
|
||||
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Memory, (long)ramSize));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Thread, 800));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Event, 700));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Memory, (long)ramSize));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Thread, 800));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Event, 700));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 200));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Session, 900));
|
||||
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Session, 900));
|
||||
|
||||
if (!resourceLimit.Reserve(LimitableResource.Memory, 0) ||
|
||||
!resourceLimit.Reserve(LimitableResource.Memory, 0x60000))
|
||||
|
@ -47,9 +47,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
|
||||
public static KMemoryRegionManager[] GetMemoryRegions(MemorySize size, MemoryArrange arrange)
|
||||
{
|
||||
ulong poolEnd = KSystemControl.GetDramEndAddress(size);
|
||||
ulong poolEnd = KSystemControl.GetDramEndAddress(size);
|
||||
ulong applicationPoolSize = KSystemControl.GetApplicationPoolSize(arrange);
|
||||
ulong appletPoolSize = KSystemControl.GetAppletPoolSize(arrange);
|
||||
ulong appletPoolSize = KSystemControl.GetAppletPoolSize(arrange);
|
||||
|
||||
MemoryRegion servicePool;
|
||||
MemoryRegion nvServicesPool;
|
||||
|
@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
ulong nvServicesPoolEnd = applicationPool.Address - appletPoolSize;
|
||||
|
||||
nvServicesPool = new MemoryRegion(nvServicesPoolEnd - nvServicesPoolSize, nvServicesPoolSize);
|
||||
appletPool = new MemoryRegion(nvServicesPoolEnd, appletPoolSize);
|
||||
appletPool = new MemoryRegion(nvServicesPoolEnd, appletPoolSize);
|
||||
|
||||
// Note: There is an extra region used by the kernel, however
|
||||
// since we are doing HLE we are not going to use that memory, so give all
|
||||
|
@ -72,12 +72,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
|
||||
servicePool = new MemoryRegion(DramMemoryMap.SlabHeapEnd, servicePoolSize);
|
||||
|
||||
return new KMemoryRegionManager[]
|
||||
return new[]
|
||||
{
|
||||
GetMemoryRegion(applicationPool),
|
||||
GetMemoryRegion(appletPool),
|
||||
GetMemoryRegion(servicePool),
|
||||
GetMemoryRegion(nvServicesPool)
|
||||
GetMemoryRegion(nvServicesPool),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -86,4 +86,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
return new KMemoryRegionManager(region.Address, region.Size, region.EndAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
return false;
|
||||
}
|
||||
|
||||
public static bool KernelToUser<T>(ulong address, T value) where T: unmanaged
|
||||
public static bool KernelToUser<T>(ulong address, T value) where T : unmanaged
|
||||
{
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -70,4 +70,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
{
|
||||
enum LimitableResource : byte
|
||||
{
|
||||
Memory = 0,
|
||||
Thread = 1,
|
||||
Event = 2,
|
||||
Memory = 0,
|
||||
Thread = 1,
|
||||
Event = 2,
|
||||
TransferMemory = 3,
|
||||
Session = 4,
|
||||
Session = 4,
|
||||
|
||||
Count = 5
|
||||
Count = 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
MemoryArrange4GiBSystemDev,
|
||||
MemoryArrange6GiB,
|
||||
MemoryArrange6GiBAppletDev,
|
||||
MemoryArrange8GiB
|
||||
MemoryArrange8GiB,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
{
|
||||
MemorySize4GiB = 0,
|
||||
MemorySize6GiB = 1,
|
||||
MemorySize8GiB = 2
|
||||
MemorySize8GiB = 2,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
class MersenneTwister
|
||||
{
|
||||
private int _index;
|
||||
private uint[] _mt;
|
||||
private readonly uint[] _mt;
|
||||
|
||||
public MersenneTwister(uint seed)
|
||||
{
|
||||
|
@ -46,12 +46,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
// If Range is already power of 2, subtract one to use log2(Range) directly.
|
||||
int rangeLog2 = nextRangeLog2 - (BitOperations.IsPow2(range) ? 1 : 0);
|
||||
|
||||
int parts = rangeLog2 > 32 ? 2 : 1;
|
||||
int parts = rangeLog2 > 32 ? 2 : 1;
|
||||
int bitsPerPart = rangeLog2 / parts;
|
||||
|
||||
int fullParts = parts - (rangeLog2 - parts * bitsPerPart);
|
||||
|
||||
uint mask = 0xffffffffu >> (32 - bitsPerPart);
|
||||
uint mask = 0xffffffffu >> (32 - bitsPerPart);
|
||||
uint maskPlus1 = 0xffffffffu >> (31 - bitsPerPart);
|
||||
|
||||
long randomNumber;
|
||||
|
@ -66,9 +66,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
}
|
||||
|
||||
private long GenRandomNumber(
|
||||
int parts,
|
||||
int fullParts,
|
||||
int bitsPerPart,
|
||||
int parts,
|
||||
int fullParts,
|
||||
int bitsPerPart,
|
||||
uint mask,
|
||||
uint maskPlus1)
|
||||
{
|
||||
|
@ -79,13 +79,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
|||
for (; part < fullParts; part++)
|
||||
{
|
||||
randomNumber <<= bitsPerPart;
|
||||
randomNumber |= GenRandomNumber() & mask;
|
||||
randomNumber |= GenRandomNumber() & mask;
|
||||
}
|
||||
|
||||
for (; part < parts; part++)
|
||||
{
|
||||
randomNumber <<= bitsPerPart + 1;
|
||||
randomNumber |= GenRandomNumber() & maskPlus1;
|
||||
randomNumber |= GenRandomNumber() & maskPlus1;
|
||||
}
|
||||
|
||||
return randomNumber;
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
NotInitialized,
|
||||
Open,
|
||||
ClientDisconnected,
|
||||
ServerDisconnected
|
||||
ServerDisconnected,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
class KBufferDescriptor
|
||||
{
|
||||
public ulong ClientAddress { get; }
|
||||
public ulong ServerAddress { get; }
|
||||
public ulong Size { get; }
|
||||
public MemoryState State { get; }
|
||||
public ulong ClientAddress { get; }
|
||||
public ulong ServerAddress { get; }
|
||||
public ulong Size { get; }
|
||||
public MemoryState State { get; }
|
||||
|
||||
public KBufferDescriptor(ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
ClientAddress = src;
|
||||
ServerAddress = dst;
|
||||
Size = size;
|
||||
State = state;
|
||||
Size = size;
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
private const int MaxInternalBuffersCount = 8;
|
||||
|
||||
private List<KBufferDescriptor> _sendBufferDescriptors;
|
||||
private List<KBufferDescriptor> _receiveBufferDescriptors;
|
||||
private List<KBufferDescriptor> _exchangeBufferDescriptors;
|
||||
private readonly List<KBufferDescriptor> _sendBufferDescriptors;
|
||||
private readonly List<KBufferDescriptor> _receiveBufferDescriptors;
|
||||
private readonly List<KBufferDescriptor> _exchangeBufferDescriptors;
|
||||
|
||||
public KBufferDescriptorTable()
|
||||
{
|
||||
_sendBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
_receiveBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
_sendBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
_receiveBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
_exchangeBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return Add(_exchangeBufferDescriptors, src, dst, size, state);
|
||||
}
|
||||
|
||||
private Result Add(List<KBufferDescriptor> list, ulong src, ulong dst, ulong size, MemoryState state)
|
||||
private static Result Add(List<KBufferDescriptor> list, ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
if (list.Count < MaxInternalBuffersCount)
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return CopyToClient(memoryManager, _exchangeBufferDescriptors);
|
||||
}
|
||||
|
||||
private Result CopyToClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
private static Result CopyToClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
{
|
||||
foreach (KBufferDescriptor desc in list)
|
||||
{
|
||||
|
@ -67,11 +67,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
switch (desc.State)
|
||||
{
|
||||
case MemoryState.IpcBuffer0: stateMask = MemoryState.IpcSendAllowedType0; break;
|
||||
case MemoryState.IpcBuffer1: stateMask = MemoryState.IpcSendAllowedType1; break;
|
||||
case MemoryState.IpcBuffer3: stateMask = MemoryState.IpcSendAllowedType3; break;
|
||||
|
||||
default: return KernelResult.InvalidCombination;
|
||||
case MemoryState.IpcBuffer0:
|
||||
stateMask = MemoryState.IpcSendAllowedType0;
|
||||
break;
|
||||
case MemoryState.IpcBuffer1:
|
||||
stateMask = MemoryState.IpcSendAllowedType1;
|
||||
break;
|
||||
case MemoryState.IpcBuffer3:
|
||||
stateMask = MemoryState.IpcSendAllowedType3;
|
||||
break;
|
||||
default:
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
MemoryAttribute attributeMask = MemoryAttribute.Borrowed | MemoryAttribute.Uncached;
|
||||
|
@ -82,7 +88,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
|
||||
ulong clientAddrTruncated = BitUtils.AlignDown<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
|
||||
ulong clientAddrRounded = BitUtils.AlignUp<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
|
||||
ulong clientAddrRounded = BitUtils.AlignUp<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
|
||||
|
||||
// Check if address is not aligned, in this case we need to perform 2 copies.
|
||||
if (clientAddrTruncated != clientAddrRounded)
|
||||
|
@ -114,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
ulong serverEndAddr = desc.ServerAddress + desc.Size;
|
||||
|
||||
ulong clientEndAddrTruncated = BitUtils.AlignDown<ulong>(clientEndAddr, (ulong)KPageTableBase.PageSize);
|
||||
ulong clientEndAddrRounded = BitUtils.AlignUp<ulong>(clientEndAddr, KPageTableBase.PageSize);
|
||||
ulong clientEndAddrRounded = BitUtils.AlignUp<ulong>(clientEndAddr, KPageTableBase.PageSize);
|
||||
ulong serverEndAddrTruncated = BitUtils.AlignDown<ulong>(serverEndAddr, (ulong)KPageTableBase.PageSize);
|
||||
|
||||
if (clientEndAddrTruncated < clientEndAddrRounded &&
|
||||
|
@ -159,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return UnmapServer(memoryManager, _exchangeBufferDescriptors);
|
||||
}
|
||||
|
||||
private Result UnmapServer(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
private static Result UnmapServer(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
{
|
||||
foreach (KBufferDescriptor descriptor in list)
|
||||
{
|
||||
|
@ -196,7 +202,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return RestoreClient(memoryManager, _exchangeBufferDescriptors);
|
||||
}
|
||||
|
||||
private Result RestoreClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
private static Result RestoreClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
{
|
||||
foreach (KBufferDescriptor descriptor in list)
|
||||
{
|
||||
|
@ -214,4 +220,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
public KClientPort(KernelContext context, KPort parent, int maxSessions) : base(context)
|
||||
{
|
||||
_maxSessions = maxSessions;
|
||||
_parent = parent;
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
public Result Connect(out KClientSession clientSession)
|
||||
|
@ -39,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return KernelResult.SessionCountExceeded;
|
||||
}
|
||||
|
||||
KSession session = new KSession(KernelContext, this);
|
||||
KSession session = new(KernelContext, this);
|
||||
|
||||
Result result = _parent.EnqueueIncomingSession(session.ServerSession);
|
||||
|
||||
|
@ -75,7 +75,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return KernelResult.SessionCountExceeded;
|
||||
}
|
||||
|
||||
KLightSession session = new KLightSession(KernelContext);
|
||||
KLightSession session = new(KernelContext);
|
||||
|
||||
Result result = _parent.EnqueueIncomingLightSession(session.ServerSession);
|
||||
|
||||
|
@ -133,7 +133,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
KAutoObject foundObj = FindNamedObject(context, name);
|
||||
|
||||
if (!(foundObj is KClientPort))
|
||||
if (foundObj is not KClientPort)
|
||||
{
|
||||
return KernelResult.NotFound;
|
||||
}
|
||||
|
@ -141,4 +141,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return KAutoObject.RemoveName(context, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
public KProcess CreatorProcess { get; }
|
||||
|
||||
private KSession _parent;
|
||||
private readonly KSession _parent;
|
||||
|
||||
public ChannelState State { get; set; }
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
public KClientSession(KernelContext context, KSession parent, KClientPort parentPort) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
_parent = parent;
|
||||
ParentPort = parentPort;
|
||||
|
||||
parentPort?.IncrementReferenceCount();
|
||||
|
@ -32,11 +32,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
KSessionRequest request = new(currentThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = Result.Success;
|
||||
|
||||
Result result = _parent.ServerSession.EnqueueRequest(request);
|
||||
|
@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize, asyncEvent);
|
||||
KSessionRequest request = new(currentThread, customCmdBuffAddr, customCmdBuffSize, asyncEvent);
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
|
@ -81,4 +81,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
_parent.DecrementReferenceCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
class KLightClientSession : KAutoObject
|
||||
{
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private readonly KLightSession _parent;
|
||||
#pragma warning restore IDE0052
|
||||
|
||||
public KLightClientSession(KernelContext context, KLightSession parent) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
class KLightServerSession : KAutoObject
|
||||
{
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private readonly KLightSession _parent;
|
||||
#pragma warning restore IDE0052
|
||||
|
||||
public KLightServerSession(KernelContext context, KLightSession parent) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,4 +13,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
ClientSession = new KLightClientSession(context, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
public KServerPort ServerPort { get; }
|
||||
public KClientPort ClientPort { get; }
|
||||
|
||||
private string _name;
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private readonly string _name;
|
||||
#pragma warning restore IDE0052
|
||||
|
||||
private ChannelState _state;
|
||||
private readonly ChannelState _state;
|
||||
|
||||
public bool IsLight { get; private set; }
|
||||
|
||||
|
@ -69,4 +71,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
class KServerPort : KSynchronizationObject
|
||||
{
|
||||
private readonly LinkedList<KServerSession> _incomingConnections;
|
||||
private readonly LinkedList<KServerSession> _incomingConnections;
|
||||
private readonly LinkedList<KLightServerSession> _lightIncomingConnections;
|
||||
|
||||
private readonly KPort _parent;
|
||||
|
@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
_parent = parent;
|
||||
|
||||
_incomingConnections = new LinkedList<KServerSession>();
|
||||
_incomingConnections = new LinkedList<KServerSession>();
|
||||
_lightIncomingConnections = new LinkedList<KLightServerSession>();
|
||||
}
|
||||
|
||||
|
@ -84,4 +84,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,19 +10,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
class KServerSession : KSynchronizationObject
|
||||
{
|
||||
private static readonly MemoryState[] IpcMemoryStates = new MemoryState[]
|
||||
{
|
||||
private static readonly MemoryState[] _ipcMemoryStates = {
|
||||
MemoryState.IpcBuffer3,
|
||||
MemoryState.IpcBuffer0,
|
||||
MemoryState.IpcBuffer1,
|
||||
(MemoryState)0xfffce5d4 //This is invalid, shouldn't be accessed.
|
||||
(MemoryState)0xfffce5d4, //This is invalid, shouldn't be accessed.
|
||||
};
|
||||
|
||||
private readonly struct Message
|
||||
{
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
public bool IsCustom { get; }
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
public bool IsCustom { get; }
|
||||
|
||||
public Message(KThread thread, ulong customCmdBuffAddress, ulong customCmdBuffSize)
|
||||
{
|
||||
|
@ -31,19 +30,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
if (IsCustom)
|
||||
{
|
||||
Address = customCmdBuffAddress;
|
||||
Size = customCmdBuffSize;
|
||||
Size = customCmdBuffSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Address = thread.TlsAddress;
|
||||
Size = 0x100;
|
||||
Size = 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
public Message(KSessionRequest request) : this(
|
||||
request.ClientThread,
|
||||
request.CustomCmdBuffAddr,
|
||||
request.CustomCmdBuffSize) { }
|
||||
request.CustomCmdBuffSize)
|
||||
{ }
|
||||
}
|
||||
|
||||
private readonly struct MessageHeader
|
||||
|
@ -52,18 +52,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
public uint Word1 { get; }
|
||||
public uint Word2 { get; }
|
||||
|
||||
public uint PointerBuffersCount { get; }
|
||||
public uint SendBuffersCount { get; }
|
||||
public uint ReceiveBuffersCount { get; }
|
||||
public uint PointerBuffersCount { get; }
|
||||
public uint SendBuffersCount { get; }
|
||||
public uint ReceiveBuffersCount { get; }
|
||||
public uint ExchangeBuffersCount { get; }
|
||||
|
||||
public uint RawDataSizeInWords { get; }
|
||||
|
||||
public uint ReceiveListType { get; }
|
||||
|
||||
public uint MessageSizeInWords { get; }
|
||||
public uint MessageSizeInWords { get; }
|
||||
public uint ReceiveListOffsetInWords { get; }
|
||||
public uint ReceiveListOffset { get; }
|
||||
public uint ReceiveListOffset { get; }
|
||||
|
||||
public bool HasHandles { get; }
|
||||
|
||||
|
@ -101,14 +101,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
MoveHandlesCount = 0;
|
||||
}
|
||||
|
||||
PointerBuffersCount = (word0 >> 16) & 0xf;
|
||||
SendBuffersCount = (word0 >> 20) & 0xf;
|
||||
ReceiveBuffersCount = (word0 >> 24) & 0xf;
|
||||
ExchangeBuffersCount = word0 >> 28;
|
||||
PointerBuffersCount = (word0 >> 16) & 0xf;
|
||||
SendBuffersCount = (word0 >> 20) & 0xf;
|
||||
ReceiveBuffersCount = (word0 >> 24) & 0xf;
|
||||
ExchangeBuffersCount = word0 >> 28;
|
||||
|
||||
uint pointerDescSizeInWords = PointerBuffersCount * 2;
|
||||
uint sendDescSizeInWords = SendBuffersCount * 3;
|
||||
uint receiveDescSizeInWords = ReceiveBuffersCount * 3;
|
||||
uint pointerDescSizeInWords = PointerBuffersCount * 2;
|
||||
uint sendDescSizeInWords = SendBuffersCount * 3;
|
||||
uint receiveDescSizeInWords = ReceiveBuffersCount * 3;
|
||||
uint exchangeDescSizeInWords = ExchangeBuffersCount * 3;
|
||||
|
||||
RawDataSizeInWords = word1 & 0x3ff;
|
||||
|
@ -119,12 +119,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
uint paddingSizeInWords = HasHandles ? 3u : 2u;
|
||||
|
||||
MessageSizeInWords = pointerDescSizeInWords +
|
||||
sendDescSizeInWords +
|
||||
receiveDescSizeInWords +
|
||||
MessageSizeInWords = pointerDescSizeInWords +
|
||||
sendDescSizeInWords +
|
||||
receiveDescSizeInWords +
|
||||
exchangeDescSizeInWords +
|
||||
RawDataSizeInWords +
|
||||
paddingSizeInWords +
|
||||
RawDataSizeInWords +
|
||||
paddingSizeInWords +
|
||||
handleDescSizeInWords;
|
||||
|
||||
if (ReceiveListOffsetInWords == 0)
|
||||
|
@ -140,25 +140,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
public uint ReceiveIndex { get; }
|
||||
|
||||
public uint BufferSize { get; }
|
||||
public uint BufferSize { get; }
|
||||
public ulong BufferAddress { get; set; }
|
||||
|
||||
public PointerBufferDesc(ulong dword)
|
||||
{
|
||||
ReceiveIndex = (uint)dword & 0xf;
|
||||
BufferSize = (uint)dword >> 16;
|
||||
BufferSize = (uint)dword >> 16;
|
||||
|
||||
BufferAddress = (dword >> 2) & 0x70;
|
||||
BufferAddress = (dword >> 2) & 0x70;
|
||||
BufferAddress |= (dword >> 12) & 0xf;
|
||||
|
||||
BufferAddress = (BufferAddress << 32) | (dword >> 32);
|
||||
}
|
||||
|
||||
public ulong Pack()
|
||||
public readonly ulong Pack()
|
||||
{
|
||||
ulong dword = (ReceiveIndex & 0xf) | ((BufferSize & 0xffff) << 16);
|
||||
|
||||
dword |= BufferAddress << 32;
|
||||
dword |= BufferAddress << 32;
|
||||
dword |= (BufferAddress >> 20) & 0xf000;
|
||||
dword |= (BufferAddress >> 30) & 0xffc0;
|
||||
|
||||
|
@ -166,9 +166,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
}
|
||||
|
||||
private KSession _parent;
|
||||
private readonly KSession _parent;
|
||||
|
||||
private LinkedList<KSessionRequest> _requests;
|
||||
private readonly LinkedList<KSessionRequest> _requests;
|
||||
|
||||
private KSessionRequest _activeRequest;
|
||||
|
||||
|
@ -208,7 +208,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
public Result Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||
{
|
||||
KThread serverThread = KernelStatic.GetCurrentThread();
|
||||
KThread serverThread = KernelStatic.GetCurrentThread();
|
||||
KProcess serverProcess = serverThread.Owner;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
@ -234,7 +234,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return KernelResult.PortRemoteClosed;
|
||||
}
|
||||
|
||||
KThread clientThread = request.ClientThread;
|
||||
KThread clientThread = request.ClientThread;
|
||||
KProcess clientProcess = clientThread.Owner;
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
@ -243,8 +243,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
request.ServerProcess = serverProcess;
|
||||
|
||||
Message clientMsg = new Message(request);
|
||||
Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
Message clientMsg = new(request);
|
||||
Message serverMsg = new(serverThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
|
||||
MessageHeader clientHeader = GetClientMessageHeader(clientProcess, clientMsg);
|
||||
MessageHeader serverHeader = GetServerMessageHeader(serverMsg);
|
||||
|
@ -399,7 +399,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
ulong pointerDesc = clientProcess.CpuMemory.Read<ulong>(clientMsg.Address + offset * 4);
|
||||
|
||||
PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc);
|
||||
PointerBufferDesc descriptor = new(pointerDesc);
|
||||
|
||||
if (descriptor.BufferSize != 0)
|
||||
{
|
||||
|
@ -409,7 +409,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
serverHeader.ReceiveListType,
|
||||
clientHeader.MessageSizeInWords,
|
||||
receiveList,
|
||||
ref recvListDstOffset,
|
||||
ref recvListDstOffset,
|
||||
out ulong recvListBufferAddress);
|
||||
|
||||
if (clientResult != Result.Success)
|
||||
|
@ -450,7 +450,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
// Copy send, receive and exchange buffers.
|
||||
uint totalBuffersCount =
|
||||
clientHeader.SendBuffersCount +
|
||||
clientHeader.SendBuffersCount +
|
||||
clientHeader.ReceiveBuffersCount +
|
||||
clientHeader.ExchangeBuffersCount;
|
||||
|
||||
|
@ -462,11 +462,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
uint descWord1 = clientProcess.CpuMemory.Read<uint>(clientDescAddress + 4);
|
||||
uint descWord2 = clientProcess.CpuMemory.Read<uint>(clientDescAddress + 8);
|
||||
|
||||
bool isSendDesc = index < clientHeader.SendBuffersCount;
|
||||
bool isSendDesc = index < clientHeader.SendBuffersCount;
|
||||
bool isExchangeDesc = index >= clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount;
|
||||
|
||||
bool notReceiveDesc = isSendDesc || isExchangeDesc;
|
||||
bool isReceiveDesc = !notReceiveDesc;
|
||||
bool isReceiveDesc = !notReceiveDesc;
|
||||
|
||||
KMemoryPermission permission = index >= clientHeader.SendBuffersCount
|
||||
? KMemoryPermission.ReadAndWrite
|
||||
|
@ -482,12 +482,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
ulong bufferAddress;
|
||||
|
||||
bufferAddress = descWord2 >> 28;
|
||||
bufferAddress = descWord2 >> 28;
|
||||
bufferAddress |= ((descWord2 >> 2) & 7) << 4;
|
||||
|
||||
bufferAddress = (bufferAddress << 32) | descWord1;
|
||||
|
||||
MemoryState state = IpcMemoryStates[(descWord2 + 1) & 3];
|
||||
MemoryState state = _ipcMemoryStates[(descWord2 + 1) & 3];
|
||||
|
||||
clientResult = serverProcess.MemoryManager.MapBufferFromClientProcess(
|
||||
bufferSize,
|
||||
|
@ -533,7 +533,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
descWord2 |= sizeHigh4 << 24;
|
||||
|
||||
descWord2 |= (uint)(dstAddress >> 34) & 0x3ffffffc;
|
||||
descWord2 |= (uint)(dstAddress >> 4) & 0xf0000000;
|
||||
descWord2 |= (uint)(dstAddress >> 4) & 0xf0000000;
|
||||
|
||||
ulong serverDescAddress = serverMsg.Address + offset * 4;
|
||||
|
||||
|
@ -586,7 +586,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
public Result Reply(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||
{
|
||||
KThread serverThread = KernelStatic.GetCurrentThread();
|
||||
KThread serverThread = KernelStatic.GetCurrentThread();
|
||||
KProcess serverProcess = serverThread.Owner;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
@ -609,11 +609,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
KThread clientThread = request.ClientThread;
|
||||
KThread clientThread = request.ClientThread;
|
||||
KProcess clientProcess = clientThread.Owner;
|
||||
|
||||
Message clientMsg = new Message(request);
|
||||
Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
Message clientMsg = new(request);
|
||||
Message serverMsg = new(serverThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
|
||||
MessageHeader clientHeader = GetClientMessageHeader(clientProcess, clientMsg);
|
||||
MessageHeader serverHeader = GetServerMessageHeader(serverMsg);
|
||||
|
@ -664,8 +664,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return KernelResult.CmdBufferTooSmall;
|
||||
}
|
||||
|
||||
if (serverHeader.SendBuffersCount != 0 ||
|
||||
serverHeader.ReceiveBuffersCount != 0 ||
|
||||
if (serverHeader.SendBuffersCount != 0 ||
|
||||
serverHeader.ReceiveBuffersCount != 0 ||
|
||||
serverHeader.ExchangeBuffersCount != 0)
|
||||
{
|
||||
CleanUpForError();
|
||||
|
@ -761,7 +761,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
{
|
||||
ulong pointerDesc = serverProcess.CpuMemory.Read<ulong>(serverMsg.Address + offset * 4);
|
||||
|
||||
PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc);
|
||||
PointerBufferDesc descriptor = new(pointerDesc);
|
||||
|
||||
ulong recvListBufferAddress = 0;
|
||||
|
||||
|
@ -817,7 +817,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
|
||||
// Set send, receive and exchange buffer descriptors to zero.
|
||||
uint totalBuffersCount =
|
||||
serverHeader.SendBuffersCount +
|
||||
serverHeader.SendBuffersCount +
|
||||
serverHeader.ReceiveBuffersCount +
|
||||
serverHeader.ExchangeBuffersCount;
|
||||
|
||||
|
@ -868,7 +868,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return serverResult;
|
||||
}
|
||||
|
||||
private MessageHeader GetClientMessageHeader(KProcess clientProcess, Message clientMsg)
|
||||
private static MessageHeader GetClientMessageHeader(KProcess clientProcess, Message clientMsg)
|
||||
{
|
||||
uint word0 = clientProcess.CpuMemory.Read<uint>(clientMsg.Address + 0);
|
||||
uint word1 = clientProcess.CpuMemory.Read<uint>(clientMsg.Address + 4);
|
||||
|
@ -877,7 +877,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return new MessageHeader(word0, word1, word2);
|
||||
}
|
||||
|
||||
private MessageHeader GetServerMessageHeader(Message serverMsg)
|
||||
private static MessageHeader GetServerMessageHeader(Message serverMsg)
|
||||
{
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -888,7 +888,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return new MessageHeader(word0, word1, word2);
|
||||
}
|
||||
|
||||
private Result GetCopyObjectHandle(KThread srcThread, KProcess dstProcess, int srcHandle, out int dstHandle)
|
||||
private static Result GetCopyObjectHandle(KThread srcThread, KProcess dstProcess, int srcHandle, out int dstHandle)
|
||||
{
|
||||
dstHandle = 0;
|
||||
|
||||
|
@ -919,7 +919,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
}
|
||||
|
||||
private Result GetMoveObjectHandle(KProcess srcProcess, KProcess dstProcess, int srcHandle, out int dstHandle)
|
||||
private static Result GetMoveObjectHandle(KProcess srcProcess, KProcess dstProcess, int srcHandle, out int dstHandle)
|
||||
{
|
||||
dstHandle = 0;
|
||||
|
||||
|
@ -939,7 +939,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
}
|
||||
|
||||
private ulong[] GetReceiveList(KProcess ownerProcess, Message message, uint recvListType, uint recvListOffset)
|
||||
private static ulong[] GetReceiveList(KProcess ownerProcess, Message message, uint recvListType, uint recvListOffset)
|
||||
{
|
||||
int recvListSize = 0;
|
||||
|
||||
|
@ -964,16 +964,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return receiveList;
|
||||
}
|
||||
|
||||
private Result GetReceiveListAddress(
|
||||
private static Result GetReceiveListAddress(
|
||||
PointerBufferDesc descriptor,
|
||||
Message message,
|
||||
uint recvListType,
|
||||
uint messageSizeInWords,
|
||||
ulong[] receiveList,
|
||||
ref uint dstOffset,
|
||||
out ulong address)
|
||||
Message message,
|
||||
uint recvListType,
|
||||
uint messageSizeInWords,
|
||||
ulong[] receiveList,
|
||||
ref uint dstOffset,
|
||||
out ulong address)
|
||||
{
|
||||
ulong recvListBufferAddress = address = 0;
|
||||
ulong recvListBufferAddress;
|
||||
address = 0;
|
||||
|
||||
if (recvListType == 0)
|
||||
{
|
||||
|
@ -987,7 +988,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
if (recvListType == 1)
|
||||
{
|
||||
recvListBaseAddr = message.Address + messageSizeInWords * 4;
|
||||
recvListEndAddr = message.Address + message.Size;
|
||||
recvListEndAddr = message.Address + message.Size;
|
||||
}
|
||||
else /* if (recvListType == 2) */
|
||||
{
|
||||
|
@ -1012,7 +1013,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
dstOffset = (uint)endAddress - (uint)recvListBaseAddr;
|
||||
|
||||
if (recvListBufferAddress + descriptor.BufferSize <= recvListBufferAddress ||
|
||||
recvListBufferAddress + descriptor.BufferSize > recvListEndAddr)
|
||||
recvListBufferAddress + descriptor.BufferSize > recvListEndAddr)
|
||||
{
|
||||
return KernelResult.OutOfResource;
|
||||
}
|
||||
|
@ -1041,7 +1042,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
private void CloseAllHandles(Message message, MessageHeader header, KProcess process)
|
||||
private static void CloseAllHandles(Message message, MessageHeader header, KProcess process)
|
||||
{
|
||||
if (header.HasHandles)
|
||||
{
|
||||
|
@ -1202,7 +1203,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
}
|
||||
|
||||
private void SendResultToAsyncRequestClient(KSessionRequest request, Result result)
|
||||
private static void SendResultToAsyncRequestClient(KSessionRequest request, Result result)
|
||||
{
|
||||
KProcess clientProcess = request.ClientThread.Owner;
|
||||
|
||||
|
@ -1232,15 +1233,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
private void WakeAndSetResult(KThread thread, Result result, KSynchronizationObject signaledObj = null)
|
||||
private static void WakeAndSetResult(KThread thread, Result result, KSynchronizationObject signaledObj = null)
|
||||
{
|
||||
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
||||
{
|
||||
thread.SignaledObj = signaledObj;
|
||||
thread.SignaledObj = signaledObj;
|
||||
thread.ObjSyncResult = result;
|
||||
|
||||
thread.Reschedule(ThreadSchedState.Running);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
public KServerSession ServerSession { get; }
|
||||
public KClientSession ClientSession { get; }
|
||||
|
||||
private bool _hasBeenInitialized;
|
||||
private readonly bool _hasBeenInitialized;
|
||||
|
||||
public KSession(KernelContext context, KClientPort parentPort = null) : base(context)
|
||||
{
|
||||
|
@ -51,4 +51,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
|||
public ulong CustomCmdBuffSize { get; }
|
||||
|
||||
public KSessionRequest(
|
||||
KThread clientThread,
|
||||
ulong customCmdBuffAddr,
|
||||
ulong customCmdBuffSize,
|
||||
KThread clientThread,
|
||||
ulong customCmdBuffAddr,
|
||||
ulong customCmdBuffSize,
|
||||
KWritableEvent asyncEvent = null)
|
||||
{
|
||||
ClientThread = clientThread;
|
||||
ClientThread = clientThread;
|
||||
CustomCmdBuffAddr = customCmdBuffAddr;
|
||||
CustomCmdBuffSize = customCmdBuffSize;
|
||||
AsyncEvent = asyncEvent;
|
||||
AsyncEvent = asyncEvent;
|
||||
|
||||
BufferDescriptorTable = new KBufferDescriptorTable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,4 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
|
||||
public const ulong CounterFrequency = 19200000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
static class KernelStatic
|
||||
{
|
||||
[ThreadStatic]
|
||||
private static KernelContext Context;
|
||||
private static KernelContext _context;
|
||||
|
||||
[ThreadStatic]
|
||||
private static KThread CurrentThread;
|
||||
private static KThread _currentThread;
|
||||
|
||||
public static Result StartInitialProcess(
|
||||
KernelContext context,
|
||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
int mainThreadPriority,
|
||||
ThreadStart customThreadStart)
|
||||
{
|
||||
KProcess process = new KProcess(context);
|
||||
KProcess process = new(context);
|
||||
|
||||
Result result = process.Initialize(
|
||||
creationInfo,
|
||||
|
@ -46,13 +46,13 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
|
||||
internal static void SetKernelContext(KernelContext context, KThread thread)
|
||||
{
|
||||
Context = context;
|
||||
CurrentThread = thread;
|
||||
_context = context;
|
||||
_currentThread = thread;
|
||||
}
|
||||
|
||||
internal static KThread GetCurrentThread()
|
||||
{
|
||||
return CurrentThread;
|
||||
return _currentThread;
|
||||
}
|
||||
|
||||
internal static KProcess GetCurrentProcess()
|
||||
|
@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
|
||||
internal static KProcess GetProcessByPid(ulong pid)
|
||||
{
|
||||
if (Context.Processes.TryGetValue(pid, out KProcess process))
|
||||
if (_context.Processes.TryGetValue(pid, out KProcess process))
|
||||
{
|
||||
return process;
|
||||
}
|
||||
|
@ -70,4 +70,4 @@ namespace Ryujinx.HLE.HOS.Kernel
|
|||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
enum AddressSpaceType
|
||||
{
|
||||
Addr32Bits = 0,
|
||||
Addr36Bits = 1,
|
||||
Addr32Bits = 0,
|
||||
Addr36Bits = 1,
|
||||
Addr32BitsNoMap = 2,
|
||||
Addr39Bits = 3
|
||||
Addr39Bits = 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
public const ulong SlabHeapBase = KernelReserveBase + 0x85000;
|
||||
public const ulong SlapHeapSize = 0xa21000;
|
||||
public const ulong SlabHeapEnd = SlabHeapBase + SlapHeapSize;
|
||||
public const ulong SlabHeapEnd = SlabHeapBase + SlapHeapSize;
|
||||
|
||||
public static bool IsHeapPhysicalAddress(ulong address)
|
||||
{
|
||||
return address >= SlabHeapEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,4 +166,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
Owner.DecrementReferenceCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,4 +153,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
class KMemoryBlockSlabManager
|
||||
{
|
||||
private ulong _capacityElements;
|
||||
private readonly ulong _capacityElements;
|
||||
|
||||
public int Count { get; set; }
|
||||
|
||||
|
@ -16,4 +16,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
return (ulong)(Count + count) <= _capacityElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,34 +3,34 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
class KMemoryInfo
|
||||
{
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
public ulong Size { get; }
|
||||
|
||||
public MemoryState State { get; }
|
||||
public KMemoryPermission Permission { get; }
|
||||
public MemoryAttribute Attribute { get; }
|
||||
public MemoryState State { get; }
|
||||
public KMemoryPermission Permission { get; }
|
||||
public MemoryAttribute Attribute { get; }
|
||||
public KMemoryPermission SourcePermission { get; }
|
||||
|
||||
public int IpcRefCount { get; }
|
||||
public int IpcRefCount { get; }
|
||||
public int DeviceRefCount { get; }
|
||||
|
||||
public KMemoryInfo(
|
||||
ulong address,
|
||||
ulong size,
|
||||
MemoryState state,
|
||||
ulong address,
|
||||
ulong size,
|
||||
MemoryState state,
|
||||
KMemoryPermission permission,
|
||||
MemoryAttribute attribute,
|
||||
MemoryAttribute attribute,
|
||||
KMemoryPermission sourcePermission,
|
||||
int ipcRefCount,
|
||||
int deviceRefCount)
|
||||
int ipcRefCount,
|
||||
int deviceRefCount)
|
||||
{
|
||||
Address = address;
|
||||
Size = size;
|
||||
State = state;
|
||||
Permission = permission;
|
||||
Attribute = attribute;
|
||||
Address = address;
|
||||
Size = size;
|
||||
State = state;
|
||||
Permission = permission;
|
||||
Attribute = attribute;
|
||||
SourcePermission = sourcePermission;
|
||||
IpcRefCount = ipcRefCount;
|
||||
DeviceRefCount = deviceRefCount;
|
||||
IpcRefCount = ipcRefCount;
|
||||
DeviceRefCount = deviceRefCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,4 +239,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
return (EndAddr - address) / KPageTableBase.PageSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
while (depth >= 0)
|
||||
{
|
||||
int ind = (int)(offset / UInt64BitSize);
|
||||
int ind = (int)(offset / UInt64BitSize);
|
||||
int which = (int)(offset % UInt64BitSize);
|
||||
|
||||
ulong mask = 1UL << which;
|
||||
|
@ -247,7 +247,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
while (depth >= 0)
|
||||
{
|
||||
int ind = (int)(offset / UInt64BitSize);
|
||||
int ind = (int)(offset / UInt64BitSize);
|
||||
int which = (int)(offset % UInt64BitSize);
|
||||
|
||||
ulong mask = 1UL << which;
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
private class Block
|
||||
{
|
||||
private KPageBitmap _bitmap = new KPageBitmap();
|
||||
private readonly KPageBitmap _bitmap = new();
|
||||
private ulong _heapAddress;
|
||||
private ulong _endOffset;
|
||||
|
||||
|
@ -29,8 +29,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
? 1UL << nextBlockShift
|
||||
: 1UL << blockShift;
|
||||
|
||||
address = BitUtils.AlignDown(address, align);
|
||||
endAddress = BitUtils.AlignUp (endAddress, align);
|
||||
address = BitUtils.AlignDown(address, align);
|
||||
endAddress = BitUtils.AlignUp(endAddress, align);
|
||||
|
||||
_heapAddress = address;
|
||||
_endOffset = (endAddress - address) / (1UL << blockShift);
|
||||
|
@ -84,11 +84,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly int[] _memoryBlockPageShifts = new int[] { 12, 16, 21, 22, 25, 29, 30 };
|
||||
private static readonly int[] _memoryBlockPageShifts = { 12, 16, 21, 22, 25, 29, 30 };
|
||||
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private readonly ulong _heapAddress;
|
||||
private readonly ulong _heapSize;
|
||||
private ulong _usedSize;
|
||||
#pragma warning restore IDE0052
|
||||
private readonly int _blocksCount;
|
||||
private readonly Block[] _blocks;
|
||||
|
||||
|
@ -175,19 +177,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
int bigIndex = _blocksCount - 1;
|
||||
|
||||
ulong start = address;
|
||||
ulong end = address + pagesCount * KPageTableBase.PageSize;
|
||||
ulong start = address;
|
||||
ulong end = address + pagesCount * KPageTableBase.PageSize;
|
||||
ulong beforeStart = start;
|
||||
ulong beforeEnd = start;
|
||||
ulong afterStart = end;
|
||||
ulong afterEnd = end;
|
||||
ulong beforeEnd = start;
|
||||
ulong afterStart = end;
|
||||
ulong afterEnd = end;
|
||||
|
||||
while (bigIndex >= 0)
|
||||
{
|
||||
ulong blockSize = _blocks[bigIndex].Size;
|
||||
|
||||
ulong bigStart = BitUtils.AlignUp (start, blockSize);
|
||||
ulong bigEnd = BitUtils.AlignDown(end, blockSize);
|
||||
ulong bigStart = BitUtils.AlignUp(start, blockSize);
|
||||
ulong bigEnd = BitUtils.AlignDown(end, blockSize);
|
||||
|
||||
if (bigStart < bigEnd)
|
||||
{
|
||||
|
@ -196,7 +198,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
FreeBlock(block, bigIndex);
|
||||
}
|
||||
|
||||
beforeEnd = bigStart;
|
||||
beforeEnd = bigStart;
|
||||
afterStart = bigEnd;
|
||||
|
||||
break;
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
if (lastNode.Address + lastNode.PagesCount * KPageTableBase.PageSize == address)
|
||||
{
|
||||
address = lastNode.Address;
|
||||
address = lastNode.Address;
|
||||
pagesCount += lastNode.PagesCount;
|
||||
|
||||
Nodes.RemoveLast();
|
||||
|
@ -50,18 +50,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
public bool IsEqual(KPageList other)
|
||||
{
|
||||
LinkedListNode<KPageNode> thisNode = Nodes.First;
|
||||
LinkedListNode<KPageNode> thisNode = Nodes.First;
|
||||
LinkedListNode<KPageNode> otherNode = other.Nodes.First;
|
||||
|
||||
while (thisNode != null && otherNode != null)
|
||||
{
|
||||
if (thisNode.Value.Address != otherNode.Value.Address ||
|
||||
if (thisNode.Value.Address != otherNode.Value.Address ||
|
||||
thisNode.Value.PagesCount != otherNode.Value.PagesCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
thisNode = thisNode.Next;
|
||||
thisNode = thisNode.Next;
|
||||
otherNode = otherNode.Next;
|
||||
}
|
||||
|
||||
|
@ -94,4 +94,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
public KPageNode(ulong address, ulong pagesCount)
|
||||
{
|
||||
Address = address;
|
||||
Address = address;
|
||||
PagesCount = pagesCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
/// <inheritdoc/>
|
||||
protected override Result MapMemory(ulong src, ulong dst, ulong pagesCount, KMemoryPermission oldSrcPermission, KMemoryPermission newDstPermission)
|
||||
{
|
||||
KPageList pageList = new KPageList();
|
||||
KPageList pageList = new();
|
||||
GetPhysicalRegions(src, pagesCount * PageSize, pageList);
|
||||
|
||||
Result result = Reprotect(src, pagesCount, KMemoryPermission.None);
|
||||
|
@ -69,8 +69,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
ulong size = pagesCount * PageSize;
|
||||
|
||||
KPageList srcPageList = new KPageList();
|
||||
KPageList dstPageList = new KPageList();
|
||||
KPageList srcPageList = new();
|
||||
KPageList dstPageList = new();
|
||||
|
||||
GetPhysicalRegions(src, size, srcPageList);
|
||||
GetPhysicalRegions(dst, size, dstPageList);
|
||||
|
@ -180,7 +180,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
/// <inheritdoc/>
|
||||
protected override Result Unmap(ulong address, ulong pagesCount)
|
||||
{
|
||||
KPageList pagesToClose = new KPageList();
|
||||
KPageList pagesToClose = new();
|
||||
|
||||
var regions = _cpuMemory.GetPhysicalRegions(address, pagesCount * PageSize);
|
||||
|
||||
|
@ -226,4 +226,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
_cpuMemory.Write(va, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
abstract class KPageTableBase
|
||||
{
|
||||
private static readonly int[] MappingUnitSizes = new int[]
|
||||
{
|
||||
private static readonly int[] _mappingUnitSizes = {
|
||||
0x1000,
|
||||
0x10000,
|
||||
0x200000,
|
||||
0x400000,
|
||||
0x2000000,
|
||||
0x40000000
|
||||
0x40000000,
|
||||
};
|
||||
|
||||
private const ulong RegionAlignment = 0x200000;
|
||||
|
@ -58,7 +57,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
public ulong AslrRegionStart { get; private set; }
|
||||
public ulong AslrRegionEnd { get; private set; }
|
||||
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private ulong _heapCapacity;
|
||||
#pragma warning restore IDE0052
|
||||
|
||||
public ulong PhysicalMemoryUsage { get; private set; }
|
||||
|
||||
|
@ -67,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
private MemoryRegion _memRegion;
|
||||
|
||||
private bool _allocateFromBack;
|
||||
private bool _isKernel;
|
||||
private readonly bool _isKernel;
|
||||
|
||||
private bool _aslrEnabled;
|
||||
|
||||
|
@ -77,10 +78,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
private MersenneTwister _randomNumberGenerator;
|
||||
|
||||
private MemoryFillValue _heapFillValue;
|
||||
private MemoryFillValue _ipcFillValue;
|
||||
private readonly MemoryFillValue _heapFillValue;
|
||||
private readonly MemoryFillValue _ipcFillValue;
|
||||
|
||||
private ulong _reservedAddressSpaceSize;
|
||||
private readonly ulong _reservedAddressSpaceSize;
|
||||
|
||||
public KPageTableBase(KernelContext context, ulong reservedAddressSpaceSize)
|
||||
{
|
||||
|
@ -96,7 +97,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
_reservedAddressSpaceSize = reservedAddressSpaceSize;
|
||||
}
|
||||
|
||||
private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 };
|
||||
private static readonly int[] _addrSpaceSizes = { 32, 36, 32, 39 };
|
||||
|
||||
public Result InitializeForProcess(
|
||||
AddressSpaceType addrSpaceType,
|
||||
|
@ -109,13 +110,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
if ((uint)addrSpaceType > (uint)AddressSpaceType.Addr39Bits)
|
||||
{
|
||||
throw new ArgumentException(nameof(addrSpaceType));
|
||||
throw new ArgumentException($"AddressSpaceType bigger than {(uint)AddressSpaceType.Addr39Bits}: {(uint)addrSpaceType}", nameof(addrSpaceType));
|
||||
}
|
||||
|
||||
_contextId = Context.ContextIdManager.GetId();
|
||||
|
||||
ulong addrSpaceBase = 0;
|
||||
ulong addrSpaceSize = 1UL << AddrSpaceSizes[(int)addrSpaceType];
|
||||
ulong addrSpaceSize = 1UL << _addrSpaceSizes[(int)addrSpaceType];
|
||||
|
||||
Result result = CreateUserAddressSpace(
|
||||
addrSpaceType,
|
||||
|
@ -157,10 +158,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
ulong endAddr = address + size;
|
||||
|
||||
Region aliasRegion = new Region();
|
||||
Region heapRegion = new Region();
|
||||
Region stackRegion = new Region();
|
||||
Region tlsIoRegion = new Region();
|
||||
Region aliasRegion = new();
|
||||
Region heapRegion = new();
|
||||
Region stackRegion = new();
|
||||
Region tlsIoRegion = new();
|
||||
|
||||
ulong codeRegionSize;
|
||||
ulong stackAndTlsIoStart;
|
||||
|
@ -238,8 +239,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
stackAndTlsIoEnd = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default: throw new ArgumentException(nameof(addrSpaceType));
|
||||
default:
|
||||
throw new ArgumentException($"AddressSpaceType bigger than {(uint)AddressSpaceType.Addr39Bits}: {(uint)addrSpaceType}", nameof(addrSpaceType));
|
||||
}
|
||||
|
||||
CodeRegionEnd = CodeRegionStart + codeRegionSize;
|
||||
|
@ -374,10 +375,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
private long GetRandomValue(long min, long max)
|
||||
{
|
||||
if (_randomNumberGenerator == null)
|
||||
{
|
||||
_randomNumberGenerator = new MersenneTwister(0);
|
||||
}
|
||||
_randomNumberGenerator ??= new MersenneTwister(0);
|
||||
|
||||
return _randomNumberGenerator.GenRandomNumber(min, max);
|
||||
}
|
||||
|
@ -442,7 +440,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
lock (_blockManager)
|
||||
{
|
||||
KPageList currentPageList = new KPageList();
|
||||
KPageList currentPageList = new();
|
||||
|
||||
GetPhysicalRegions(address, size, currentPageList);
|
||||
|
||||
|
@ -486,13 +484,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
}
|
||||
}
|
||||
|
||||
public Result MapNormalMemory(long address, long size, KMemoryPermission permission)
|
||||
public static Result MapNormalMemory(long address, long size, KMemoryPermission permission)
|
||||
{
|
||||
// TODO.
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result MapIoMemory(long address, long size, KMemoryPermission permission)
|
||||
public static Result MapIoMemory(long address, long size, KMemoryPermission permission)
|
||||
{
|
||||
// TODO.
|
||||
return Result.Success;
|
||||
|
@ -1174,8 +1172,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
return KernelResult.InvalidMemState;
|
||||
}
|
||||
|
||||
KPageList srcPageList = new KPageList();
|
||||
KPageList dstPageList = new KPageList();
|
||||
KPageList srcPageList = new();
|
||||
KPageList dstPageList = new();
|
||||
|
||||
srcPageTable.GetPhysicalRegions(src, size, srcPageList);
|
||||
GetPhysicalRegions(dst, size, dstPageList);
|
||||
|
@ -1681,11 +1679,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
switch (state)
|
||||
{
|
||||
case MemoryState.IpcBuffer0: stateMask = MemoryState.IpcSendAllowedType0; break;
|
||||
case MemoryState.IpcBuffer1: stateMask = MemoryState.IpcSendAllowedType1; break;
|
||||
case MemoryState.IpcBuffer3: stateMask = MemoryState.IpcSendAllowedType3; break;
|
||||
|
||||
default: return KernelResult.InvalidCombination;
|
||||
case MemoryState.IpcBuffer0:
|
||||
stateMask = MemoryState.IpcSendAllowedType0;
|
||||
break;
|
||||
case MemoryState.IpcBuffer1:
|
||||
stateMask = MemoryState.IpcSendAllowedType1;
|
||||
break;
|
||||
case MemoryState.IpcBuffer3:
|
||||
stateMask = MemoryState.IpcSendAllowedType3;
|
||||
break;
|
||||
default:
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
KMemoryPermission permissionMask = permission == KMemoryPermission.ReadAndWrite
|
||||
|
@ -1822,9 +1826,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
ulong va = 0;
|
||||
|
||||
for (int unit = MappingUnitSizes.Length - 1; unit >= 0 && va == 0; unit--)
|
||||
for (int unit = _mappingUnitSizes.Length - 1; unit >= 0 && va == 0; unit--)
|
||||
{
|
||||
int alignment = MappingUnitSizes[unit];
|
||||
int alignment = _mappingUnitSizes[unit];
|
||||
|
||||
va = AllocateVa(AliasRegionStart, regionPagesCount, neededPagesCount, alignment);
|
||||
}
|
||||
|
@ -1937,7 +1941,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
if (srcPageTable.Supports4KBPages)
|
||||
{
|
||||
KPageList pageList = new KPageList();
|
||||
KPageList pageList = new();
|
||||
srcPageTable.GetPhysicalRegions(addressRounded, alignedSize, pageList);
|
||||
|
||||
result = MapPages(currentVa, pageList, permission, MemoryMapFlags.None);
|
||||
|
@ -2075,11 +2079,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
switch (state)
|
||||
{
|
||||
case MemoryState.IpcBuffer0: stateMask = MemoryState.IpcSendAllowedType0; break;
|
||||
case MemoryState.IpcBuffer1: stateMask = MemoryState.IpcSendAllowedType1; break;
|
||||
case MemoryState.IpcBuffer3: stateMask = MemoryState.IpcSendAllowedType3; break;
|
||||
|
||||
default: return KernelResult.InvalidCombination;
|
||||
case MemoryState.IpcBuffer0:
|
||||
stateMask = MemoryState.IpcSendAllowedType0;
|
||||
break;
|
||||
case MemoryState.IpcBuffer1:
|
||||
stateMask = MemoryState.IpcSendAllowedType1;
|
||||
break;
|
||||
case MemoryState.IpcBuffer3:
|
||||
stateMask = MemoryState.IpcSendAllowedType3;
|
||||
break;
|
||||
default:
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
MemoryAttribute attributeMask =
|
||||
|
@ -2392,7 +2402,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
|
||||
if (pageList != null)
|
||||
{
|
||||
KPageList currentPageList = new KPageList();
|
||||
KPageList currentPageList = new();
|
||||
|
||||
GetPhysicalRegions(address, pagesCount * PageSize, currentPageList);
|
||||
|
||||
|
@ -3050,4 +3060,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
/// <exception cref="Ryujinx.Memory.InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
|
||||
protected abstract void Write(ulong va, ReadOnlySpan<byte> data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
_pageList = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public readonly void Dispose()
|
||||
{
|
||||
_pageList?.DecrementPagesReferenceCount(_manager);
|
||||
}
|
||||
|
|
|
@ -72,4 +72,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
return memoryManager.UnmapPages(address, _pageList, MemoryState.SharedMemory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
{
|
||||
class KSlabHeap
|
||||
{
|
||||
private LinkedList<ulong> _items;
|
||||
private readonly LinkedList<ulong> _items;
|
||||
|
||||
public KSlabHeap(ulong pa, ulong itemSize, ulong size)
|
||||
{
|
||||
|
@ -47,4 +47,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,4 +127,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,20 +3,20 @@ using System;
|
|||
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
{
|
||||
[Flags]
|
||||
enum MemoryAttribute : byte
|
||||
enum MemoryAttribute : byte
|
||||
{
|
||||
None = 0,
|
||||
Mask = 0xff,
|
||||
|
||||
Borrowed = 1 << 0,
|
||||
IpcMapped = 1 << 1,
|
||||
Borrowed = 1 << 0,
|
||||
IpcMapped = 1 << 1,
|
||||
DeviceMapped = 1 << 2,
|
||||
Uncached = 1 << 3,
|
||||
Uncached = 1 << 3,
|
||||
|
||||
IpcAndDeviceMapped = IpcMapped | DeviceMapped,
|
||||
|
||||
BorrowedAndIpcMapped = Borrowed | IpcMapped,
|
||||
|
||||
DeviceMappedAndUncached = DeviceMapped | Uncached
|
||||
DeviceMappedAndUncached = DeviceMapped | Uncached,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
[Flags]
|
||||
enum KMemoryPermission : uint
|
||||
{
|
||||
None = 0,
|
||||
None = 0,
|
||||
UserMask = Read | Write | Execute,
|
||||
Mask = uint.MaxValue,
|
||||
Mask = uint.MaxValue,
|
||||
|
||||
Read = 1 << 0,
|
||||
Write = 1 << 1,
|
||||
Execute = 1 << 2,
|
||||
Read = 1 << 0,
|
||||
Write = 1 << 1,
|
||||
Execute = 1 << 2,
|
||||
DontCare = 1 << 28,
|
||||
|
||||
ReadAndWrite = Read | Write,
|
||||
ReadAndExecute = Read | Execute
|
||||
ReadAndWrite = Read | Write,
|
||||
ReadAndExecute = Read | Execute,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
enum MemoryRegion
|
||||
{
|
||||
Application = 0,
|
||||
Applet = 1,
|
||||
Service = 2,
|
||||
NvServices = 3
|
||||
Applet = 1,
|
||||
Service = 2,
|
||||
NvServices = 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,46 +5,46 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
[Flags]
|
||||
enum MemoryState : uint
|
||||
{
|
||||
Unmapped = 0x00000000,
|
||||
Io = 0x00002001,
|
||||
Normal = 0x00042002,
|
||||
CodeStatic = 0x00DC7E03,
|
||||
CodeMutable = 0x03FEBD04,
|
||||
Heap = 0x037EBD05,
|
||||
SharedMemory = 0x00402006,
|
||||
ModCodeStatic = 0x00DD7E08,
|
||||
ModCodeMutable = 0x03FFBD09,
|
||||
IpcBuffer0 = 0x005C3C0A,
|
||||
Stack = 0x005C3C0B,
|
||||
ThreadLocal = 0x0040200C,
|
||||
Unmapped = 0x00000000,
|
||||
Io = 0x00002001,
|
||||
Normal = 0x00042002,
|
||||
CodeStatic = 0x00DC7E03,
|
||||
CodeMutable = 0x03FEBD04,
|
||||
Heap = 0x037EBD05,
|
||||
SharedMemory = 0x00402006,
|
||||
ModCodeStatic = 0x00DD7E08,
|
||||
ModCodeMutable = 0x03FFBD09,
|
||||
IpcBuffer0 = 0x005C3C0A,
|
||||
Stack = 0x005C3C0B,
|
||||
ThreadLocal = 0x0040200C,
|
||||
TransferMemoryIsolated = 0x015C3C0D,
|
||||
TransferMemory = 0x005C380E,
|
||||
ProcessMemory = 0x0040380F,
|
||||
Reserved = 0x00000010,
|
||||
IpcBuffer1 = 0x005C3811,
|
||||
IpcBuffer3 = 0x004C2812,
|
||||
KernelStack = 0x00002013,
|
||||
CodeReadOnly = 0x00402214,
|
||||
CodeWritable = 0x00402015,
|
||||
UserMask = 0xff,
|
||||
Mask = 0xffffffff,
|
||||
TransferMemory = 0x005C380E,
|
||||
ProcessMemory = 0x0040380F,
|
||||
Reserved = 0x00000010,
|
||||
IpcBuffer1 = 0x005C3811,
|
||||
IpcBuffer3 = 0x004C2812,
|
||||
KernelStack = 0x00002013,
|
||||
CodeReadOnly = 0x00402214,
|
||||
CodeWritable = 0x00402015,
|
||||
UserMask = 0xff,
|
||||
Mask = 0xffffffff,
|
||||
|
||||
PermissionChangeAllowed = 1 << 8,
|
||||
PermissionChangeAllowed = 1 << 8,
|
||||
ForceReadWritableByDebugSyscalls = 1 << 9,
|
||||
IpcSendAllowedType0 = 1 << 10,
|
||||
IpcSendAllowedType3 = 1 << 11,
|
||||
IpcSendAllowedType1 = 1 << 12,
|
||||
ProcessPermissionChangeAllowed = 1 << 14,
|
||||
MapAllowed = 1 << 15,
|
||||
UnmapProcessCodeMemoryAllowed = 1 << 16,
|
||||
TransferMemoryAllowed = 1 << 17,
|
||||
QueryPhysicalAddressAllowed = 1 << 18,
|
||||
MapDeviceAllowed = 1 << 19,
|
||||
MapDeviceAlignedAllowed = 1 << 20,
|
||||
IpcBufferAllowed = 1 << 21,
|
||||
IsPoolAllocated = 1 << 22,
|
||||
MapProcessAllowed = 1 << 23,
|
||||
AttributeChangeAllowed = 1 << 24,
|
||||
CodeMemoryAllowed = 1 << 25
|
||||
IpcSendAllowedType0 = 1 << 10,
|
||||
IpcSendAllowedType3 = 1 << 11,
|
||||
IpcSendAllowedType1 = 1 << 12,
|
||||
ProcessPermissionChangeAllowed = 1 << 14,
|
||||
MapAllowed = 1 << 15,
|
||||
UnmapProcessCodeMemoryAllowed = 1 << 16,
|
||||
TransferMemoryAllowed = 1 << 17,
|
||||
QueryPhysicalAddressAllowed = 1 << 18,
|
||||
MapDeviceAllowed = 1 << 19,
|
||||
MapDeviceAlignedAllowed = 1 << 20,
|
||||
IpcBufferAllowed = 1 << 21,
|
||||
IsPoolAllocated = 1 << 22,
|
||||
MapProcessAllowed = 1 << 23,
|
||||
AttributeChangeAllowed = 1 << 24,
|
||||
CodeMemoryAllowed = 1 << 25,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return (uint)BitOperations.TrailingZeroCount(type.GetFlag());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
enum CapabilityType : uint
|
||||
{
|
||||
CorePriority = (1u << 3) - 1,
|
||||
SyscallMask = (1u << 4) - 1,
|
||||
MapRange = (1u << 6) - 1,
|
||||
MapIoPage = (1u << 7) - 1,
|
||||
MapRegion = (1u << 10) - 1,
|
||||
CorePriority = (1u << 3) - 1,
|
||||
SyscallMask = (1u << 4) - 1,
|
||||
MapRange = (1u << 6) - 1,
|
||||
MapIoPage = (1u << 7) - 1,
|
||||
MapRegion = (1u << 10) - 1,
|
||||
InterruptPair = (1u << 11) - 1,
|
||||
ProgramType = (1u << 13) - 1,
|
||||
ProgramType = (1u << 13) - 1,
|
||||
KernelVersion = (1u << 14) - 1,
|
||||
HandleTable = (1u << 15) - 1,
|
||||
DebugFlags = (1u << 16) - 1,
|
||||
HandleTable = (1u << 15) - 1,
|
||||
DebugFlags = (1u << 16) - 1,
|
||||
|
||||
Invalid = 0u,
|
||||
Padding = ~0u
|
||||
Invalid = 0u,
|
||||
Padding = ~0u,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
private const int Mod0 = 'M' << 0 | 'O' << 8 | 'D' << 16 | '0' << 24;
|
||||
|
||||
private KProcess _owner;
|
||||
private readonly KProcess _owner;
|
||||
|
||||
private class Image
|
||||
{
|
||||
|
@ -27,12 +27,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
public Image(ulong baseAddress, ulong size, ElfSymbol[] symbols)
|
||||
{
|
||||
BaseAddress = baseAddress;
|
||||
Size = size;
|
||||
Symbols = symbols;
|
||||
Size = size;
|
||||
Symbols = symbols;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Image> _images;
|
||||
private readonly List<Image> _images;
|
||||
|
||||
private int _loaded;
|
||||
|
||||
|
@ -49,7 +49,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
var context = thread.Context;
|
||||
|
||||
StringBuilder trace = new StringBuilder();
|
||||
StringBuilder trace = new();
|
||||
|
||||
trace.AppendLine($"Process: {_owner.Name}, PID: {_owner.Pid}");
|
||||
|
||||
|
@ -111,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
var context = thread.Context;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new();
|
||||
|
||||
string GetReg(int x)
|
||||
{
|
||||
|
@ -145,11 +145,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
private bool TryGetSubName(Image image, ulong address, out ElfSymbol symbol)
|
||||
private static bool TryGetSubName(Image image, ulong address, out ElfSymbol symbol)
|
||||
{
|
||||
address -= image.BaseAddress;
|
||||
|
||||
int left = 0;
|
||||
int left = 0;
|
||||
int right = image.Symbols.Length - 1;
|
||||
|
||||
while (left <= right)
|
||||
|
@ -190,9 +190,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
public ulong Offset;
|
||||
public ulong SubOffset;
|
||||
|
||||
public string ImageDisplay => $"{ImageName}:0x{Offset:x4}";
|
||||
public string SubDisplay => SubOffset == 0 ? SubName : $"{SubName}:0x{SubOffset:x4}";
|
||||
public string SpDisplay => SubOffset == 0 ? "SP" : $"SP:-0x{SubOffset:x4}";
|
||||
public readonly string ImageDisplay => $"{ImageName}:0x{Offset:x4}";
|
||||
public readonly string SubDisplay => SubOffset == 0 ? SubName : $"{SubName}:0x{SubOffset:x4}";
|
||||
public readonly string SpDisplay => SubOffset == 0 ? "SP" : $"SP:-0x{SubOffset:x4}";
|
||||
}
|
||||
|
||||
private bool AnalyzePointer(out PointerInfo info, ulong address, KThread thread)
|
||||
|
@ -324,7 +324,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
private void ScanMemoryForTextSegments()
|
||||
{
|
||||
ulong oldAddress = 0;
|
||||
ulong address = 0;
|
||||
ulong address = 0;
|
||||
|
||||
while (address >= oldAddress)
|
||||
{
|
||||
|
@ -355,7 +355,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return;
|
||||
}
|
||||
|
||||
Dictionary<ElfDynamicTag, ulong> dynamic = new Dictionary<ElfDynamicTag, ulong>();
|
||||
Dictionary<ElfDynamicTag, ulong> dynamic = new();
|
||||
|
||||
int mod0Magic = memory.Read<int>(mod0Offset + 0x0);
|
||||
|
||||
|
@ -364,12 +364,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return;
|
||||
}
|
||||
|
||||
ulong dynamicOffset = memory.Read<uint>(mod0Offset + 0x4) + mod0Offset;
|
||||
ulong bssStartOffset = memory.Read<uint>(mod0Offset + 0x8) + mod0Offset;
|
||||
ulong bssEndOffset = memory.Read<uint>(mod0Offset + 0xc) + mod0Offset;
|
||||
ulong dynamicOffset = memory.Read<uint>(mod0Offset + 0x4) + mod0Offset;
|
||||
ulong bssStartOffset = memory.Read<uint>(mod0Offset + 0x8) + mod0Offset;
|
||||
ulong bssEndOffset = memory.Read<uint>(mod0Offset + 0xc) + mod0Offset;
|
||||
ulong ehHdrStartOffset = memory.Read<uint>(mod0Offset + 0x10) + mod0Offset;
|
||||
ulong ehHdrEndOffset = memory.Read<uint>(mod0Offset + 0x14) + mod0Offset;
|
||||
ulong modObjOffset = memory.Read<uint>(mod0Offset + 0x18) + mod0Offset;
|
||||
ulong ehHdrEndOffset = memory.Read<uint>(mod0Offset + 0x14) + mod0Offset;
|
||||
ulong modObjOffset = memory.Read<uint>(mod0Offset + 0x18) + mod0Offset;
|
||||
|
||||
bool isAArch32 = memory.Read<ulong>(dynamicOffset) > 0xFFFFFFFF || memory.Read<ulong>(dynamicOffset + 0x10) > 0xFFFFFFFF;
|
||||
|
||||
|
@ -381,14 +381,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
if (isAArch32)
|
||||
{
|
||||
tagVal = memory.Read<uint>(dynamicOffset + 0);
|
||||
value = memory.Read<uint>(dynamicOffset + 4);
|
||||
value = memory.Read<uint>(dynamicOffset + 4);
|
||||
|
||||
dynamicOffset += 0x8;
|
||||
}
|
||||
else
|
||||
{
|
||||
tagVal = memory.Read<ulong>(dynamicOffset + 0);
|
||||
value = memory.Read<ulong>(dynamicOffset + 8);
|
||||
value = memory.Read<ulong>(dynamicOffset + 8);
|
||||
|
||||
dynamicOffset += 0x10;
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
ulong strTblAddr = textOffset + strTab;
|
||||
ulong symTblAddr = textOffset + symTab;
|
||||
|
||||
List<ElfSymbol> symbols = new List<ElfSymbol>();
|
||||
List<ElfSymbol> symbols = new();
|
||||
|
||||
while (symTblAddr < strTblAddr)
|
||||
{
|
||||
|
@ -430,7 +430,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
}
|
||||
|
||||
private ElfSymbol GetSymbol64(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
|
||||
private static ElfSymbol GetSymbol64(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
|
||||
{
|
||||
ElfSymbol64 sym = memory.Read<ElfSymbol64>(address);
|
||||
|
||||
|
@ -446,7 +446,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size);
|
||||
}
|
||||
|
||||
private ElfSymbol GetSymbol32(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
|
||||
private static ElfSymbol GetSymbol32(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
|
||||
{
|
||||
ElfSymbol32 sym = memory.Read<ElfSymbol32>(address);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
private const int IdMasksCount = 8;
|
||||
|
||||
private int[] _idMasks;
|
||||
private readonly int[] _idMasks;
|
||||
|
||||
private int _nextFreeBitHint;
|
||||
|
||||
|
@ -67,17 +67,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
private bool TestBit(int bit)
|
||||
{
|
||||
return (_idMasks[_nextFreeBitHint / 32] & (1 << (_nextFreeBitHint & 31))) != 0;
|
||||
return (_idMasks[bit / 32] & (1 << (bit & 31))) != 0;
|
||||
}
|
||||
|
||||
private void SetBit(int bit)
|
||||
{
|
||||
_idMasks[_nextFreeBitHint / 32] |= (1 << (_nextFreeBitHint & 31));
|
||||
_idMasks[bit / 32] |= (1 << (bit & 31));
|
||||
}
|
||||
|
||||
private void ClearBit(int bit)
|
||||
{
|
||||
_idMasks[_nextFreeBitHint / 32] &= ~(1 << (_nextFreeBitHint & 31));
|
||||
_idMasks[bit / 32] &= ~(1 << (bit & 31));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
public int Index { get; private set; }
|
||||
|
||||
public ushort HandleId { get; set; }
|
||||
public KAutoObject Obj { get; set; }
|
||||
public ushort HandleId { get; set; }
|
||||
public KAutoObject Obj { get; set; }
|
||||
|
||||
public KHandleEntry(int index)
|
||||
{
|
||||
Index = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
class KHandleTable
|
||||
{
|
||||
public const int SelfThreadHandle = (0x1ffff << 15) | 0;
|
||||
public const int SelfThreadHandle = (0x1ffff << 15) | 0;
|
||||
public const int SelfProcessHandle = (0x1ffff << 15) | 1;
|
||||
|
||||
private readonly KernelContext _context;
|
||||
|
||||
private KHandleEntry[] _table;
|
||||
|
||||
private KHandleEntry _tableHead;
|
||||
|
@ -23,11 +21,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
private ushort _idCounter;
|
||||
|
||||
public KHandleTable(KernelContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public Result Initialize(uint size)
|
||||
{
|
||||
if (size > 1024)
|
||||
|
@ -81,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
_nextFreeEntry = entry.Next;
|
||||
|
||||
entry.Obj = obj;
|
||||
entry.Obj = obj;
|
||||
entry.HandleId = _idCounter;
|
||||
|
||||
_activeSlotsCount++;
|
||||
|
@ -143,7 +136,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
KHandleEntry entry = _table[index];
|
||||
|
||||
entry.Obj = null;
|
||||
entry.Obj = null;
|
||||
entry.Next = _nextFreeEntry;
|
||||
|
||||
_nextFreeEntry = entry;
|
||||
|
@ -154,14 +147,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
public void SetReservedHandleObj(int handle, KAutoObject obj)
|
||||
{
|
||||
int index = (handle >> 0) & 0x7fff;
|
||||
int index = (handle >> 0) & 0x7fff;
|
||||
int handleId = (handle >> 15);
|
||||
|
||||
lock (_table)
|
||||
{
|
||||
KHandleEntry entry = _table[index];
|
||||
|
||||
entry.Obj = obj;
|
||||
entry.Obj = obj;
|
||||
entry.HandleId = (ushort)handleId;
|
||||
|
||||
obj.IncrementReferenceCount();
|
||||
|
@ -177,7 +170,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return false;
|
||||
}
|
||||
|
||||
int index = (handle >> 0) & 0x7fff;
|
||||
int index = (handle >> 0) & 0x7fff;
|
||||
int handleId = (handle >> 15);
|
||||
|
||||
KAutoObject obj = null;
|
||||
|
@ -192,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
if ((obj = entry.Obj) != null && entry.HandleId == handleId)
|
||||
{
|
||||
entry.Obj = null;
|
||||
entry.Obj = null;
|
||||
entry.Next = _nextFreeEntry;
|
||||
|
||||
_nextFreeEntry = entry;
|
||||
|
@ -214,7 +207,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
public T GetObject<T>(int handle) where T : KAutoObject
|
||||
{
|
||||
int index = (handle >> 0) & 0x7fff;
|
||||
int index = (handle >> 0) & 0x7fff;
|
||||
int handleId = (handle >> 15);
|
||||
|
||||
lock (_table)
|
||||
|
@ -273,7 +266,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
|
||||
entry.Obj.DecrementReferenceCount();
|
||||
entry.Obj = null;
|
||||
entry.Obj = null;
|
||||
entry.Next = _nextFreeEntry;
|
||||
|
||||
_nextFreeEntry = entry;
|
||||
|
@ -282,4 +275,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
public KPageTableBase MemoryManager { get; private set; }
|
||||
|
||||
private SortedDictionary<ulong, KTlsPageInfo> _fullTlsPages;
|
||||
private SortedDictionary<ulong, KTlsPageInfo> _freeTlsPages;
|
||||
private readonly SortedDictionary<ulong, KTlsPageInfo> _fullTlsPages;
|
||||
private readonly SortedDictionary<ulong, KTlsPageInfo> _freeTlsPages;
|
||||
|
||||
public int DefaultCpuCore { get; set; }
|
||||
|
||||
|
@ -66,19 +66,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
public bool IsApplication { get; private set; }
|
||||
public ulong Pid { get; private set; }
|
||||
|
||||
private long _creationTimestamp;
|
||||
private ulong _entrypoint;
|
||||
private ThreadStart _customThreadStart;
|
||||
private ulong _imageSize;
|
||||
private ulong _mainThreadStackSize;
|
||||
private ulong _memoryUsageCapacity;
|
||||
private int _version;
|
||||
|
||||
public KHandleTable HandleTable { get; private set; }
|
||||
|
||||
public ulong UserExceptionContextAddress { get; private set; }
|
||||
|
||||
private LinkedList<KThread> _threads;
|
||||
private readonly LinkedList<KThread> _threads;
|
||||
|
||||
public bool IsPaused { get; private set; }
|
||||
|
||||
|
@ -107,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
PinnedThreads = new KThread[KScheduler.CpuCoresCount];
|
||||
|
||||
// TODO: Remove once we no longer need to initialize it externally.
|
||||
HandleTable = new KHandleTable(context);
|
||||
HandleTable = new KHandleTable();
|
||||
|
||||
_threads = new LinkedList<KThread>();
|
||||
|
||||
|
@ -347,10 +345,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
State = ProcessState.Created;
|
||||
|
||||
_creationTimestamp = PerformanceCounter.ElapsedMilliseconds;
|
||||
|
||||
Flags = creationInfo.Flags;
|
||||
_version = creationInfo.Version;
|
||||
TitleId = creationInfo.TitleId;
|
||||
_entrypoint = creationInfo.CodeAddress;
|
||||
_imageSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
||||
|
@ -370,8 +365,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
MemoryManager.AliasRegionEnd -
|
||||
MemoryManager.AliasRegionStart;
|
||||
break;
|
||||
|
||||
default: throw new InvalidOperationException($"Invalid MMU flags value 0x{Flags:x2}.");
|
||||
default:
|
||||
throw new InvalidOperationException($"Invalid MMU flags value 0x{Flags:x2}.");
|
||||
}
|
||||
|
||||
GenerateRandomEntropy();
|
||||
|
@ -476,9 +471,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
Result result = Result.Success;
|
||||
|
||||
KTlsPageInfo pageInfo;
|
||||
|
||||
if (_fullTlsPages.TryGetValue(tlsPageAddr, out pageInfo))
|
||||
if (_fullTlsPages.TryGetValue(tlsPageAddr, out KTlsPageInfo pageInfo))
|
||||
{
|
||||
// TLS page was full, free slot and move to free pages tree.
|
||||
_fullTlsPages.Remove(tlsPageAddr);
|
||||
|
@ -525,10 +519,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
private void GenerateRandomEntropy()
|
||||
{
|
||||
// TODO.
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
public Result Start(int mainThreadPriority, ulong stackSize)
|
||||
{
|
||||
|
@ -549,7 +545,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
if (_mainThreadStackSize != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Trying to start a process with a invalid state!");
|
||||
throw new InvalidOperationException("Trying to start a process with an invalid state!");
|
||||
}
|
||||
|
||||
ulong stackSizeRounded = BitUtils.AlignUp<ulong>(stackSize, KPageTableBase.PageSize);
|
||||
|
@ -648,7 +644,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return result;
|
||||
}
|
||||
|
||||
HandleTable = new KHandleTable(KernelContext);
|
||||
HandleTable = new KHandleTable();
|
||||
|
||||
result = HandleTable.Initialize(Capabilities.HandleTableSize);
|
||||
|
||||
|
@ -1018,22 +1014,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
}
|
||||
|
||||
private void SignalExitToDebugTerminated()
|
||||
private static void SignalExitToDebugTerminated()
|
||||
{
|
||||
// TODO: Debug events.
|
||||
}
|
||||
|
||||
private void SignalExitToDebugExited()
|
||||
private static void SignalExitToDebugExited()
|
||||
{
|
||||
// TODO: Debug events.
|
||||
}
|
||||
|
||||
private void SignalExit()
|
||||
{
|
||||
if (ResourceLimit != null)
|
||||
{
|
||||
ResourceLimit.Release(LimitableResource.Memory, GetMemoryUsage());
|
||||
}
|
||||
ResourceLimit?.Release(LimitableResource.Memory, GetMemoryUsage());
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
|
@ -1075,7 +1068,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
ProcessCreationFlags.AddressSpace64BitDeprecated => 36,
|
||||
ProcessCreationFlags.AddressSpace32BitWithoutAlias => 32,
|
||||
ProcessCreationFlags.AddressSpace64Bit => 39,
|
||||
_ => 39
|
||||
_ => 39,
|
||||
};
|
||||
|
||||
bool for64Bit = flags.HasFlag(ProcessCreationFlags.Is64Bit);
|
||||
|
@ -1184,10 +1177,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsExceptionUserThread(KThread thread)
|
||||
public static bool IsExceptionUserThread(KThread thread)
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
public byte[] SvcAccessMask { get; }
|
||||
public byte[] IrqAccessMask { get; }
|
||||
|
||||
public ulong AllowedCpuCoresMask { get; private set; }
|
||||
public ulong AllowedCpuCoresMask { get; private set; }
|
||||
public ulong AllowedThreadPriosMask { get; private set; }
|
||||
|
||||
public uint DebuggingFlags { get; private set; }
|
||||
public uint HandleTableSize { get; private set; }
|
||||
public uint DebuggingFlags { get; private set; }
|
||||
public uint HandleTableSize { get; private set; }
|
||||
public uint KernelReleaseVersion { get; private set; }
|
||||
public uint ApplicationType { get; private set; }
|
||||
public uint ApplicationType { get; private set; }
|
||||
|
||||
public KProcessCapabilities()
|
||||
{
|
||||
|
@ -28,10 +28,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
public Result InitializeForKernel(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
|
||||
{
|
||||
AllowedCpuCoresMask = 0xf;
|
||||
AllowedCpuCoresMask = 0xf;
|
||||
AllowedThreadPriosMask = ulong.MaxValue;
|
||||
DebuggingFlags &= ~3u;
|
||||
KernelReleaseVersion = KProcess.KernelVersionPacked;
|
||||
DebuggingFlags &= ~3u;
|
||||
KernelReleaseVersion = KProcess.KernelVersionPacked;
|
||||
|
||||
return Parse(capabilities, memoryManager);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
|
||||
long address = ((long)prevCap << 5) & 0xffffff000;
|
||||
long size = ((long)cap << 5) & 0xfffff000;
|
||||
long size = ((long)cap << 5) & 0xfffff000;
|
||||
|
||||
if (((ulong)(address + size - 1) >> 36) != 0)
|
||||
{
|
||||
|
@ -101,11 +101,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
if ((cap >> 31) != 0)
|
||||
{
|
||||
result = memoryManager.MapNormalMemory(address, size, perm);
|
||||
result = KPageTableBase.MapNormalMemory(address, size, perm);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = memoryManager.MapIoMemory(address, size, perm);
|
||||
result = KPageTableBase.MapIoMemory(address, size, perm);
|
||||
}
|
||||
|
||||
if (result != Result.Success)
|
||||
|
@ -144,168 +144,168 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
switch (code)
|
||||
{
|
||||
case CapabilityType.CorePriority:
|
||||
{
|
||||
if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0)
|
||||
{
|
||||
return KernelResult.InvalidCapability;
|
||||
if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0)
|
||||
{
|
||||
return KernelResult.InvalidCapability;
|
||||
}
|
||||
|
||||
uint lowestCpuCore = (cap >> 16) & 0xff;
|
||||
uint highestCpuCore = (cap >> 24) & 0xff;
|
||||
|
||||
if (lowestCpuCore > highestCpuCore)
|
||||
{
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
uint highestThreadPrio = (cap >> 4) & 0x3f;
|
||||
uint lowestThreadPrio = (cap >> 10) & 0x3f;
|
||||
|
||||
if (lowestThreadPrio > highestThreadPrio)
|
||||
{
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
if (highestCpuCore >= KScheduler.CpuCoresCount)
|
||||
{
|
||||
return KernelResult.InvalidCpuCore;
|
||||
}
|
||||
|
||||
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
|
||||
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uint lowestCpuCore = (cap >> 16) & 0xff;
|
||||
uint highestCpuCore = (cap >> 24) & 0xff;
|
||||
|
||||
if (lowestCpuCore > highestCpuCore)
|
||||
{
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
uint highestThreadPrio = (cap >> 4) & 0x3f;
|
||||
uint lowestThreadPrio = (cap >> 10) & 0x3f;
|
||||
|
||||
if (lowestThreadPrio > highestThreadPrio)
|
||||
{
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
if (highestCpuCore >= KScheduler.CpuCoresCount)
|
||||
{
|
||||
return KernelResult.InvalidCpuCore;
|
||||
}
|
||||
|
||||
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
|
||||
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.SyscallMask:
|
||||
{
|
||||
int slot = ((int)cap >> 29) & 7;
|
||||
|
||||
int svcSlotMask = 1 << slot;
|
||||
|
||||
if ((mask1 & svcSlotMask) != 0)
|
||||
{
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
int slot = ((int)cap >> 29) & 7;
|
||||
|
||||
mask1 |= svcSlotMask;
|
||||
int svcSlotMask = 1 << slot;
|
||||
|
||||
uint svcMask = (cap >> 5) & 0xffffff;
|
||||
|
||||
int baseSvc = slot * 24;
|
||||
|
||||
for (int index = 0; index < 24; index++)
|
||||
{
|
||||
if (((svcMask >> index) & 1) == 0)
|
||||
if ((mask1 & svcSlotMask) != 0)
|
||||
{
|
||||
continue;
|
||||
return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
int svcId = baseSvc + index;
|
||||
mask1 |= svcSlotMask;
|
||||
|
||||
if (svcId >= KernelConstants.SupervisorCallCount)
|
||||
uint svcMask = (cap >> 5) & 0xffffff;
|
||||
|
||||
int baseSvc = slot * 24;
|
||||
|
||||
for (int index = 0; index < 24; index++)
|
||||
{
|
||||
return KernelResult.MaximumExceeded;
|
||||
if (((svcMask >> index) & 1) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int svcId = baseSvc + index;
|
||||
|
||||
if (svcId >= KernelConstants.SupervisorCallCount)
|
||||
{
|
||||
return KernelResult.MaximumExceeded;
|
||||
}
|
||||
|
||||
SvcAccessMask[svcId / 8] |= (byte)(1 << (svcId & 7));
|
||||
}
|
||||
|
||||
SvcAccessMask[svcId / 8] |= (byte)(1 << (svcId & 7));
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.MapIoPage:
|
||||
{
|
||||
long address = ((long)cap << 4) & 0xffffff000;
|
||||
{
|
||||
long address = ((long)cap << 4) & 0xffffff000;
|
||||
|
||||
memoryManager.MapIoMemory(address, KPageTableBase.PageSize, KMemoryPermission.ReadAndWrite);
|
||||
KPageTableBase.MapIoMemory(address, KPageTableBase.PageSize, KMemoryPermission.ReadAndWrite);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.MapRegion:
|
||||
{
|
||||
// TODO: Implement capabilities for MapRegion
|
||||
{
|
||||
// TODO: Implement capabilities for MapRegion
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.InterruptPair:
|
||||
{
|
||||
// TODO: GIC distributor check.
|
||||
int irq0 = ((int)cap >> 12) & 0x3ff;
|
||||
int irq1 = ((int)cap >> 22) & 0x3ff;
|
||||
|
||||
if (irq0 != 0x3ff)
|
||||
{
|
||||
IrqAccessMask[irq0 / 8] |= (byte)(1 << (irq0 & 7));
|
||||
}
|
||||
// TODO: GIC distributor check.
|
||||
int irq0 = ((int)cap >> 12) & 0x3ff;
|
||||
int irq1 = ((int)cap >> 22) & 0x3ff;
|
||||
|
||||
if (irq1 != 0x3ff)
|
||||
{
|
||||
IrqAccessMask[irq1 / 8] |= (byte)(1 << (irq1 & 7));
|
||||
}
|
||||
if (irq0 != 0x3ff)
|
||||
{
|
||||
IrqAccessMask[irq0 / 8] |= (byte)(1 << (irq0 & 7));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (irq1 != 0x3ff)
|
||||
{
|
||||
IrqAccessMask[irq1 / 8] |= (byte)(1 << (irq1 & 7));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.ProgramType:
|
||||
{
|
||||
uint applicationType = (cap >> 14);
|
||||
|
||||
if (applicationType > 7)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
uint applicationType = (cap >> 14);
|
||||
|
||||
if (applicationType > 7)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
}
|
||||
|
||||
ApplicationType = applicationType;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ApplicationType = applicationType;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.KernelVersion:
|
||||
{
|
||||
// Note: This check is bugged on kernel too, we are just replicating the bug here.
|
||||
if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
// Note: This check is bugged on kernel too, we are just replicating the bug here.
|
||||
if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
}
|
||||
|
||||
KernelReleaseVersion = cap;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
KernelReleaseVersion = cap;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.HandleTable:
|
||||
{
|
||||
uint handleTableSize = cap >> 26;
|
||||
|
||||
if (handleTableSize > 0x3ff)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
uint handleTableSize = cap >> 26;
|
||||
|
||||
if (handleTableSize > 0x3ff)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
}
|
||||
|
||||
HandleTableSize = handleTableSize;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
HandleTableSize = handleTableSize;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CapabilityType.DebugFlags:
|
||||
{
|
||||
uint debuggingFlags = cap >> 19;
|
||||
|
||||
if (debuggingFlags > 3)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
uint debuggingFlags = cap >> 19;
|
||||
|
||||
if (debuggingFlags > 3)
|
||||
{
|
||||
return KernelResult.ReservedValue;
|
||||
}
|
||||
|
||||
DebuggingFlags &= ~3u;
|
||||
DebuggingFlags |= debuggingFlags;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
DebuggingFlags &= ~3u;
|
||||
DebuggingFlags |= debuggingFlags;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: return KernelResult.InvalidCapability;
|
||||
default:
|
||||
return KernelResult.InvalidCapability;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
|
@ -325,4 +325,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
return mask << (int)min;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,4 +74,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
_isSlotFree[(address - PageVirtualAddress) / TlsEntrySize] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
private const int TlsEntrySize = 0x200;
|
||||
|
||||
private long _pagePosition;
|
||||
private readonly long _pagePosition;
|
||||
|
||||
private int _usedSlots;
|
||||
|
||||
private bool[] _slots;
|
||||
private readonly bool[] _slots;
|
||||
|
||||
public bool IsEmpty => _usedSlots == 0;
|
||||
public bool IsFull => _usedSlots == _slots.Length;
|
||||
public bool IsFull => _usedSlots == _slots.Length;
|
||||
|
||||
public KTlsPageManager(long pagePosition)
|
||||
{
|
||||
|
@ -58,4 +58,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
_usedSlots--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||
{
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
enum ProcessCreationFlags
|
||||
{
|
||||
Is64Bit = 1 << 0,
|
||||
|
@ -36,6 +38,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
IsApplication |
|
||||
DeprecatedUseSecureMemory |
|
||||
PoolPartitionMask |
|
||||
OptimizeMemoryAllocation
|
||||
OptimizeMemoryAllocation,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,4 +34,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
SystemResourcePagesCount = systemResourcePagesCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
public ulong Pc => 0UL;
|
||||
|
||||
public ulong CntfrqEl0 { get; set; }
|
||||
public ulong CntpctEl0 => 0UL;
|
||||
|
||||
public long TpidrEl0 { get; set; }
|
||||
public long TpidrroEl0 { get; set; }
|
||||
|
||||
|
@ -43,4 +40,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
enum ProcessState : byte
|
||||
{
|
||||
Created = 0,
|
||||
Created = 0,
|
||||
CreatedAttached = 1,
|
||||
Started = 2,
|
||||
Crashed = 3,
|
||||
Attached = 4,
|
||||
Exiting = 5,
|
||||
Exited = 6,
|
||||
DebugSuspended = 7
|
||||
Started = 2,
|
||||
Crashed = 3,
|
||||
Attached = 4,
|
||||
Exiting = 5,
|
||||
Exited = 6,
|
||||
DebugSuspended = 7,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
public ProcessTamperInfo(KProcess process, IEnumerable<string> buildIds, IEnumerable<ulong> codeAddresses, ulong heapAddress, ulong aliasAddress, ulong aslrAddress)
|
||||
{
|
||||
Process = process;
|
||||
BuildIds = buildIds;
|
||||
Process = process;
|
||||
BuildIds = buildIds;
|
||||
CodeAddresses = codeAddresses;
|
||||
HeapAddress = heapAddress;
|
||||
AliasAddress = aliasAddress;
|
||||
AslrAddress = aslrAddress;
|
||||
HeapAddress = heapAddress;
|
||||
AliasAddress = aliasAddress;
|
||||
AslrAddress = aslrAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
Map,
|
||||
MapToOwner,
|
||||
Unmap,
|
||||
UnmapFromOwner
|
||||
UnmapFromOwner,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,6 @@
|
|||
IsApplication,
|
||||
FreeThreadCount,
|
||||
ThreadTickCount,
|
||||
MesosphereCurrentProcess = 65001
|
||||
MesosphereCurrentProcess = 65001,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
public KMemoryPermission Permission;
|
||||
public int IpcRefCount;
|
||||
public int DeviceRefCount;
|
||||
#pragma warning disable CS0414
|
||||
private int _padding;
|
||||
#pragma warning restore CS0414
|
||||
#pragma warning disable CS0414, IDE0052 // Remove unread private member
|
||||
private readonly int _padding;
|
||||
#pragma warning restore CS0414, IDE0052
|
||||
|
||||
public MemoryInfo(
|
||||
ulong address,
|
||||
|
@ -34,4 +34,4 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
_padding = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
KHandleTable handleTable = KernelStatic.GetCurrentProcess().HandleTable;
|
||||
|
||||
KProcess process = new KProcess(_context);
|
||||
KProcess process = new(_context);
|
||||
|
||||
using var _ = new OnScopeExit(process.DecrementReferenceCount);
|
||||
|
||||
|
@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
ProcessCreationFlags.PoolPartitionApplet => MemoryRegion.Applet,
|
||||
ProcessCreationFlags.PoolPartitionSystem => MemoryRegion.Service,
|
||||
ProcessCreationFlags.PoolPartitionSystemNonSecure => MemoryRegion.NvServices,
|
||||
_ => MemoryRegion.NvServices
|
||||
_ => MemoryRegion.NvServices,
|
||||
};
|
||||
|
||||
Result result = process.Initialize(
|
||||
|
@ -138,6 +138,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return handleTable.GenerateHandle(process, out handle);
|
||||
}
|
||||
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KProcess>(handle);
|
||||
|
@ -170,14 +171,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x5f)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result FlushProcessDataCache(int processHandle, ulong address, ulong size)
|
||||
{
|
||||
// FIXME: This needs to be implemented as ARMv7 doesn't have any way to do cache maintenance operations on EL0.
|
||||
// As we don't support (and don't actually need) to flush the cache, this is stubbed.
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
// IPC
|
||||
|
||||
|
@ -251,6 +255,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x22)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SendSyncRequestWithUserBuffer(
|
||||
[PointerSized] ulong messagePtr,
|
||||
[PointerSized] ulong messageSize,
|
||||
|
@ -300,6 +305,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return result;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x23)]
|
||||
public Result SendAsyncRequestWithUserBuffer(
|
||||
|
@ -351,7 +357,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
else
|
||||
{
|
||||
KEvent doneEvent = new KEvent(_context);
|
||||
KEvent doneEvent = new(_context);
|
||||
|
||||
result = currentProcess.HandleTable.GenerateHandle(doneEvent.ReadableEvent, out doneEventHandle);
|
||||
|
||||
|
@ -408,7 +414,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
if (isLight)
|
||||
{
|
||||
KLightSession session = new KLightSession(_context);
|
||||
KLightSession session = new(_context);
|
||||
|
||||
result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle);
|
||||
|
||||
|
@ -429,7 +435,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
else
|
||||
{
|
||||
KSession session = new KSession(_context);
|
||||
KSession session = new(_context);
|
||||
|
||||
result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle);
|
||||
|
||||
|
@ -745,7 +751,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.MaximumExceeded;
|
||||
}
|
||||
|
||||
KPort port = new KPort(_context, maxSessions, isLight, name);
|
||||
KPort port = new(_context, maxSessions, isLight, name);
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -798,7 +804,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KAutoObject.RemoveName(_context, name);
|
||||
}
|
||||
|
||||
KPort port = new KPort(_context, maxSessions, false, null);
|
||||
KPort port = new(_context, maxSessions, false, null);
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -889,6 +895,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(2)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetMemoryPermission([PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -920,8 +927,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return currentProcess.MemoryManager.SetMemoryPermission(address, size, permission);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(3)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetMemoryAttribute(
|
||||
[PointerSized] ulong address,
|
||||
[PointerSized] ulong size,
|
||||
|
@ -961,8 +970,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return result;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(4)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result MapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] ulong size)
|
||||
{
|
||||
if (!PageAligned(src | dst))
|
||||
|
@ -998,8 +1009,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return process.MemoryManager.Map(dst, src, size);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(5)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result UnmapMemory([PointerSized] ulong dst, [PointerSized] ulong src, [PointerSized] ulong size)
|
||||
{
|
||||
if (!PageAligned(src | dst))
|
||||
|
@ -1035,6 +1048,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return process.MemoryManager.Unmap(dst, src, size);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(6)]
|
||||
public Result QueryMemory([PointerSized] ulong infoPtr, [PointerSized] out ulong pageInfo, [PointerSized] ulong address)
|
||||
|
@ -1051,6 +1065,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result QueryMemory(out MemoryInfo info, out ulong pageInfo, ulong address)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -1070,8 +1085,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x13)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result MapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -1117,8 +1134,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
currentProcess,
|
||||
permission);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x14)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result UnmapSharedMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -1158,6 +1177,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
size,
|
||||
currentProcess);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x15)]
|
||||
public Result CreateTransferMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
|
||||
|
@ -1205,7 +1225,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidMemState;
|
||||
}
|
||||
|
||||
KTransferMemory transferMemory = new KTransferMemory(_context);
|
||||
KTransferMemory transferMemory = new(_context);
|
||||
|
||||
Result result = transferMemory.Initialize(address, size, permission);
|
||||
|
||||
|
@ -1224,6 +1244,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x51)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result MapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size, KMemoryPermission permission)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -1269,8 +1290,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
currentProcess,
|
||||
permission);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x52)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result UnmapTransferMemory(int handle, [PointerSized] ulong address, [PointerSized] ulong size)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -1310,8 +1333,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
size,
|
||||
currentProcess);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x2c)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result MapPhysicalMemory([PointerSized] ulong address, [PointerSized] ulong size)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -1346,8 +1371,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return process.MemoryManager.MapPhysicalMemory(address, size);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x2d)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result UnmapPhysicalMemory([PointerSized] ulong address, [PointerSized] ulong size)
|
||||
{
|
||||
if (!PageAligned(address))
|
||||
|
@ -1382,6 +1409,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return process.MemoryManager.UnmapPhysicalMemory(address, size);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x4b)]
|
||||
public Result CreateCodeMemory(out int handle, [PointerSized] ulong address, [PointerSized] ulong size)
|
||||
|
@ -1403,7 +1431,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidMemState;
|
||||
}
|
||||
|
||||
KCodeMemory codeMemory = new KCodeMemory(_context);
|
||||
KCodeMemory codeMemory = new(_context);
|
||||
|
||||
using var _ = new OnScopeExit(codeMemory.DecrementReferenceCount);
|
||||
|
||||
|
@ -1425,6 +1453,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x4c)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result ControlCodeMemory(
|
||||
int handle,
|
||||
CodeMemoryOperation op,
|
||||
|
@ -1498,11 +1527,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return codeMemory.UnmapFromOwner(address, size);
|
||||
|
||||
default: return KernelResult.InvalidEnumValue;
|
||||
default:
|
||||
return KernelResult.InvalidEnumValue;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x73)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetProcessMemoryPermission(
|
||||
int handle,
|
||||
[PointerSized] ulong src,
|
||||
|
@ -1543,8 +1575,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x74)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result MapProcessMemory(
|
||||
[PointerSized] ulong dst,
|
||||
int handle,
|
||||
|
@ -1580,7 +1614,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidMemRange;
|
||||
}
|
||||
|
||||
KPageList pageList = new KPageList();
|
||||
KPageList pageList = new();
|
||||
|
||||
Result result = srcProcess.MemoryManager.GetPagesIfStateEquals(
|
||||
src,
|
||||
|
@ -1600,8 +1634,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return dstProcess.MemoryManager.MapPages(dst, pageList, MemoryState.ProcessMemory, KMemoryPermission.ReadAndWrite);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x75)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result UnmapProcessMemory(
|
||||
[PointerSized] ulong dst,
|
||||
int handle,
|
||||
|
@ -1646,8 +1682,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x77)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size)
|
||||
{
|
||||
if (!PageAligned(dst) || !PageAligned(src))
|
||||
|
@ -1684,8 +1722,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return targetProcess.MemoryManager.MapProcessCodeMemory(dst, src, size);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x78)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size)
|
||||
{
|
||||
if (!PageAligned(dst) || !PageAligned(src))
|
||||
|
@ -1722,6 +1762,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
private static bool PageAligned(ulong address)
|
||||
{
|
||||
|
@ -1731,6 +1772,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
// System
|
||||
|
||||
[Svc(0x7b)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result TerminateProcess(int handle)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -1759,12 +1801,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return result;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(7)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public void ExitProcess()
|
||||
{
|
||||
KernelStatic.GetCurrentProcess().TerminateCurrentProcess();
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x11)]
|
||||
public Result SignalEvent(int handle)
|
||||
|
@ -1857,6 +1902,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x26)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public void Break(ulong reason)
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
@ -1882,8 +1928,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
Logger.Debug?.Print(LogClass.KernelSvc, "Debugger triggered.");
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x27)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public void OutputDebugString([PointerSized] ulong strPtr, [PointerSized] ulong size)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -1892,6 +1940,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
Logger.Warning?.Print(LogClass.KernelSvc, str);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x29)]
|
||||
public Result GetInfo(out ulong value, InfoType id, int handle, long subId)
|
||||
|
@ -1937,33 +1986,56 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
switch (id)
|
||||
{
|
||||
case InfoType.CoreMask: value = process.Capabilities.AllowedCpuCoresMask; break;
|
||||
case InfoType.PriorityMask: value = process.Capabilities.AllowedThreadPriosMask; break;
|
||||
case InfoType.CoreMask:
|
||||
value = process.Capabilities.AllowedCpuCoresMask;
|
||||
break;
|
||||
case InfoType.PriorityMask:
|
||||
value = process.Capabilities.AllowedThreadPriosMask;
|
||||
break;
|
||||
|
||||
case InfoType.AliasRegionAddress: value = process.MemoryManager.AliasRegionStart; break;
|
||||
case InfoType.AliasRegionAddress:
|
||||
value = process.MemoryManager.AliasRegionStart;
|
||||
break;
|
||||
case InfoType.AliasRegionSize:
|
||||
value = (process.MemoryManager.AliasRegionEnd -
|
||||
process.MemoryManager.AliasRegionStart); break;
|
||||
process.MemoryManager.AliasRegionStart);
|
||||
break;
|
||||
|
||||
case InfoType.HeapRegionAddress: value = process.MemoryManager.HeapRegionStart; break;
|
||||
case InfoType.HeapRegionAddress:
|
||||
value = process.MemoryManager.HeapRegionStart;
|
||||
break;
|
||||
case InfoType.HeapRegionSize:
|
||||
value = (process.MemoryManager.HeapRegionEnd -
|
||||
process.MemoryManager.HeapRegionStart); break;
|
||||
process.MemoryManager.HeapRegionStart);
|
||||
break;
|
||||
|
||||
case InfoType.TotalMemorySize: value = process.GetMemoryCapacity(); break;
|
||||
case InfoType.TotalMemorySize:
|
||||
value = process.GetMemoryCapacity();
|
||||
break;
|
||||
|
||||
case InfoType.UsedMemorySize: value = process.GetMemoryUsage(); break;
|
||||
case InfoType.UsedMemorySize:
|
||||
value = process.GetMemoryUsage();
|
||||
break;
|
||||
|
||||
case InfoType.AslrRegionAddress: value = process.MemoryManager.GetAddrSpaceBaseAddr(); break;
|
||||
case InfoType.AslrRegionAddress:
|
||||
value = process.MemoryManager.GetAddrSpaceBaseAddr();
|
||||
break;
|
||||
|
||||
case InfoType.AslrRegionSize: value = process.MemoryManager.GetAddrSpaceSize(); break;
|
||||
case InfoType.AslrRegionSize:
|
||||
value = process.MemoryManager.GetAddrSpaceSize();
|
||||
break;
|
||||
|
||||
case InfoType.StackRegionAddress: value = process.MemoryManager.StackRegionStart; break;
|
||||
case InfoType.StackRegionAddress:
|
||||
value = process.MemoryManager.StackRegionStart;
|
||||
break;
|
||||
case InfoType.StackRegionSize:
|
||||
value = (process.MemoryManager.StackRegionEnd -
|
||||
process.MemoryManager.StackRegionStart); break;
|
||||
process.MemoryManager.StackRegionStart);
|
||||
break;
|
||||
|
||||
case InfoType.SystemResourceSizeTotal: value = process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break;
|
||||
case InfoType.SystemResourceSizeTotal:
|
||||
value = process.PersonalMmHeapPagesCount * KPageTableBase.PageSize;
|
||||
break;
|
||||
|
||||
case InfoType.SystemResourceSizeUsed:
|
||||
if (process.PersonalMmHeapPagesCount != 0)
|
||||
|
@ -1973,15 +2045,25 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
break;
|
||||
|
||||
case InfoType.ProgramId: value = process.TitleId; break;
|
||||
case InfoType.ProgramId:
|
||||
value = process.TitleId;
|
||||
break;
|
||||
|
||||
case InfoType.UserExceptionContextAddress: value = process.UserExceptionContextAddress; break;
|
||||
case InfoType.UserExceptionContextAddress:
|
||||
value = process.UserExceptionContextAddress;
|
||||
break;
|
||||
|
||||
case InfoType.TotalNonSystemMemorySize: value = process.GetMemoryCapacityWithoutPersonalMmHeap(); break;
|
||||
case InfoType.TotalNonSystemMemorySize:
|
||||
value = process.GetMemoryCapacityWithoutPersonalMmHeap();
|
||||
break;
|
||||
|
||||
case InfoType.UsedNonSystemMemorySize: value = process.GetMemoryUsageWithoutPersonalMmHeap(); break;
|
||||
case InfoType.UsedNonSystemMemorySize:
|
||||
value = process.GetMemoryUsageWithoutPersonalMmHeap();
|
||||
break;
|
||||
|
||||
case InfoType.IsApplication: value = process.IsApplication ? 1UL : 0UL; break;
|
||||
case InfoType.IsApplication:
|
||||
value = process.IsApplication ? 1UL : 0UL;
|
||||
break;
|
||||
|
||||
case InfoType.FreeThreadCount:
|
||||
if (process.ResourceLimit != null)
|
||||
|
@ -2160,7 +2242,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
break;
|
||||
}
|
||||
|
||||
default: return KernelResult.InvalidEnumValue;
|
||||
default:
|
||||
return KernelResult.InvalidEnumValue;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
|
@ -2169,7 +2252,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
[Svc(0x45)]
|
||||
public Result CreateEvent(out int wEventHandle, out int rEventHandle)
|
||||
{
|
||||
KEvent Event = new KEvent(_context);
|
||||
KEvent Event = new(_context);
|
||||
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -2269,7 +2352,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
switch (id)
|
||||
{
|
||||
// Memory region capacity.
|
||||
case 0: value = (long)region.Size; break;
|
||||
case 0:
|
||||
value = (long)region.Size;
|
||||
break;
|
||||
|
||||
// Memory region free space.
|
||||
case 1:
|
||||
|
@ -2291,8 +2376,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
switch (subId)
|
||||
{
|
||||
case 0: value = _context.PrivilegedProcessLowestId; break;
|
||||
case 1: value = _context.PrivilegedProcessHighestId; break;
|
||||
case 0:
|
||||
value = _context.PrivilegedProcessLowestId;
|
||||
break;
|
||||
case 1:
|
||||
value = _context.PrivilegedProcessHighestId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2300,6 +2389,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x30)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetResourceLimitLimitValue(out long limitValue, int handle, LimitableResource resource)
|
||||
{
|
||||
limitValue = 0;
|
||||
|
@ -2320,8 +2410,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x31)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetResourceLimitCurrentValue(out long limitValue, int handle, LimitableResource resource)
|
||||
{
|
||||
limitValue = 0;
|
||||
|
@ -2342,8 +2434,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x37)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetResourceLimitPeakValue(out long peak, int handle, LimitableResource resource)
|
||||
{
|
||||
peak = 0;
|
||||
|
@ -2364,11 +2458,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x7d)]
|
||||
public Result CreateResourceLimit(out int handle)
|
||||
{
|
||||
KResourceLimit limit = new KResourceLimit(_context);
|
||||
KResourceLimit limit = new(_context);
|
||||
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -2376,6 +2471,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x7e)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetResourceLimitLimitValue(int handle, LimitableResource resource, long limitValue)
|
||||
{
|
||||
if (resource >= LimitableResource.Count)
|
||||
|
@ -2392,6 +2488,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return resourceLimit.SetLimitValue(resource, limitValue);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
// Thread
|
||||
|
||||
|
@ -2443,7 +2540,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.ResLimitExceeded;
|
||||
}
|
||||
|
||||
KThread thread = new KThread(_context);
|
||||
KThread thread = new(_context);
|
||||
|
||||
Result result = currentProcess.InitializeThread(
|
||||
thread,
|
||||
|
@ -2471,6 +2568,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(9)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result StartThread(int handle)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2497,14 +2595,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidHandle;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0xa)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public void ExitThread()
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
currentThread.Exit();
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0xb)]
|
||||
public void SleepThread(long timeout)
|
||||
|
@ -2513,9 +2614,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
{
|
||||
switch (timeout)
|
||||
{
|
||||
case 0: KScheduler.Yield(_context); break;
|
||||
case -1: KScheduler.YieldWithLoadBalancing(_context); break;
|
||||
case -2: KScheduler.YieldToAnyThread(_context); break;
|
||||
case 0:
|
||||
KScheduler.Yield(_context);
|
||||
break;
|
||||
case -1:
|
||||
KScheduler.YieldWithLoadBalancing(_context);
|
||||
break;
|
||||
case -2:
|
||||
KScheduler.YieldToAnyThread(_context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2525,6 +2632,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0xc)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetThreadPriority(out int priority, int handle)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2544,8 +2652,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidHandle;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0xd)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetThreadPriority(int handle, int priority)
|
||||
{
|
||||
// TODO: NPDM check.
|
||||
|
@ -2563,8 +2673,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0xe)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetThreadCoreMask(out int preferredCore, out ulong affinityMask, int handle)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2586,8 +2698,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidHandle;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0xf)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetThreadCoreMask(int handle, int preferredCore, ulong affinityMask)
|
||||
{
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2635,14 +2749,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return thread.SetCoreAndAffinityMask(preferredCore, affinityMask);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x10)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public int GetCurrentProcessorNumber()
|
||||
{
|
||||
return KernelStatic.GetCurrentThread().CurrentCore;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x25)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetThreadId(out ulong threadUid, int handle)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2662,8 +2780,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.InvalidHandle;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x32)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SetThreadActivity(int handle, bool pause)
|
||||
{
|
||||
KProcess process = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2687,8 +2807,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return thread.SetActivity(pause);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x33)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result GetThreadContext3([PointerSized] ulong address, int handle)
|
||||
{
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2722,6 +2844,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return result;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
// Thread synchronization
|
||||
|
||||
|
@ -2758,7 +2881,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return KernelResult.UserCopyFailed;
|
||||
}
|
||||
|
||||
Span<int> handles = new Span<int>(currentThread.WaitSyncHandles).Slice(0, handlesCount);
|
||||
Span<int> handles = new Span<int>(currentThread.WaitSyncHandles)[..handlesCount];
|
||||
|
||||
if (!KernelTransfer.UserToKernelArray(handlesPtr, handles))
|
||||
{
|
||||
|
@ -2782,7 +2905,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
var syncObjs = new Span<KSynchronizationObject>(currentThread.WaitSyncObjects).Slice(0, handles.Length);
|
||||
var syncObjs = new Span<KSynchronizationObject>(currentThread.WaitSyncObjects)[..handles.Length];
|
||||
|
||||
if (handles.Length != 0)
|
||||
{
|
||||
|
@ -2854,6 +2977,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
}
|
||||
|
||||
[Svc(0x1a)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result ArbitrateLock(int ownerHandle, [PointerSized] ulong mutexAddress, int requesterHandle)
|
||||
{
|
||||
if (IsPointingInsideKernel(mutexAddress))
|
||||
|
@ -2870,8 +2994,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x1b)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result ArbitrateUnlock([PointerSized] ulong mutexAddress)
|
||||
{
|
||||
if (IsPointingInsideKernel(mutexAddress))
|
||||
|
@ -2888,8 +3014,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x1c)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result WaitProcessWideKeyAtomic(
|
||||
[PointerSized] ulong mutexAddress,
|
||||
[PointerSized] ulong condVarAddress,
|
||||
|
@ -2919,8 +3047,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
handle,
|
||||
timeout);
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x1d)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SignalProcessWideKey([PointerSized] ulong address, int count)
|
||||
{
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
@ -2929,8 +3059,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x34)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result WaitForAddress([PointerSized] ulong address, ArbitrationType type, int value, long timeout)
|
||||
{
|
||||
if (IsPointingInsideKernel(address))
|
||||
|
@ -2961,8 +3093,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
_ => KernelResult.InvalidEnumValue,
|
||||
};
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x35)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SignalToAddress([PointerSized] ulong address, SignalType type, int value, int count)
|
||||
{
|
||||
if (IsPointingInsideKernel(address))
|
||||
|
@ -2985,17 +3119,20 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
=> currentProcess.AddressArbiter.SignalAndIncrementIfEqual(address, value, count),
|
||||
SignalType.SignalAndModifyIfEqual
|
||||
=> currentProcess.AddressArbiter.SignalAndModifyIfEqual(address, value, count),
|
||||
_ => KernelResult.InvalidEnumValue
|
||||
_ => KernelResult.InvalidEnumValue,
|
||||
};
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
[Svc(0x36)]
|
||||
#pragma warning disable CA1822 // Mark member as static
|
||||
public Result SynchronizePreemptionState()
|
||||
{
|
||||
KernelStatic.GetCurrentThread().SynchronizePreemptionState();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
#pragma warning restore CA1822
|
||||
|
||||
private static bool IsPointingInsideKernel(ulong address)
|
||||
{
|
||||
|
@ -3007,4 +3144,4 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
return (address & 3) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,4 +41,4 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
currentThread.HandlePostSyscall();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
public ulong Sp;
|
||||
public ulong Pc;
|
||||
public uint Pstate;
|
||||
#pragma warning disable CS0169
|
||||
private uint _padding;
|
||||
#pragma warning restore CS0169
|
||||
#pragma warning disable CS0169, IDE0051 // Remove unused private member
|
||||
private readonly uint _padding;
|
||||
#pragma warning restore CS0169, IDE0051
|
||||
public Array32<V128> FpuRegisters;
|
||||
public uint Fpcr;
|
||||
public uint Fpsr;
|
||||
|
|
|
@ -2,8 +2,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
enum ArbitrationType
|
||||
{
|
||||
WaitIfLessThan = 0,
|
||||
WaitIfLessThan = 0,
|
||||
DecrementAndWaitIfLessThan = 1,
|
||||
WaitIfEqual = 2
|
||||
WaitIfEqual = 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.ThreadTerminating;
|
||||
}
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = Result.Success;
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.InvalidHandle;
|
||||
}
|
||||
|
||||
currentThread.MutexAddress = mutexAddress;
|
||||
currentThread.MutexAddress = mutexAddress;
|
||||
currentThread.ThreadHandleForUserMutex = requesterHandle;
|
||||
|
||||
mutexOwner.AddMutexWaiter(currentThread);
|
||||
|
@ -76,10 +76,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_context.CriticalSection.Leave();
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
if (currentThread.MutexOwner != null)
|
||||
{
|
||||
currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
|
||||
}
|
||||
currentThread.MutexOwner?.RemoveMutexWaiter(currentThread);
|
||||
|
||||
_context.CriticalSection.Leave();
|
||||
|
||||
|
@ -103,7 +100,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
if (result != Result.Success && newOwnerThread != null)
|
||||
{
|
||||
newOwnerThread.SignaledObj = null;
|
||||
newOwnerThread.SignaledObj = null;
|
||||
newOwnerThread.ObjSyncResult = result;
|
||||
}
|
||||
|
||||
|
@ -118,7 +115,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = KernelResult.TimedOut;
|
||||
|
||||
if (currentThread.TerminationRequested)
|
||||
|
@ -139,9 +136,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.InvalidMemState;
|
||||
}
|
||||
|
||||
currentThread.MutexAddress = mutexAddress;
|
||||
currentThread.MutexAddress = mutexAddress;
|
||||
currentThread.ThreadHandleForUserMutex = threadHandle;
|
||||
currentThread.CondVarAddress = condVarAddress;
|
||||
currentThread.CondVarAddress = condVarAddress;
|
||||
|
||||
_condVarThreads.Add(currentThread);
|
||||
|
||||
|
@ -164,10 +161,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
if (currentThread.MutexOwner != null)
|
||||
{
|
||||
currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
|
||||
}
|
||||
currentThread.MutexOwner?.RemoveMutexWaiter(currentThread);
|
||||
|
||||
_condVarThreads.Remove(currentThread);
|
||||
|
||||
|
@ -176,7 +170,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return currentThread.ObjSyncResult;
|
||||
}
|
||||
|
||||
private (int, KThread) MutexUnlock(KThread currentThread, ulong mutexAddress)
|
||||
private static (int, KThread) MutexUnlock(KThread currentThread, ulong mutexAddress)
|
||||
{
|
||||
KThread newOwnerThread = currentThread.RelinquishMutex(mutexAddress, out int count);
|
||||
|
||||
|
@ -191,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
mutexValue |= HasListenersMask;
|
||||
}
|
||||
|
||||
newOwnerThread.SignaledObj = null;
|
||||
newOwnerThread.SignaledObj = null;
|
||||
newOwnerThread.ObjSyncResult = Result.Success;
|
||||
|
||||
newOwnerThread.ReleaseAndResume();
|
||||
|
@ -223,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
if (!currentProcess.CpuMemory.IsMapped(address))
|
||||
{
|
||||
// Invalid address.
|
||||
requester.SignaledObj = null;
|
||||
requester.SignaledObj = null;
|
||||
requester.ObjSyncResult = KernelResult.InvalidMemState;
|
||||
|
||||
return;
|
||||
|
@ -253,7 +247,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
if (mutexValue == 0)
|
||||
{
|
||||
// We now own the mutex.
|
||||
requester.SignaledObj = null;
|
||||
requester.SignaledObj = null;
|
||||
requester.ObjSyncResult = Result.Success;
|
||||
|
||||
requester.ReleaseAndResume();
|
||||
|
@ -273,7 +267,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
else
|
||||
{
|
||||
// Invalid mutex owner.
|
||||
requester.SignaledObj = null;
|
||||
requester.SignaledObj = null;
|
||||
requester.ObjSyncResult = KernelResult.InvalidHandle;
|
||||
|
||||
requester.ReleaseAndResume();
|
||||
|
@ -293,7 +287,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.ThreadTerminating;
|
||||
}
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = KernelResult.TimedOut;
|
||||
|
||||
if (!KernelTransfer.UserToKernel(out int currentValue, address))
|
||||
|
@ -312,7 +306,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.TimedOut;
|
||||
}
|
||||
|
||||
currentThread.MutexAddress = address;
|
||||
currentThread.MutexAddress = address;
|
||||
currentThread.WaitingInArbitration = true;
|
||||
|
||||
_arbiterThreads.Add(currentThread);
|
||||
|
@ -363,7 +357,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.ThreadTerminating;
|
||||
}
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = KernelResult.TimedOut;
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
@ -389,7 +383,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.TimedOut;
|
||||
}
|
||||
|
||||
currentThread.MutexAddress = address;
|
||||
currentThread.MutexAddress = address;
|
||||
currentThread.WaitingInArbitration = true;
|
||||
|
||||
_arbiterThreads.Add(currentThread);
|
||||
|
@ -551,7 +545,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
static void RemoveArbiterThread(KThread thread)
|
||||
{
|
||||
thread.SignaledObj = null;
|
||||
thread.SignaledObj = null;
|
||||
thread.ObjSyncResult = Result.Success;
|
||||
|
||||
thread.ReleaseAndResume();
|
||||
|
|
|
@ -67,4 +67,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
context.CriticalSection.Leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,4 +61,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
public KEvent(KernelContext context)
|
||||
{
|
||||
ReadableEvent = new KReadableEvent(context, this);
|
||||
ReadableEvent = new KReadableEvent(context);
|
||||
WritableEvent = new KWritableEvent(context, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_prioMask &= ~(1L << _prio);
|
||||
}
|
||||
|
||||
public KThread Current => _node?.Value;
|
||||
public readonly KThread Current => _node?.Value;
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
|
@ -283,4 +283,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return _scheduledThreadsPerPrioPerCore[prio][core];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
class KReadableEvent : KSynchronizationObject
|
||||
{
|
||||
private readonly KEvent _parent;
|
||||
|
||||
private bool _signaled;
|
||||
|
||||
public KReadableEvent(KernelContext context, KEvent parent) : base(context)
|
||||
public KReadableEvent(KernelContext context) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
public override void Signal()
|
||||
|
@ -62,4 +59,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return _signaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
partial class KScheduler : IDisposable
|
||||
{
|
||||
public const int PrioritiesCount = 64;
|
||||
public const int CpuCoresCount = 4;
|
||||
public const int CpuCoresCount = 4;
|
||||
|
||||
private const int RoundRobinTimeQuantumMs = 10;
|
||||
|
||||
private static readonly int[] PreemptionPriorities = new int[] { 59, 59, 59, 63 };
|
||||
private static readonly int[] _preemptionPriorities = { 59, 59, 59, 63 };
|
||||
|
||||
private static readonly int[] _srcCoresHighestPrioThreads = new int[CpuCoresCount];
|
||||
|
||||
|
@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
private KThread CreateIdleThread(KernelContext context, int cpuCore)
|
||||
{
|
||||
KThread idleThread = new KThread(context);
|
||||
KThread idleThread = new(context);
|
||||
|
||||
idleThread.Initialize(0UL, 0UL, 0UL, PrioritiesCount, cpuCore, null, ThreadType.Dummy, IdleThreadLoop);
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
KThread candidate = thread.Owner.PinnedThreads[core];
|
||||
|
||||
if (candidate.KernelWaitersCount == 0 && !thread.Owner.IsExceptionUserThread(candidate))
|
||||
if (candidate.KernelWaitersCount == 0 && !KProcess.IsExceptionUserThread(candidate))
|
||||
{
|
||||
if (candidate.SchedFlags == ThreadSchedState.Running)
|
||||
{
|
||||
|
@ -378,10 +378,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
currentThread.AddCpuTime(ticksDelta);
|
||||
|
||||
if (currentProcess != null)
|
||||
{
|
||||
currentProcess.AddCpuTime(ticksDelta);
|
||||
}
|
||||
currentProcess?.AddCpuTime(ticksDelta);
|
||||
|
||||
LastContextSwitchTime = currentTicks;
|
||||
|
||||
|
@ -411,7 +408,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
for (int core = 0; core < CpuCoresCount; core++)
|
||||
{
|
||||
RotateScheduledQueue(context, core, PreemptionPriorities[core]);
|
||||
RotateScheduledQueue(context, core, _preemptionPriorities[core]);
|
||||
}
|
||||
|
||||
context.CriticalSection.Leave();
|
||||
|
@ -431,7 +428,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
nextThread = context.PriorityQueue.Reschedule(prio, core, selectedThread);
|
||||
}
|
||||
|
||||
static KThread FirstSuitableCandidateOrDefault(KernelContext context, int core, KThread selectedThread, KThread nextThread, Predicate< KThread> predicate)
|
||||
static KThread FirstSuitableCandidateOrDefault(KernelContext context, int core, KThread selectedThread, KThread nextThread, Predicate<KThread> predicate)
|
||||
{
|
||||
foreach (KThread suggested in context.PriorityQueue.SuggestedThreads(core))
|
||||
{
|
||||
|
@ -651,11 +648,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
// Ensure that the idle thread is not blocked and can exit.
|
||||
lock (_idleInterruptEventLock)
|
||||
{
|
||||
if (_idleInterruptEvent != null)
|
||||
{
|
||||
_idleInterruptEvent.Set();
|
||||
}
|
||||
_idleInterruptEvent?.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
class KSynchronization
|
||||
{
|
||||
private KernelContext _context;
|
||||
private readonly KernelContext _context;
|
||||
|
||||
public KSynchronization(KernelContext context)
|
||||
{
|
||||
|
@ -68,8 +68,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
syncNodes[index] = syncObjs[index].AddWaitingThread(currentThread);
|
||||
}
|
||||
|
||||
currentThread.WaitingSync = true;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.WaitingSync = true;
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = result;
|
||||
|
||||
currentThread.Reschedule(ThreadSchedState.Paused);
|
||||
|
@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
||||
{
|
||||
thread.SignaledObj = syncObj;
|
||||
thread.SignaledObj = syncObj;
|
||||
thread.ObjSyncResult = Result.Success;
|
||||
|
||||
thread.Reschedule(ThreadSchedState.Running);
|
||||
|
@ -139,4 +139,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_context.CriticalSection.Leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,10 +68,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
public LinkedListNode<KThread> ProcessListNode { get; set; }
|
||||
|
||||
private LinkedList<KThread> _mutexWaiters;
|
||||
private readonly LinkedList<KThread> _mutexWaiters;
|
||||
private LinkedListNode<KThread> _mutexWaiterNode;
|
||||
|
||||
private LinkedList<KThread> _pinnedWaiters;
|
||||
private readonly LinkedList<KThread> _pinnedWaiters;
|
||||
|
||||
public KThread MutexOwner { get; private set; }
|
||||
|
||||
|
@ -659,7 +659,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
const int MaxRegistersAArch32 = 15;
|
||||
const int MaxFpuRegistersAArch32 = 16;
|
||||
|
||||
ThreadContext context = new ThreadContext();
|
||||
ThreadContext context = new();
|
||||
|
||||
if (Owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit))
|
||||
{
|
||||
|
@ -1433,4 +1433,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
Owner.CpuMemory.Write<ushort>(_tlsAddress + TlsUserInterruptFlagOffset, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return _parent.ReadableEvent.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
enum SignalType
|
||||
{
|
||||
Signal = 0,
|
||||
Signal = 0,
|
||||
SignalAndIncrementIfEqual = 1,
|
||||
SignalAndModifyIfEqual = 2
|
||||
SignalAndModifyIfEqual = 2,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
[Flags]
|
||||
enum ThreadSchedState : ushort
|
||||
{
|
||||
LowMask = 0xf,
|
||||
HighMask = 0xfff0,
|
||||
LowMask = 0xf,
|
||||
HighMask = 0xfff0,
|
||||
ForcePauseMask = 0x1f0,
|
||||
|
||||
ProcessPauseFlag = 1 << 4,
|
||||
ThreadPauseFlag = 1 << 5,
|
||||
ProcessPauseFlag = 1 << 4,
|
||||
ThreadPauseFlag = 1 << 5,
|
||||
ProcessDebugPauseFlag = 1 << 6,
|
||||
BacktracePauseFlag = 1 << 7,
|
||||
KernelInitPauseFlag = 1 << 8,
|
||||
BacktracePauseFlag = 1 << 7,
|
||||
KernelInitPauseFlag = 1 << 8,
|
||||
|
||||
None = 0,
|
||||
Paused = 1,
|
||||
Running = 2,
|
||||
TerminationPending = 3
|
||||
None = 0,
|
||||
Paused = 1,
|
||||
Running = 2,
|
||||
TerminationPending = 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
Dummy,
|
||||
Kernel,
|
||||
Kernel2,
|
||||
User
|
||||
User,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue