[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:
TSRBerry 2023-07-16 19:31:14 +02:00 committed by GitHub
parent fec8291c17
commit 326749498b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1015 changed files with 8173 additions and 7615 deletions

View file

@ -4,4 +4,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
{
void TimeUp();
}
}
}

View file

@ -70,4 +70,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
{
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -32,4 +32,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
return false;
}
}
}
}

View file

@ -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}\"."),
};
}
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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,
}
}
}

View file

@ -7,6 +7,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
MemoryArrange4GiBSystemDev,
MemoryArrange6GiB,
MemoryArrange6GiBAppletDev,
MemoryArrange8GiB
MemoryArrange8GiB,
}
}
}

View file

@ -4,6 +4,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
{
MemorySize4GiB = 0,
MemorySize6GiB = 1,
MemorySize8GiB = 2
MemorySize8GiB = 2,
}
}
}

View file

@ -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;

View file

@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
NotInitialized,
Open,
ClientDisconnected,
ServerDisconnected
ServerDisconnected,
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -13,4 +13,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
ClientSession = new KLightClientSession(context, this);
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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
}
}
}
}
}

View file

@ -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);
}
}
}
}
}

View file

@ -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
}
}
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -17,4 +17,4 @@ namespace Ryujinx.HLE.HOS.Kernel
public const ulong CounterFrequency = 19200000;
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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,
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -166,4 +166,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
Owner.DecrementReferenceCount();
}
}
}
}

View file

@ -153,4 +153,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
}
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -239,4 +239,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return (EndAddr - address) / KPageTableBase.PageSize;
}
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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();
}
}
}
}

View file

@ -7,8 +7,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public KPageNode(ulong address, ulong pagesCount)
{
Address = address;
Address = address;
PagesCount = pagesCount;
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
_pageList = null;
}
public void Dispose()
public readonly void Dispose()
{
_pageList?.DecrementPagesReferenceCount(_manager);
}

View file

@ -72,4 +72,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return memoryManager.UnmapPages(address, _pageList, MemoryState.SharedMemory);
}
}
}
}

View file

@ -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
}
}
}
}
}

View file

@ -127,4 +127,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
}
}
}
}
}

View file

@ -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,
}
}
}

View file

@ -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,
}
}
}

View file

@ -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,
}
}
}

View file

@ -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,
}
}
}

View file

@ -19,4 +19,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return (uint)BitOperations.TrailingZeroCount(type.GetFlag());
}
}
}
}

View file

@ -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,
}
}
}

View file

@ -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);

View file

@ -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));
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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
}
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -74,4 +74,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_isSlotFree[(address - PageVirtualAddress) / TlsEntrySize] = true;
}
}
}
}

View file

@ -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--;
}
}
}
}

View file

@ -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,
}
}

View file

@ -34,4 +34,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
SystemResourcePagesCount = systemResourcePagesCount;
}
}
}
}

View file

@ -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
{
}
}
}
}

View file

@ -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,
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Map,
MapToOwner,
Unmap,
UnmapFromOwner
UnmapFromOwner,
};
}
}

View file

@ -29,6 +29,6 @@
IsApplication,
FreeThreadCount,
ThreadTickCount,
MesosphereCurrentProcess = 65001
MesosphereCurrentProcess = 65001,
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -41,4 +41,4 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
currentThread.HandlePostSyscall();
}
}
}
}

View file

@ -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;

View file

@ -2,8 +2,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
enum ArbitrationType
{
WaitIfLessThan = 0,
WaitIfLessThan = 0,
DecrementAndWaitIfLessThan = 1,
WaitIfEqual = 2
WaitIfEqual = 2,
}
}
}

View file

@ -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();

View file

@ -67,4 +67,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
context.CriticalSection.Leave();
}
}
}
}

View file

@ -61,4 +61,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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];
}
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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();
}
}
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -22,4 +22,4 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
return _parent.ReadableEvent.Clear();
}
}
}
}

View file

@ -2,8 +2,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{
enum SignalType
{
Signal = 0,
Signal = 0,
SignalAndIncrementIfEqual = 1,
SignalAndModifyIfEqual = 2
SignalAndModifyIfEqual = 2,
}
}

View file

@ -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,
}
}
}

View file

@ -5,6 +5,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
Dummy,
Kernel,
Kernel2,
User
User,
}
}
}