mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-03-14 22:40:18 +00:00
IPC refactor part 3 + 4: New server HIPC message processor with source generator based serialization
This commit is contained in:
parent
02714a1291
commit
f8dc005e5c
196 changed files with 9262 additions and 842 deletions
|
@ -36,6 +36,7 @@ using Ryujinx.HLE.HOS.Services.SurfaceFlinger;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
|
using Ryujinx.Horizon;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -319,6 +320,43 @@ namespace Ryujinx.HLE.HOS
|
||||||
ViServer = new ServerBase(KernelContext, "ViServerU");
|
ViServer = new ServerBase(KernelContext, "ViServerU");
|
||||||
ViServerM = new ServerBase(KernelContext, "ViServerM");
|
ViServerM = new ServerBase(KernelContext, "ViServerM");
|
||||||
ViServerS = new ServerBase(KernelContext, "ViServerS");
|
ViServerS = new ServerBase(KernelContext, "ViServerS");
|
||||||
|
|
||||||
|
StartNewServices();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartNewServices()
|
||||||
|
{
|
||||||
|
var services = ServiceTable.GetServices(new HorizonOptions(Device.Configuration.IgnoreMissingServices));
|
||||||
|
|
||||||
|
foreach (var service in services)
|
||||||
|
{
|
||||||
|
const ProcessCreationFlags flags =
|
||||||
|
ProcessCreationFlags.EnableAslr |
|
||||||
|
ProcessCreationFlags.AddressSpace64Bit |
|
||||||
|
ProcessCreationFlags.Is64Bit |
|
||||||
|
ProcessCreationFlags.PoolPartitionSystem;
|
||||||
|
|
||||||
|
ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
|
||||||
|
|
||||||
|
int[] defaultCapabilities = new int[]
|
||||||
|
{
|
||||||
|
0x030363F7,
|
||||||
|
0x1FFFFFCF,
|
||||||
|
0x207FFFEF,
|
||||||
|
0x47E0060F,
|
||||||
|
0x0048BFFF,
|
||||||
|
0x01007FFF
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - Pass enough information (capabilities, process creation info, etc) on ServiceEntry for proper initialization.
|
||||||
|
// - Have the ThreadStart function take the syscall, address space and thread context parameters instead of passing
|
||||||
|
// them here.
|
||||||
|
KernelStatic.StartInitialProcess(KernelContext, creationInfo, defaultCapabilities, 44, () =>
|
||||||
|
{
|
||||||
|
service.Start(KernelContext.Syscall, KernelStatic.GetCurrentProcess().CpuMemory, KernelStatic.GetCurrentThread().ThreadContext);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadKip(string kipPath)
|
public void LoadKip(string kipPath)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -16,24 +17,24 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
_referenceCount = 1;
|
_referenceCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual KernelResult SetName(string name)
|
public virtual Result SetName(string name)
|
||||||
{
|
{
|
||||||
if (!KernelContext.AutoObjectNames.TryAdd(name, this))
|
if (!KernelContext.AutoObjectNames.TryAdd(name, this))
|
||||||
{
|
{
|
||||||
return KernelResult.InvalidState;
|
return KernelResult.InvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KernelResult RemoveName(KernelContext context, string name)
|
public static Result RemoveName(KernelContext context, string name)
|
||||||
{
|
{
|
||||||
if (!context.AutoObjectNames.TryRemove(name, out _))
|
if (!context.AutoObjectNames.TryRemove(name, out _))
|
||||||
{
|
{
|
||||||
return KernelResult.NotFound;
|
return KernelResult.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KAutoObject FindNamedObject(KernelContext context, string name)
|
public static KAutoObject FindNamedObject(KernelContext context, string name)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Common
|
namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
|
@ -159,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetLimitValue(LimitableResource resource, long limit)
|
public Result SetLimitValue(LimitableResource resource, long limit)
|
||||||
{
|
{
|
||||||
int index = GetIndex(resource);
|
int index = GetIndex(resource);
|
||||||
|
|
||||||
|
@ -170,7 +171,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
_limit[index] = limit;
|
_limit[index] = limit;
|
||||||
_peak[index] = _current[index];
|
_peak[index] = _current[index];
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Common
|
namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
|
@ -21,9 +22,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
|
|
||||||
public static void InitializeResourceLimit(KResourceLimit resourceLimit, MemorySize size)
|
public static void InitializeResourceLimit(KResourceLimit resourceLimit, MemorySize size)
|
||||||
{
|
{
|
||||||
void EnsureSuccess(KernelResult result)
|
void EnsureSuccess(Result result)
|
||||||
{
|
{
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Unexpected result \"{result}\".");
|
throw new InvalidOperationException($"Unexpected result \"{result}\".");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Common
|
|
||||||
{
|
|
||||||
enum KernelResult
|
|
||||||
{
|
|
||||||
Success = 0,
|
|
||||||
SessionCountExceeded = 0xe01,
|
|
||||||
InvalidCapability = 0x1c01,
|
|
||||||
ThreadNotStarted = 0x7201,
|
|
||||||
ThreadTerminating = 0x7601,
|
|
||||||
InvalidSize = 0xca01,
|
|
||||||
InvalidAddress = 0xcc01,
|
|
||||||
OutOfResource = 0xce01,
|
|
||||||
OutOfMemory = 0xd001,
|
|
||||||
HandleTableFull = 0xd201,
|
|
||||||
InvalidMemState = 0xd401,
|
|
||||||
InvalidPermission = 0xd801,
|
|
||||||
InvalidMemRange = 0xdc01,
|
|
||||||
InvalidPriority = 0xe001,
|
|
||||||
InvalidCpuCore = 0xe201,
|
|
||||||
InvalidHandle = 0xe401,
|
|
||||||
UserCopyFailed = 0xe601,
|
|
||||||
InvalidCombination = 0xe801,
|
|
||||||
TimedOut = 0xea01,
|
|
||||||
Cancelled = 0xec01,
|
|
||||||
MaximumExceeded = 0xee01,
|
|
||||||
InvalidEnumValue = 0xf001,
|
|
||||||
NotFound = 0xf201,
|
|
||||||
InvalidThread = 0xf401,
|
|
||||||
PortRemoteClosed = 0xf601,
|
|
||||||
InvalidState = 0xfa01,
|
|
||||||
ReservedValue = 0xfc01,
|
|
||||||
PortClosed = 0x10601,
|
|
||||||
ResLimitExceeded = 0x10801,
|
|
||||||
OutOfVaSpace = 0x20601,
|
|
||||||
CmdBufferTooSmall = 0x20801
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Common
|
|
||||||
{
|
|
||||||
readonly struct OnScopeExit : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Action _action;
|
|
||||||
public OnScopeExit(Action action) => _action = action;
|
|
||||||
public void Dispose() => _action();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
@ -20,38 +20,38 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
_exchangeBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
_exchangeBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult AddSendBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
public Result AddSendBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
||||||
{
|
{
|
||||||
return Add(_sendBufferDescriptors, src, dst, size, state);
|
return Add(_sendBufferDescriptors, src, dst, size, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult AddReceiveBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
public Result AddReceiveBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
||||||
{
|
{
|
||||||
return Add(_receiveBufferDescriptors, src, dst, size, state);
|
return Add(_receiveBufferDescriptors, src, dst, size, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult AddExchangeBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
public Result AddExchangeBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
||||||
{
|
{
|
||||||
return Add(_exchangeBufferDescriptors, src, dst, size, state);
|
return Add(_exchangeBufferDescriptors, src, dst, size, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult Add(List<KBufferDescriptor> list, ulong src, ulong dst, ulong size, MemoryState state)
|
private Result Add(List<KBufferDescriptor> list, ulong src, ulong dst, ulong size, MemoryState state)
|
||||||
{
|
{
|
||||||
if (list.Count < MaxInternalBuffersCount)
|
if (list.Count < MaxInternalBuffersCount)
|
||||||
{
|
{
|
||||||
list.Add(new KBufferDescriptor(src, dst, size, state));
|
list.Add(new KBufferDescriptor(src, dst, size, state));
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.OutOfMemory;
|
return KernelResult.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult CopyBuffersToClient(KPageTableBase memoryManager)
|
public Result CopyBuffersToClient(KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
KernelResult result = CopyToClient(memoryManager, _receiveBufferDescriptors);
|
Result result = CopyToClient(memoryManager, _receiveBufferDescriptors);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return CopyToClient(memoryManager, _exchangeBufferDescriptors);
|
return CopyToClient(memoryManager, _exchangeBufferDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult CopyToClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
private Result CopyToClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||||
{
|
{
|
||||||
foreach (KBufferDescriptor desc in list)
|
foreach (KBufferDescriptor desc in list)
|
||||||
{
|
{
|
||||||
|
@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
copySize = desc.Size;
|
copySize = desc.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = memoryManager.CopyDataFromCurrentProcess(
|
Result result = memoryManager.CopyDataFromCurrentProcess(
|
||||||
desc.ClientAddress,
|
desc.ClientAddress,
|
||||||
copySize,
|
copySize,
|
||||||
stateMask,
|
stateMask,
|
||||||
|
@ -104,7 +104,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
MemoryAttribute.None,
|
MemoryAttribute.None,
|
||||||
desc.ServerAddress);
|
desc.ServerAddress);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
if (clientEndAddrTruncated < clientEndAddrRounded &&
|
if (clientEndAddrTruncated < clientEndAddrRounded &&
|
||||||
(clientAddrTruncated == clientAddrRounded || clientAddrTruncated < clientEndAddrTruncated))
|
(clientAddrTruncated == clientAddrRounded || clientAddrTruncated < clientEndAddrTruncated))
|
||||||
{
|
{
|
||||||
KernelResult result = memoryManager.CopyDataFromCurrentProcess(
|
Result result = memoryManager.CopyDataFromCurrentProcess(
|
||||||
clientEndAddrTruncated,
|
clientEndAddrTruncated,
|
||||||
clientEndAddr - clientEndAddrTruncated,
|
clientEndAddr - clientEndAddrTruncated,
|
||||||
stateMask,
|
stateMask,
|
||||||
|
@ -130,28 +130,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
MemoryAttribute.None,
|
MemoryAttribute.None,
|
||||||
serverEndAddrTruncated);
|
serverEndAddrTruncated);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapServerBuffers(KPageTableBase memoryManager)
|
public Result UnmapServerBuffers(KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
KernelResult result = UnmapServer(memoryManager, _sendBufferDescriptors);
|
Result result = UnmapServer(memoryManager, _sendBufferDescriptors);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = UnmapServer(memoryManager, _receiveBufferDescriptors);
|
result = UnmapServer(memoryManager, _receiveBufferDescriptors);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -159,36 +159,36 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return UnmapServer(memoryManager, _exchangeBufferDescriptors);
|
return UnmapServer(memoryManager, _exchangeBufferDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult UnmapServer(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
private Result UnmapServer(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||||
{
|
{
|
||||||
foreach (KBufferDescriptor descriptor in list)
|
foreach (KBufferDescriptor descriptor in list)
|
||||||
{
|
{
|
||||||
KernelResult result = memoryManager.UnmapNoAttributeIfStateEquals(
|
Result result = memoryManager.UnmapNoAttributeIfStateEquals(
|
||||||
descriptor.ServerAddress,
|
descriptor.ServerAddress,
|
||||||
descriptor.Size,
|
descriptor.Size,
|
||||||
descriptor.State);
|
descriptor.State);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult RestoreClientBuffers(KPageTableBase memoryManager)
|
public Result RestoreClientBuffers(KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
KernelResult result = RestoreClient(memoryManager, _sendBufferDescriptors);
|
Result result = RestoreClient(memoryManager, _sendBufferDescriptors);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = RestoreClient(memoryManager, _receiveBufferDescriptors);
|
result = RestoreClient(memoryManager, _receiveBufferDescriptors);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -196,22 +196,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return RestoreClient(memoryManager, _exchangeBufferDescriptors);
|
return RestoreClient(memoryManager, _exchangeBufferDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult RestoreClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
private Result RestoreClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||||
{
|
{
|
||||||
foreach (KBufferDescriptor descriptor in list)
|
foreach (KBufferDescriptor descriptor in list)
|
||||||
{
|
{
|
||||||
KernelResult result = memoryManager.UnmapIpcRestorePermission(
|
Result result = memoryManager.UnmapIpcRestorePermission(
|
||||||
descriptor.ClientAddress,
|
descriptor.ClientAddress,
|
||||||
descriptor.Size,
|
descriptor.Size,
|
||||||
descriptor.State);
|
descriptor.State);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
@ -19,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Connect(out KClientSession clientSession)
|
public Result Connect(out KClientSession clientSession)
|
||||||
{
|
{
|
||||||
clientSession = null;
|
clientSession = null;
|
||||||
|
|
||||||
|
@ -40,9 +41,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
KSession session = new KSession(KernelContext, this);
|
KSession session = new KSession(KernelContext, this);
|
||||||
|
|
||||||
KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession);
|
Result result = _parent.EnqueueIncomingSession(session.ServerSession);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
session.ClientSession.DecrementReferenceCount();
|
session.ClientSession.DecrementReferenceCount();
|
||||||
session.ServerSession.DecrementReferenceCount();
|
session.ServerSession.DecrementReferenceCount();
|
||||||
|
@ -55,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult ConnectLight(out KLightClientSession clientSession)
|
public Result ConnectLight(out KLightClientSession clientSession)
|
||||||
{
|
{
|
||||||
clientSession = null;
|
clientSession = null;
|
||||||
|
|
||||||
|
@ -76,9 +77,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
KLightSession session = new KLightSession(KernelContext);
|
KLightSession session = new KLightSession(KernelContext);
|
||||||
|
|
||||||
KernelResult result = _parent.EnqueueIncomingLightSession(session.ServerSession);
|
Result result = _parent.EnqueueIncomingLightSession(session.ServerSession);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
session.ClientSession.DecrementReferenceCount();
|
session.ClientSession.DecrementReferenceCount();
|
||||||
session.ServerSession.DecrementReferenceCount();
|
session.ServerSession.DecrementReferenceCount();
|
||||||
|
@ -128,7 +129,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public new static KernelResult RemoveName(KernelContext context, string name)
|
public new static Result RemoveName(KernelContext context, string name)
|
||||||
{
|
{
|
||||||
KAutoObject foundObj = FindNamedObject(context, name);
|
KAutoObject foundObj = FindNamedObject(context, name);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
{
|
{
|
||||||
|
@ -27,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
CreatorProcess.IncrementReferenceCount();
|
CreatorProcess.IncrementReferenceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SendSyncRequest(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
public Result SendSyncRequest(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||||
{
|
{
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
|
@ -36,13 +37,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
currentThread.SignaledObj = null;
|
currentThread.SignaledObj = null;
|
||||||
currentThread.ObjSyncResult = KernelResult.Success;
|
currentThread.ObjSyncResult = Result.Success;
|
||||||
|
|
||||||
KernelResult result = _parent.ServerSession.EnqueueRequest(request);
|
Result result = _parent.ServerSession.EnqueueRequest(request);
|
||||||
|
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
result = currentThread.ObjSyncResult;
|
result = currentThread.ObjSyncResult;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SendAsyncRequest(KWritableEvent asyncEvent, ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
public Result SendAsyncRequest(KWritableEvent asyncEvent, ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||||
{
|
{
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
KernelResult result = _parent.ServerSession.EnqueueRequest(request);
|
Result result = _parent.ServerSession.EnqueueRequest(request);
|
||||||
|
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
{
|
{
|
||||||
|
@ -7,26 +8,26 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
public KServerPort ServerPort { get; }
|
public KServerPort ServerPort { get; }
|
||||||
public KClientPort ClientPort { get; }
|
public KClientPort ClientPort { get; }
|
||||||
|
|
||||||
private long _nameAddress;
|
private string _name;
|
||||||
|
|
||||||
private ChannelState _state;
|
private ChannelState _state;
|
||||||
|
|
||||||
public bool IsLight { get; private set; }
|
public bool IsLight { get; private set; }
|
||||||
|
|
||||||
public KPort(KernelContext context, int maxSessions, bool isLight, long nameAddress) : base(context)
|
public KPort(KernelContext context, int maxSessions, bool isLight, string name) : base(context)
|
||||||
{
|
{
|
||||||
ServerPort = new KServerPort(context, this);
|
ServerPort = new KServerPort(context, this);
|
||||||
ClientPort = new KClientPort(context, this, maxSessions);
|
ClientPort = new KClientPort(context, this, maxSessions);
|
||||||
|
|
||||||
IsLight = isLight;
|
IsLight = isLight;
|
||||||
_nameAddress = nameAddress;
|
_name = name;
|
||||||
|
|
||||||
_state = ChannelState.Open;
|
_state = ChannelState.Open;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult EnqueueIncomingSession(KServerSession session)
|
public Result EnqueueIncomingSession(KServerSession session)
|
||||||
{
|
{
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
{
|
{
|
||||||
ServerPort.EnqueueIncomingSession(session);
|
ServerPort.EnqueueIncomingSession(session);
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -46,9 +47,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult EnqueueIncomingLightSession(KLightServerSession session)
|
public Result EnqueueIncomingLightSession(KLightServerSession session)
|
||||||
{
|
{
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
{
|
{
|
||||||
ServerPort.EnqueueIncomingLightSession(session);
|
ServerPort.EnqueueIncomingLightSession(session);
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
@ -178,7 +179,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
_requests = new LinkedList<KSessionRequest>();
|
_requests = new LinkedList<KSessionRequest>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult EnqueueRequest(KSessionRequest request)
|
public Result EnqueueRequest(KSessionRequest request)
|
||||||
{
|
{
|
||||||
if (_parent.ClientSession.State != ChannelState.Open)
|
if (_parent.ClientSession.State != ChannelState.Open)
|
||||||
{
|
{
|
||||||
|
@ -203,10 +204,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
Signal();
|
Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
public Result Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||||
{
|
{
|
||||||
KThread serverThread = KernelStatic.GetCurrentThread();
|
KThread serverThread = KernelStatic.GetCurrentThread();
|
||||||
KProcess serverProcess = serverThread.Owner;
|
KProcess serverProcess = serverThread.Owner;
|
||||||
|
@ -249,12 +250,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
MessageHeader clientHeader = GetClientMessageHeader(clientProcess, clientMsg);
|
MessageHeader clientHeader = GetClientMessageHeader(clientProcess, clientMsg);
|
||||||
MessageHeader serverHeader = GetServerMessageHeader(serverMsg);
|
MessageHeader serverHeader = GetServerMessageHeader(serverMsg);
|
||||||
|
|
||||||
KernelResult serverResult = KernelResult.NotFound;
|
Result serverResult = KernelResult.NotFound;
|
||||||
KernelResult clientResult = KernelResult.Success;
|
Result clientResult = Result.Success;
|
||||||
|
|
||||||
void CleanUpForError()
|
void CleanUpForError()
|
||||||
{
|
{
|
||||||
if (request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager) == KernelResult.Success)
|
if (request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager) == Result.Success)
|
||||||
{
|
{
|
||||||
request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager);
|
request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager);
|
||||||
}
|
}
|
||||||
|
@ -348,7 +349,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
int newHandle = 0;
|
int newHandle = 0;
|
||||||
int handle = clientProcess.CpuMemory.Read<int>(clientMsg.Address + offset * 4);
|
int handle = clientProcess.CpuMemory.Read<int>(clientMsg.Address + offset * 4);
|
||||||
|
|
||||||
if (clientResult == KernelResult.Success && handle != 0)
|
if (clientResult == Result.Success && handle != 0)
|
||||||
{
|
{
|
||||||
clientResult = GetCopyObjectHandle(clientThread, serverProcess, handle, out newHandle);
|
clientResult = GetCopyObjectHandle(clientThread, serverProcess, handle, out newHandle);
|
||||||
}
|
}
|
||||||
|
@ -365,7 +366,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
if (handle != 0)
|
if (handle != 0)
|
||||||
{
|
{
|
||||||
if (clientResult == KernelResult.Success)
|
if (clientResult == Result.Success)
|
||||||
{
|
{
|
||||||
clientResult = GetMoveObjectHandle(clientProcess, serverProcess, handle, out newHandle);
|
clientResult = GetMoveObjectHandle(clientProcess, serverProcess, handle, out newHandle);
|
||||||
}
|
}
|
||||||
|
@ -380,7 +381,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -412,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
ref recvListDstOffset,
|
ref recvListDstOffset,
|
||||||
out ulong recvListBufferAddress);
|
out ulong recvListBufferAddress);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -429,7 +430,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
MemoryAttribute.Uncached,
|
MemoryAttribute.Uncached,
|
||||||
MemoryAttribute.None);
|
MemoryAttribute.None);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -498,7 +499,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
notReceiveDesc,
|
notReceiveDesc,
|
||||||
out dstAddress);
|
out dstAddress);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -518,7 +519,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
clientResult = request.BufferDescriptorTable.AddExchangeBuffer(bufferAddress, dstAddress, bufferSize, state);
|
clientResult = request.BufferDescriptorTable.AddExchangeBuffer(bufferAddress, dstAddress, bufferSize, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -573,7 +574,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
serverProcess.CpuMemory.Write(copyDst, clientProcess.CpuMemory.GetSpan(copySrc, (int)copySize));
|
serverProcess.CpuMemory.Write(copyDst, clientProcess.CpuMemory.GetSpan(copySrc, (int)copySize));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -581,10 +582,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Reply(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
public Result Reply(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||||
{
|
{
|
||||||
KThread serverThread = KernelStatic.GetCurrentThread();
|
KThread serverThread = KernelStatic.GetCurrentThread();
|
||||||
KProcess serverProcess = serverThread.Owner;
|
KProcess serverProcess = serverThread.Owner;
|
||||||
|
@ -618,8 +619,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
MessageHeader clientHeader = GetClientMessageHeader(clientProcess, clientMsg);
|
MessageHeader clientHeader = GetClientMessageHeader(clientProcess, clientMsg);
|
||||||
MessageHeader serverHeader = GetServerMessageHeader(serverMsg);
|
MessageHeader serverHeader = GetServerMessageHeader(serverMsg);
|
||||||
|
|
||||||
KernelResult clientResult = KernelResult.Success;
|
Result clientResult = Result.Success;
|
||||||
KernelResult serverResult = KernelResult.Success;
|
Result serverResult = Result.Success;
|
||||||
|
|
||||||
void CleanUpForError()
|
void CleanUpForError()
|
||||||
{
|
{
|
||||||
|
@ -683,7 +684,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
// Copy receive and exchange buffers.
|
// Copy receive and exchange buffers.
|
||||||
clientResult = request.BufferDescriptorTable.CopyBuffersToClient(clientProcess.MemoryManager);
|
clientResult = request.BufferDescriptorTable.CopyBuffersToClient(clientProcess.MemoryManager);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -734,7 +735,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
if (handle != 0)
|
if (handle != 0)
|
||||||
{
|
{
|
||||||
if (clientResult == KernelResult.Success)
|
if (clientResult == Result.Success)
|
||||||
{
|
{
|
||||||
clientResult = GetMoveObjectHandle(serverProcess, clientProcess, handle, out newHandle);
|
clientResult = GetMoveObjectHandle(serverProcess, clientProcess, handle, out newHandle);
|
||||||
}
|
}
|
||||||
|
@ -776,7 +777,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
ref recvListDstOffset,
|
ref recvListDstOffset,
|
||||||
out recvListBufferAddress);
|
out recvListBufferAddress);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -793,7 +794,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
MemoryAttribute.None,
|
MemoryAttribute.None,
|
||||||
descriptor.BufferAddress);
|
descriptor.BufferAddress);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -888,7 +889,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return new MessageHeader(word0, word1, word2);
|
return new MessageHeader(word0, word1, word2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult GetCopyObjectHandle(KThread srcThread, KProcess dstProcess, int srcHandle, out int dstHandle)
|
private Result GetCopyObjectHandle(KThread srcThread, KProcess dstProcess, int srcHandle, out int dstHandle)
|
||||||
{
|
{
|
||||||
dstHandle = 0;
|
dstHandle = 0;
|
||||||
|
|
||||||
|
@ -919,7 +920,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult GetMoveObjectHandle(KProcess srcProcess, KProcess dstProcess, int srcHandle, out int dstHandle)
|
private Result GetMoveObjectHandle(KProcess srcProcess, KProcess dstProcess, int srcHandle, out int dstHandle)
|
||||||
{
|
{
|
||||||
dstHandle = 0;
|
dstHandle = 0;
|
||||||
|
|
||||||
|
@ -927,7 +928,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
{
|
{
|
||||||
KernelResult result = dstProcess.HandleTable.GenerateHandle(obj, out dstHandle);
|
Result result = dstProcess.HandleTable.GenerateHandle(obj, out dstHandle);
|
||||||
|
|
||||||
srcProcess.HandleTable.CloseHandle(srcHandle);
|
srcProcess.HandleTable.CloseHandle(srcHandle);
|
||||||
|
|
||||||
|
@ -964,7 +965,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return receiveList;
|
return receiveList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult GetReceiveListAddress(
|
private Result GetReceiveListAddress(
|
||||||
PointerBufferDesc descriptor,
|
PointerBufferDesc descriptor,
|
||||||
Message message,
|
Message message,
|
||||||
uint recvListType,
|
uint recvListType,
|
||||||
|
@ -1038,7 +1039,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
address = recvListBufferAddress;
|
address = recvListBufferAddress;
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CloseAllHandles(Message message, MessageHeader header, KProcess process)
|
private void CloseAllHandles(Message message, MessageHeader header, KProcess process)
|
||||||
|
@ -1166,19 +1167,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return hasRequest;
|
return hasRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FinishRequest(KSessionRequest request, KernelResult result)
|
private void FinishRequest(KSessionRequest request, Result result)
|
||||||
{
|
{
|
||||||
KProcess clientProcess = request.ClientThread.Owner;
|
KProcess clientProcess = request.ClientThread.Owner;
|
||||||
KProcess serverProcess = request.ServerProcess;
|
KProcess serverProcess = request.ServerProcess;
|
||||||
|
|
||||||
KernelResult unmapResult = KernelResult.Success;
|
Result unmapResult = Result.Success;
|
||||||
|
|
||||||
if (serverProcess != null)
|
if (serverProcess != null)
|
||||||
{
|
{
|
||||||
unmapResult = request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager);
|
unmapResult = request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unmapResult == KernelResult.Success)
|
if (unmapResult == Result.Success)
|
||||||
{
|
{
|
||||||
request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager);
|
request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager);
|
||||||
}
|
}
|
||||||
|
@ -1186,7 +1187,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
WakeClientThread(request, result);
|
WakeClientThread(request, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WakeClientThread(KSessionRequest request, KernelResult result)
|
private void WakeClientThread(KSessionRequest request, Result result)
|
||||||
{
|
{
|
||||||
// Wait client thread waiting for a response for the given request.
|
// Wait client thread waiting for a response for the given request.
|
||||||
if (request.AsyncEvent != null)
|
if (request.AsyncEvent != null)
|
||||||
|
@ -1203,16 +1204,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendResultToAsyncRequestClient(KSessionRequest request, KernelResult result)
|
private void SendResultToAsyncRequestClient(KSessionRequest request, Result result)
|
||||||
{
|
{
|
||||||
KProcess clientProcess = request.ClientThread.Owner;
|
KProcess clientProcess = request.ClientThread.Owner;
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
ulong address = request.CustomCmdBuffAddr;
|
ulong address = request.CustomCmdBuffAddr;
|
||||||
|
|
||||||
clientProcess.CpuMemory.Write<ulong>(address, 0);
|
clientProcess.CpuMemory.Write<ulong>(address, 0);
|
||||||
clientProcess.CpuMemory.Write(address + 8, (int)result);
|
clientProcess.CpuMemory.Write(address + 8, result.ErrorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
clientProcess.MemoryManager.UnborrowIpcBuffer(request.CustomCmdBuffAddr, request.CustomCmdBuffSize);
|
clientProcess.MemoryManager.UnborrowIpcBuffer(request.CustomCmdBuffAddr, request.CustomCmdBuffSize);
|
||||||
|
@ -1220,7 +1221,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
request.AsyncEvent.Signal();
|
request.AsyncEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WakeServerThreads(KernelResult result)
|
private void WakeServerThreads(Result result)
|
||||||
{
|
{
|
||||||
// Wake all server threads waiting for requests.
|
// Wake all server threads waiting for requests.
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
@ -1233,7 +1234,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WakeAndSetResult(KThread thread, KernelResult result)
|
private void WakeAndSetResult(KThread thread, Result result)
|
||||||
{
|
{
|
||||||
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static KThread CurrentThread;
|
private static KThread CurrentThread;
|
||||||
|
|
||||||
public static KernelResult StartInitialProcess(
|
public static Result StartInitialProcess(
|
||||||
KernelContext context,
|
KernelContext context,
|
||||||
ProcessCreationInfo creationInfo,
|
ProcessCreationInfo creationInfo,
|
||||||
ReadOnlySpan<int> capabilities,
|
ReadOnlySpan<int> capabilities,
|
||||||
|
@ -24,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
KProcess process = new KProcess(context);
|
KProcess process = new KProcess(context);
|
||||||
|
|
||||||
KernelResult result = process.Initialize(
|
Result result = process.Initialize(
|
||||||
creationInfo,
|
creationInfo,
|
||||||
capabilities,
|
capabilities,
|
||||||
context.ResourceLimit,
|
context.ResourceLimit,
|
||||||
|
@ -32,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
null,
|
null,
|
||||||
customThreadStart);
|
customThreadStart);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
@ -21,13 +22,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_lock = new object();
|
_lock = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Initialize(ulong address, ulong size)
|
public Result Initialize(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
Owner = KernelStatic.GetCurrentProcess();
|
Owner = KernelStatic.GetCurrentProcess();
|
||||||
|
|
||||||
KernelResult result = Owner.MemoryManager.BorrowCodeMemory(_pageList, address, size);
|
Result result = Owner.MemoryManager.BorrowCodeMemory(_pageList, address, size);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -39,10 +40,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_isMapped = false;
|
_isMapped = false;
|
||||||
_isOwnerMapped = false;
|
_isOwnerMapped = false;
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Map(ulong address, ulong size, KMemoryPermission perm)
|
public Result Map(ulong address, ulong size, KMemoryPermission perm)
|
||||||
{
|
{
|
||||||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
|
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
|
||||||
{
|
{
|
||||||
|
@ -58,9 +59,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
KProcess process = KernelStatic.GetCurrentProcess();
|
KProcess process = KernelStatic.GetCurrentProcess();
|
||||||
|
|
||||||
KernelResult result = process.MemoryManager.MapPages(address, _pageList, MemoryState.CodeWritable, KMemoryPermission.ReadAndWrite);
|
Result result = process.MemoryManager.MapPages(address, _pageList, MemoryState.CodeWritable, KMemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -68,10 +69,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_isMapped = true;
|
_isMapped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapToOwner(ulong address, ulong size, KMemoryPermission permission)
|
public Result MapToOwner(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
|
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
|
||||||
{
|
{
|
||||||
|
@ -87,9 +88,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
Debug.Assert(permission == KMemoryPermission.Read || permission == KMemoryPermission.ReadAndExecute);
|
Debug.Assert(permission == KMemoryPermission.Read || permission == KMemoryPermission.ReadAndExecute);
|
||||||
|
|
||||||
KernelResult result = Owner.MemoryManager.MapPages(address, _pageList, MemoryState.CodeReadOnly, permission);
|
Result result = Owner.MemoryManager.MapPages(address, _pageList, MemoryState.CodeReadOnly, permission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -97,10 +98,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_isOwnerMapped = true;
|
_isOwnerMapped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Unmap(ulong address, ulong size)
|
public Result Unmap(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
|
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, (ulong)KPageTableBase.PageSize))
|
||||||
{
|
{
|
||||||
|
@ -111,9 +112,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
KProcess process = KernelStatic.GetCurrentProcess();
|
KProcess process = KernelStatic.GetCurrentProcess();
|
||||||
|
|
||||||
KernelResult result = process.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeWritable);
|
Result result = process.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeWritable);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -123,10 +124,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_isMapped = false;
|
_isMapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapFromOwner(ulong address, ulong size)
|
public Result UnmapFromOwner(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
|
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
|
||||||
{
|
{
|
||||||
|
@ -135,9 +136,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
KernelResult result = Owner.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeReadOnly);
|
Result result = Owner.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeReadOnly);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_isOwnerMapped = false;
|
_isOwnerMapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Destroy()
|
protected override void Destroy()
|
||||||
|
@ -156,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
ulong size = _pageList.GetPagesCount() * KPageTableBase.PageSize;
|
ulong size = _pageList.GetPagesCount() * KPageTableBase.PageSize;
|
||||||
|
|
||||||
if (Owner.MemoryManager.UnborrowCodeMemory(_address, size, _pageList) != KernelResult.Success)
|
if (Owner.MemoryManager.UnborrowCodeMemory(_address, size, _pageList) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Unexpected failure restoring transfer memory attributes.");
|
throw new InvalidOperationException("Unexpected failure restoring transfer memory attributes.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using Ryujinx.Common.Collections;
|
using Ryujinx.Common.Collections;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockTree = new IntrusiveRedBlackTree<KMemoryBlock>();
|
_blockTree = new IntrusiveRedBlackTree<KMemoryBlock>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Initialize(ulong addrSpaceStart, ulong addrSpaceEnd, KMemoryBlockSlabManager slabManager)
|
public Result Initialize(ulong addrSpaceStart, ulong addrSpaceEnd, KMemoryBlockSlabManager slabManager)
|
||||||
{
|
{
|
||||||
_slabManager = slabManager;
|
_slabManager = slabManager;
|
||||||
_addrSpaceStart = addrSpaceStart;
|
_addrSpaceStart = addrSpaceStart;
|
||||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
KMemoryPermission.None,
|
KMemoryPermission.None,
|
||||||
MemoryAttribute.None));
|
MemoryAttribute.None));
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InsertBlock(
|
public void InsertBlock(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
@ -25,20 +25,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_pageHeap.UpdateUsedSize();
|
_pageHeap.UpdateUsedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult AllocatePages(out KPageList pageList, ulong pagesCount)
|
public Result AllocatePages(out KPageList pageList, ulong pagesCount)
|
||||||
{
|
{
|
||||||
if (pagesCount == 0)
|
if (pagesCount == 0)
|
||||||
{
|
{
|
||||||
pageList = new KPageList();
|
pageList = new KPageList();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (_pageHeap)
|
lock (_pageHeap)
|
||||||
{
|
{
|
||||||
KernelResult result = AllocatePagesImpl(out pageList, pagesCount, false);
|
Result result = AllocatePagesImpl(out pageList, pagesCount, false);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
foreach (var node in pageList)
|
foreach (var node in pageList)
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random)
|
private Result AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random)
|
||||||
{
|
{
|
||||||
pageList = new KPageList();
|
pageList = new KPageList();
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = pageList.AddRange(allocatedBlock, pagesPerAlloc);
|
Result result = pageList.AddRange(allocatedBlock, pagesPerAlloc);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
FreePages(pageList);
|
FreePages(pageList);
|
||||||
_pageHeap.Free(allocatedBlock, pagesPerAlloc);
|
_pageHeap.Free(allocatedBlock, pagesPerAlloc);
|
||||||
|
@ -116,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.OutOfMemory;
|
return KernelResult.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong AllocatePagesContiguousImpl(ulong pagesCount, ulong alignPages, bool random)
|
private ulong AllocatePagesContiguousImpl(ulong pagesCount, ulong alignPages, bool random)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
Nodes = new LinkedList<KPageNode>();
|
Nodes = new LinkedList<KPageNode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult AddRange(ulong address, ulong pagesCount)
|
public Result AddRange(ulong address, ulong pagesCount)
|
||||||
{
|
{
|
||||||
if (pagesCount != 0)
|
if (pagesCount != 0)
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
Nodes.AddLast(new KPageNode(address, pagesCount));
|
Nodes.AddLast(new KPageNode(address, pagesCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetPagesCount()
|
public ulong GetPagesCount()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -31,31 +31,31 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult MapMemory(ulong src, ulong dst, ulong pagesCount, KMemoryPermission oldSrcPermission, KMemoryPermission newDstPermission)
|
protected override Result MapMemory(ulong src, ulong dst, ulong pagesCount, KMemoryPermission oldSrcPermission, KMemoryPermission newDstPermission)
|
||||||
{
|
{
|
||||||
KPageList pageList = new KPageList();
|
KPageList pageList = new KPageList();
|
||||||
GetPhysicalRegions(src, pagesCount * PageSize, pageList);
|
GetPhysicalRegions(src, pagesCount * PageSize, pageList);
|
||||||
|
|
||||||
KernelResult result = Reprotect(src, pagesCount, KMemoryPermission.None);
|
Result result = Reprotect(src, pagesCount, KMemoryPermission.None);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = MapPages(dst, pageList, newDstPermission, false, 0);
|
result = MapPages(dst, pageList, newDstPermission, false, 0);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
KernelResult reprotectResult = Reprotect(src, pagesCount, oldSrcPermission);
|
Result reprotectResult = Reprotect(src, pagesCount, oldSrcPermission);
|
||||||
Debug.Assert(reprotectResult == KernelResult.Success);
|
Debug.Assert(reprotectResult == Result.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult UnmapMemory(ulong dst, ulong src, ulong pagesCount, KMemoryPermission oldDstPermission, KMemoryPermission newSrcPermission)
|
protected override Result UnmapMemory(ulong dst, ulong src, ulong pagesCount, KMemoryPermission oldDstPermission, KMemoryPermission newSrcPermission)
|
||||||
{
|
{
|
||||||
ulong size = pagesCount * PageSize;
|
ulong size = pagesCount * PageSize;
|
||||||
|
|
||||||
|
@ -70,26 +70,26 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.InvalidMemRange;
|
return KernelResult.InvalidMemRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = Unmap(dst, pagesCount);
|
Result result = Unmap(dst, pagesCount);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Reprotect(src, pagesCount, newSrcPermission);
|
result = Reprotect(src, pagesCount, newSrcPermission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
KernelResult mapResult = MapPages(dst, dstPageList, oldDstPermission, false, 0);
|
Result mapResult = MapPages(dst, dstPageList, oldDstPermission, false, 0);
|
||||||
Debug.Assert(mapResult == KernelResult.Success);
|
Debug.Assert(mapResult == Result.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
|
protected override Result MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
|
||||||
{
|
{
|
||||||
ulong size = pagesCount * PageSize;
|
ulong size = pagesCount * PageSize;
|
||||||
|
|
||||||
|
@ -107,11 +107,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_cpuMemory.Fill(dstVa, size, fillValue);
|
_cpuMemory.Fill(dstVa, size, fillValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
|
protected override Result MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
|
||||||
{
|
{
|
||||||
using var scopedPageList = new KScopedPageList(Context.MemoryManager, pageList);
|
using var scopedPageList = new KScopedPageList(Context.MemoryManager, pageList);
|
||||||
|
|
||||||
|
@ -136,11 +136,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
scopedPageList.SignalSuccess();
|
scopedPageList.SignalSuccess();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult Unmap(ulong address, ulong pagesCount)
|
protected override Result Unmap(ulong address, ulong pagesCount)
|
||||||
{
|
{
|
||||||
KPageList pagesToClose = new KPageList();
|
KPageList pagesToClose = new KPageList();
|
||||||
|
|
||||||
|
@ -159,21 +159,21 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
pagesToClose.DecrementPagesReferenceCount(Context.MemoryManager);
|
pagesToClose.DecrementPagesReferenceCount(Context.MemoryManager);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult Reprotect(ulong address, ulong pagesCount, KMemoryPermission permission)
|
protected override Result Reprotect(ulong address, ulong pagesCount, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
// TODO.
|
// TODO.
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override KernelResult ReprotectWithAttributes(ulong address, ulong pagesCount, KMemoryPermission permission)
|
protected override Result ReprotectWithAttributes(ulong address, ulong pagesCount, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
// TODO.
|
// TODO.
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -88,7 +89,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 };
|
private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 };
|
||||||
|
|
||||||
public KernelResult InitializeForProcess(
|
public Result InitializeForProcess(
|
||||||
AddressSpaceType addrSpaceType,
|
AddressSpaceType addrSpaceType,
|
||||||
bool aslrEnabled,
|
bool aslrEnabled,
|
||||||
bool aslrDisabled,
|
bool aslrDisabled,
|
||||||
|
@ -107,7 +108,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
ulong addrSpaceBase = 0;
|
ulong addrSpaceBase = 0;
|
||||||
ulong addrSpaceSize = 1UL << AddrSpaceSizes[(int)addrSpaceType];
|
ulong addrSpaceSize = 1UL << AddrSpaceSizes[(int)addrSpaceType];
|
||||||
|
|
||||||
KernelResult result = CreateUserAddressSpace(
|
Result result = CreateUserAddressSpace(
|
||||||
addrSpaceType,
|
addrSpaceType,
|
||||||
aslrEnabled,
|
aslrEnabled,
|
||||||
aslrDisabled,
|
aslrDisabled,
|
||||||
|
@ -118,7 +119,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
size,
|
size,
|
||||||
slabManager);
|
slabManager);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Context.ContextIdManager.PutId(_contextId);
|
Context.ContextIdManager.PutId(_contextId);
|
||||||
}
|
}
|
||||||
|
@ -134,7 +135,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
public ulong AslrOffset;
|
public ulong AslrOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult CreateUserAddressSpace(
|
private Result CreateUserAddressSpace(
|
||||||
AddressSpaceType addrSpaceType,
|
AddressSpaceType addrSpaceType,
|
||||||
bool aslrEnabled,
|
bool aslrEnabled,
|
||||||
bool aslrDisabled,
|
bool aslrDisabled,
|
||||||
|
@ -342,7 +343,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapPages(ulong address, KPageList pageList, MemoryState state, KMemoryPermission permission)
|
public Result MapPages(ulong address, KPageList pageList, MemoryState state, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
ulong pagesCount = pageList.GetPagesCount();
|
ulong pagesCount = pageList.GetPagesCount();
|
||||||
|
|
||||||
|
@ -365,9 +366,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.OutOfResource;
|
return KernelResult.OutOfResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = MapPages(address, pageList, permission);
|
Result result = MapPages(address, pageList, permission);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_blockManager.InsertBlock(address, pagesCount, state, permission);
|
_blockManager.InsertBlock(address, pagesCount, state, permission);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +377,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapPages(ulong address, KPageList pageList, MemoryState stateExpected)
|
public Result UnmapPages(ulong address, KPageList pageList, MemoryState stateExpected)
|
||||||
{
|
{
|
||||||
ulong pagesCount = pageList.GetPagesCount();
|
ulong pagesCount = pageList.GetPagesCount();
|
||||||
ulong size = pagesCount * PageSize;
|
ulong size = pagesCount * PageSize;
|
||||||
|
@ -430,9 +431,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.OutOfResource;
|
return KernelResult.OutOfResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = Unmap(address, pagesCount);
|
Result result = Unmap(address, pagesCount);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_blockManager.InsertBlock(address, pagesCount, MemoryState.Unmapped);
|
_blockManager.InsertBlock(address, pagesCount, MemoryState.Unmapped);
|
||||||
}
|
}
|
||||||
|
@ -446,19 +447,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapNormalMemory(long address, long size, KMemoryPermission permission)
|
public Result MapNormalMemory(long address, long size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
// TODO.
|
// TODO.
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapIoMemory(long address, long size, KMemoryPermission permission)
|
public Result MapIoMemory(long address, long size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
// TODO.
|
// TODO.
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapPages(
|
public Result MapPages(
|
||||||
ulong pagesCount,
|
ulong pagesCount,
|
||||||
int alignment,
|
int alignment,
|
||||||
ulong srcPa,
|
ulong srcPa,
|
||||||
|
@ -497,7 +498,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.OutOfResource;
|
return KernelResult.OutOfResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
if (paIsValid)
|
if (paIsValid)
|
||||||
{
|
{
|
||||||
|
@ -508,7 +509,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
result = AllocateAndMapPages(address, pagesCount, permission);
|
result = AllocateAndMapPages(address, pagesCount, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -516,10 +517,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockManager.InsertBlock(address, pagesCount, state, permission);
|
_blockManager.InsertBlock(address, pagesCount, state, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapPages(ulong address, ulong pagesCount, MemoryState state, KMemoryPermission permission)
|
public Result MapPages(ulong address, ulong pagesCount, MemoryState state, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
ulong size = pagesCount * PageSize;
|
ulong size = pagesCount * PageSize;
|
||||||
|
|
||||||
|
@ -540,9 +541,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.OutOfResource;
|
return KernelResult.OutOfResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = AllocateAndMapPages(address, pagesCount, permission);
|
Result result = AllocateAndMapPages(address, pagesCount, permission);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_blockManager.InsertBlock(address, pagesCount, state, permission);
|
_blockManager.InsertBlock(address, pagesCount, state, permission);
|
||||||
}
|
}
|
||||||
|
@ -551,13 +552,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult AllocateAndMapPages(ulong address, ulong pagesCount, KMemoryPermission permission)
|
private Result AllocateAndMapPages(ulong address, ulong pagesCount, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
KMemoryRegionManager region = GetMemoryRegionManager();
|
KMemoryRegionManager region = GetMemoryRegionManager();
|
||||||
|
|
||||||
KernelResult result = region.AllocatePages(out KPageList pageList, pagesCount);
|
Result result = region.AllocatePages(out KPageList pageList, pagesCount);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -567,7 +568,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return MapPages(address, pageList, permission);
|
return MapPages(address, pageList, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapProcessCodeMemory(ulong dst, ulong src, ulong size)
|
public Result MapProcessCodeMemory(ulong dst, ulong src, ulong size)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
|
@ -596,12 +597,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result = MapMemory(src, dst, pagesCount, permission, KMemoryPermission.None);
|
Result result = MapMemory(src, dst, pagesCount, permission, KMemoryPermission.None);
|
||||||
|
|
||||||
_blockManager.InsertBlock(src, pagesCount, state, KMemoryPermission.None, MemoryAttribute.Borrowed);
|
_blockManager.InsertBlock(src, pagesCount, state, KMemoryPermission.None, MemoryAttribute.Borrowed);
|
||||||
_blockManager.InsertBlock(dst, pagesCount, MemoryState.ModCodeStatic);
|
_blockManager.InsertBlock(dst, pagesCount, MemoryState.ModCodeStatic);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -610,7 +611,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapProcessCodeMemory(ulong dst, ulong src, ulong size)
|
public Result UnmapProcessCodeMemory(ulong dst, ulong src, ulong size)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
|
@ -656,9 +657,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result = Unmap(dst, pagesCount);
|
Result result = Unmap(dst, pagesCount);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +674,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped);
|
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped);
|
||||||
_blockManager.InsertBlock(src, pagesCount, MemoryState.Heap, KMemoryPermission.ReadAndWrite);
|
_blockManager.InsertBlock(src, pagesCount, MemoryState.Heap, KMemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -682,7 +683,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetHeapSize(ulong size, out ulong address)
|
public Result SetHeapSize(ulong size, out ulong address)
|
||||||
{
|
{
|
||||||
address = 0;
|
address = 0;
|
||||||
|
|
||||||
|
@ -712,7 +713,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
KMemoryRegionManager region = GetMemoryRegionManager();
|
KMemoryRegionManager region = GetMemoryRegionManager();
|
||||||
|
|
||||||
KernelResult result = region.AllocatePages(out KPageList pageList, pagesCount);
|
Result result = region.AllocatePages(out KPageList pageList, pagesCount);
|
||||||
|
|
||||||
using var _ = new OnScopeExit(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager));
|
using var _ = new OnScopeExit(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager));
|
||||||
|
|
||||||
|
@ -724,7 +725,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -747,7 +748,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
result = MapPages(_currentHeapAddr, pageList, KMemoryPermission.ReadAndWrite, true, (byte)_heapFillValue);
|
result = MapPages(_currentHeapAddr, pageList, KMemoryPermission.ReadAndWrite, true, (byte)_heapFillValue);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -786,9 +787,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = sizeDelta / PageSize;
|
ulong pagesCount = sizeDelta / PageSize;
|
||||||
|
|
||||||
KernelResult result = Unmap(freeAddr, pagesCount);
|
Result result = Unmap(freeAddr, pagesCount);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -803,10 +804,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
address = HeapRegionStart;
|
address = HeapRegionStart;
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
public Result SetMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
|
@ -833,9 +834,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result = Reprotect(address, pagesCount, permission);
|
Result result = Reprotect(address, pagesCount, permission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -843,7 +844,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockManager.InsertBlock(address, pagesCount, oldState, permission);
|
_blockManager.InsertBlock(address, pagesCount, oldState, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -865,17 +866,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return _currentHeapAddr - HeapRegionStart;
|
return _currentHeapAddr - HeapRegionStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetHeapCapacity(ulong capacity)
|
public Result SetHeapCapacity(ulong capacity)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
_heapCapacity = capacity;
|
_heapCapacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetMemoryAttribute(
|
public Result SetMemoryAttribute(
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
MemoryAttribute attributeMask,
|
MemoryAttribute attributeMask,
|
||||||
|
@ -909,7 +910,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
_blockManager.InsertBlock(address, pagesCount, state, permission, attribute);
|
_blockManager.InsertBlock(address, pagesCount, state, permission, attribute);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -942,7 +943,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Map(ulong dst, ulong src, ulong size)
|
public Result Map(ulong dst, ulong src, ulong size)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
|
@ -973,9 +974,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result = MapMemory(src, dst, pagesCount, KMemoryPermission.ReadAndWrite, KMemoryPermission.ReadAndWrite);
|
Result result = MapMemory(src, dst, pagesCount, KMemoryPermission.ReadAndWrite, KMemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -983,7 +984,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockManager.InsertBlock(src, pagesCount, srcState, KMemoryPermission.None, MemoryAttribute.Borrowed);
|
_blockManager.InsertBlock(src, pagesCount, srcState, KMemoryPermission.None, MemoryAttribute.Borrowed);
|
||||||
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Stack, KMemoryPermission.ReadAndWrite);
|
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Stack, KMemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -992,7 +993,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapForKernel(ulong address, ulong pagesCount, MemoryState stateExpected)
|
public Result UnmapForKernel(ulong address, ulong pagesCount, MemoryState stateExpected)
|
||||||
{
|
{
|
||||||
ulong size = pagesCount * PageSize;
|
ulong size = pagesCount * PageSize;
|
||||||
|
|
||||||
|
@ -1017,14 +1018,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return KernelResult.OutOfResource;
|
return KernelResult.OutOfResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = Unmap(address, pagesCount);
|
Result result = Unmap(address, pagesCount);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_blockManager.InsertBlock(address, pagesCount, MemoryState.Unmapped);
|
_blockManager.InsertBlock(address, pagesCount, MemoryState.Unmapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1033,7 +1034,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Unmap(ulong dst, ulong src, ulong size)
|
public Result Unmap(ulong dst, ulong src, ulong size)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
|
@ -1076,9 +1077,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result = UnmapMemory(dst, src, pagesCount, dstPermission, KMemoryPermission.ReadAndWrite);
|
Result result = UnmapMemory(dst, src, pagesCount, dstPermission, KMemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1086,7 +1087,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockManager.InsertBlock(src, pagesCount, srcState, KMemoryPermission.ReadAndWrite);
|
_blockManager.InsertBlock(src, pagesCount, srcState, KMemoryPermission.ReadAndWrite);
|
||||||
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped);
|
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1095,7 +1096,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapProcessMemory(ulong dst, ulong size, KPageTableBase srcPageTable, ulong src)
|
public Result UnmapProcessMemory(ulong dst, ulong size, KPageTableBase srcPageTable, ulong src)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
|
@ -1153,20 +1154,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result = Unmap(dst, pagesCount);
|
Result result = Unmap(dst, pagesCount);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped);
|
_blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
public Result SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
|
@ -1213,7 +1214,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
if ((oldPermission & KMemoryPermission.Execute) != 0)
|
if ((oldPermission & KMemoryPermission.Execute) != 0)
|
||||||
{
|
{
|
||||||
|
@ -1224,7 +1225,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
result = Reprotect(address, pagesCount, permission);
|
result = Reprotect(address, pagesCount, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1233,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_blockManager.InsertBlock(address, pagesCount, newState, permission);
|
_blockManager.InsertBlock(address, pagesCount, newState, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1241,7 +1242,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapPhysicalMemory(ulong address, ulong size)
|
public Result MapPhysicalMemory(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
ulong endAddr = address + size;
|
ulong endAddr = address + size;
|
||||||
|
|
||||||
|
@ -1259,7 +1260,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (mappedSize == size)
|
if (mappedSize == size)
|
||||||
{
|
{
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong remainingSize = size - mappedSize;
|
ulong remainingSize = size - mappedSize;
|
||||||
|
@ -1276,7 +1277,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
KMemoryRegionManager region = GetMemoryRegionManager();
|
KMemoryRegionManager region = GetMemoryRegionManager();
|
||||||
|
|
||||||
KernelResult result = region.AllocatePages(out KPageList pageList, remainingPages);
|
Result result = region.AllocatePages(out KPageList pageList, remainingPages);
|
||||||
|
|
||||||
using var _ = new OnScopeExit(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager));
|
using var _ = new OnScopeExit(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager));
|
||||||
|
|
||||||
|
@ -1285,7 +1286,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
currentProcess.ResourceLimit?.Release(LimitableResource.Memory, remainingSize);
|
currentProcess.ResourceLimit?.Release(LimitableResource.Memory, remainingSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -1357,10 +1358,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
MemoryAttribute.None);
|
MemoryAttribute.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapPhysicalMemory(ulong address, ulong size)
|
public Result UnmapPhysicalMemory(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
ulong endAddr = address + size;
|
ulong endAddr = address + size;
|
||||||
|
|
||||||
|
@ -1391,7 +1392,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (heapMappedSize == 0)
|
if (heapMappedSize == 0)
|
||||||
{
|
{
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_slabManager.CanAllocate(MaxBlocksNeededForInsertion))
|
if (!_slabManager.CanAllocate(MaxBlocksNeededForInsertion))
|
||||||
|
@ -1400,7 +1401,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to unmap all the heap mapped memory inside range.
|
// Try to unmap all the heap mapped memory inside range.
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
foreach (KMemoryInfo info in IterateOverRange(address, endAddr))
|
foreach (KMemoryInfo info in IterateOverRange(address, endAddr))
|
||||||
{
|
{
|
||||||
|
@ -1416,11 +1417,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
// The kernel would attempt to remap if this fails, but we don't because:
|
// The kernel would attempt to remap if this fails, but we don't because:
|
||||||
// - The implementation may not support remapping if memory aliasing is not supported on the platform.
|
// - The implementation may not support remapping if memory aliasing is not supported on the platform.
|
||||||
// - Unmap can't ever fail here anyway.
|
// - Unmap can't ever fail here anyway.
|
||||||
Debug.Assert(result == KernelResult.Success);
|
Debug.Assert(result == Result.Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
PhysicalMemoryUsage -= heapMappedSize;
|
PhysicalMemoryUsage -= heapMappedSize;
|
||||||
|
|
||||||
|
@ -1437,7 +1438,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult CopyDataToCurrentProcess(
|
public Result CopyDataToCurrentProcess(
|
||||||
ulong dst,
|
ulong dst,
|
||||||
ulong size,
|
ulong size,
|
||||||
ulong src,
|
ulong src,
|
||||||
|
@ -1460,7 +1461,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
toServer: true);
|
toServer: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult CopyDataFromCurrentProcess(
|
public Result CopyDataFromCurrentProcess(
|
||||||
ulong dst,
|
ulong dst,
|
||||||
ulong size,
|
ulong size,
|
||||||
MemoryState stateMask,
|
MemoryState stateMask,
|
||||||
|
@ -1483,7 +1484,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
toServer: false);
|
toServer: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult CopyDataFromOrToCurrentProcess(
|
private Result CopyDataFromOrToCurrentProcess(
|
||||||
ulong size,
|
ulong size,
|
||||||
ulong clientAddress,
|
ulong clientAddress,
|
||||||
ulong serverAddress,
|
ulong serverAddress,
|
||||||
|
@ -1543,7 +1544,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
size -= copySize;
|
size -= copySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1552,7 +1553,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapBufferFromClientProcess(
|
public Result MapBufferFromClientProcess(
|
||||||
ulong size,
|
ulong size,
|
||||||
ulong src,
|
ulong src,
|
||||||
KPageTableBase srcPageTable,
|
KPageTableBase srcPageTable,
|
||||||
|
@ -1567,14 +1568,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
KernelResult result = srcPageTable.ReprotectClientProcess(
|
Result result = srcPageTable.ReprotectClientProcess(
|
||||||
src,
|
src,
|
||||||
size,
|
size,
|
||||||
permission,
|
permission,
|
||||||
state,
|
state,
|
||||||
out int blocksNeeded);
|
out int blocksNeeded);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1590,7 +1591,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
result = MapPagesFromClientProcess(size, src, permission, state, srcPageTable, send, out ulong va);
|
result = MapPagesFromClientProcess(size, src, permission, state, srcPageTable, send, out ulong va);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
if (srcMapEndAddr > srcMapAddress)
|
if (srcMapEndAddr > srcMapAddress)
|
||||||
{
|
{
|
||||||
|
@ -1613,10 +1614,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult ReprotectClientProcess(
|
private Result ReprotectClientProcess(
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
KMemoryPermission permission,
|
KMemoryPermission permission,
|
||||||
|
@ -1689,8 +1690,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong blockPagesCount = blockSize / PageSize;
|
ulong blockPagesCount = blockSize / PageSize;
|
||||||
|
|
||||||
KernelResult reprotectResult = Reprotect(blockAddress, blockPagesCount, info.Permission);
|
Result reprotectResult = Reprotect(blockAddress, blockPagesCount, info.Permission);
|
||||||
Debug.Assert(reprotectResult == KernelResult.Success);
|
Debug.Assert(reprotectResult == Result.Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1699,7 +1700,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
SignalMemoryTracking(addressTruncated, endAddrRounded - addressTruncated, false);
|
SignalMemoryTracking(addressTruncated, endAddrRounded - addressTruncated, false);
|
||||||
|
|
||||||
// Reprotect the aligned pages range on the client to make them inaccessible from the client process.
|
// Reprotect the aligned pages range on the client to make them inaccessible from the client process.
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
if (addressRounded < endAddrTruncated)
|
if (addressRounded < endAddrTruncated)
|
||||||
{
|
{
|
||||||
|
@ -1736,7 +1737,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
result = Reprotect(blockAddress, blockPagesCount, permissionMask);
|
result = Reprotect(blockAddress, blockPagesCount, permissionMask);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -1748,10 +1749,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult MapPagesFromClientProcess(
|
private Result MapPagesFromClientProcess(
|
||||||
ulong size,
|
ulong size,
|
||||||
ulong address,
|
ulong address,
|
||||||
KMemoryPermission permission,
|
KMemoryPermission permission,
|
||||||
|
@ -1877,9 +1878,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
Context.Memory.Fill(GetDramAddressFromPa(firstPageFillAddress), unusedSizeAfter, (byte)_ipcFillValue);
|
Context.Memory.Fill(GetDramAddressFromPa(firstPageFillAddress), unusedSizeAfter, (byte)_ipcFillValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = MapPages(currentVa, 1, dstFirstPagePa, permission);
|
Result result = MapPages(currentVa, 1, dstFirstPagePa, permission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -1896,9 +1897,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
KPageList pageList = new KPageList();
|
KPageList pageList = new KPageList();
|
||||||
srcPageTable.GetPhysicalRegions(addressRounded, alignedSize, pageList);
|
srcPageTable.GetPhysicalRegions(addressRounded, alignedSize, pageList);
|
||||||
|
|
||||||
KernelResult result = MapPages(currentVa, pageList, permission);
|
Result result = MapPages(currentVa, pageList, permission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -1931,9 +1932,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
Context.Memory.Fill(GetDramAddressFromPa(lastPageFillAddr), unusedSizeAfter, (byte)_ipcFillValue);
|
Context.Memory.Fill(GetDramAddressFromPa(lastPageFillAddr), unusedSizeAfter, (byte)_ipcFillValue);
|
||||||
|
|
||||||
KernelResult result = MapPages(currentVa, 1, dstLastPagePa, permission);
|
Result result = MapPages(currentVa, 1, dstLastPagePa, permission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -1945,10 +1946,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
dst = va + (address - addressTruncated);
|
dst = va + (address - addressTruncated);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapNoAttributeIfStateEquals(ulong address, ulong size, MemoryState state)
|
public Result UnmapNoAttributeIfStateEquals(ulong address, ulong size, MemoryState state)
|
||||||
{
|
{
|
||||||
if (AddrSpaceStart > address)
|
if (AddrSpaceStart > address)
|
||||||
{
|
{
|
||||||
|
@ -1990,9 +1991,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong pagesCount = (endAddrRounded - addressTruncated) / PageSize;
|
ulong pagesCount = (endAddrRounded - addressTruncated) / PageSize;
|
||||||
|
|
||||||
KernelResult result = Unmap(addressTruncated, pagesCount);
|
Result result = Unmap(addressTruncated, pagesCount);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_blockManager.InsertBlock(addressTruncated, pagesCount, MemoryState.Unmapped);
|
_blockManager.InsertBlock(addressTruncated, pagesCount, MemoryState.Unmapped);
|
||||||
}
|
}
|
||||||
|
@ -2006,7 +2007,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapIpcRestorePermission(ulong address, ulong size, MemoryState state)
|
public Result UnmapIpcRestorePermission(ulong address, ulong size, MemoryState state)
|
||||||
{
|
{
|
||||||
ulong endAddr = address + size;
|
ulong endAddr = address + size;
|
||||||
|
|
||||||
|
@ -2019,7 +2020,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (pagesCount == 0)
|
if (pagesCount == 0)
|
||||||
{
|
{
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryState stateMask;
|
MemoryState stateMask;
|
||||||
|
@ -2069,9 +2070,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
ulong blockPagesCount = blockSize / PageSize;
|
ulong blockPagesCount = blockSize / PageSize;
|
||||||
|
|
||||||
KernelResult result = Reprotect(blockAddress, blockPagesCount, info.SourcePermission);
|
Result result = Reprotect(blockAddress, blockPagesCount, info.SourcePermission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2080,7 +2081,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
_blockManager.InsertBlock(addressRounded, pagesCount, RestoreIpcMappingPermissions);
|
_blockManager.InsertBlock(addressRounded, pagesCount, RestoreIpcMappingPermissions);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2094,7 +2095,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
block.RestoreIpcMappingPermission();
|
block.RestoreIpcMappingPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult GetPagesIfStateEquals(
|
public Result GetPagesIfStateEquals(
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
MemoryState stateMask,
|
MemoryState stateMask,
|
||||||
|
@ -2128,7 +2129,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
GetPhysicalRegions(address, size, pageList);
|
GetPhysicalRegions(address, size, pageList);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2137,7 +2138,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult BorrowIpcBuffer(ulong address, ulong size)
|
public Result BorrowIpcBuffer(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
return SetAttributesAndChangePermission(
|
return SetAttributesAndChangePermission(
|
||||||
address,
|
address,
|
||||||
|
@ -2152,7 +2153,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
MemoryAttribute.Borrowed);
|
MemoryAttribute.Borrowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult BorrowTransferMemory(KPageList pageList, ulong address, ulong size, KMemoryPermission permission)
|
public Result BorrowTransferMemory(KPageList pageList, ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
return SetAttributesAndChangePermission(
|
return SetAttributesAndChangePermission(
|
||||||
address,
|
address,
|
||||||
|
@ -2168,7 +2169,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
pageList);
|
pageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult BorrowCodeMemory(KPageList pageList, ulong address, ulong size)
|
public Result BorrowCodeMemory(KPageList pageList, ulong address, ulong size)
|
||||||
{
|
{
|
||||||
return SetAttributesAndChangePermission(
|
return SetAttributesAndChangePermission(
|
||||||
address,
|
address,
|
||||||
|
@ -2184,7 +2185,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
pageList);
|
pageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult SetAttributesAndChangePermission(
|
private Result SetAttributesAndChangePermission(
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
MemoryState stateMask,
|
MemoryState stateMask,
|
||||||
|
@ -2237,9 +2238,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (newPermission != oldPermission)
|
if (newPermission != oldPermission)
|
||||||
{
|
{
|
||||||
KernelResult result = Reprotect(address, pagesCount, newPermission);
|
Result result = Reprotect(address, pagesCount, newPermission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2249,7 +2250,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
_blockManager.InsertBlock(address, pagesCount, oldState, newPermission, newAttribute);
|
_blockManager.InsertBlock(address, pagesCount, oldState, newPermission, newAttribute);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2258,7 +2259,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnborrowIpcBuffer(ulong address, ulong size)
|
public Result UnborrowIpcBuffer(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
return ClearAttributesAndChangePermission(
|
return ClearAttributesAndChangePermission(
|
||||||
address,
|
address,
|
||||||
|
@ -2273,7 +2274,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
MemoryAttribute.Borrowed);
|
MemoryAttribute.Borrowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnborrowTransferMemory(ulong address, ulong size, KPageList pageList)
|
public Result UnborrowTransferMemory(ulong address, ulong size, KPageList pageList)
|
||||||
{
|
{
|
||||||
return ClearAttributesAndChangePermission(
|
return ClearAttributesAndChangePermission(
|
||||||
address,
|
address,
|
||||||
|
@ -2289,7 +2290,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
pageList);
|
pageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnborrowCodeMemory(ulong address, ulong size, KPageList pageList)
|
public Result UnborrowCodeMemory(ulong address, ulong size, KPageList pageList)
|
||||||
{
|
{
|
||||||
return ClearAttributesAndChangePermission(
|
return ClearAttributesAndChangePermission(
|
||||||
address,
|
address,
|
||||||
|
@ -2305,7 +2306,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
pageList);
|
pageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult ClearAttributesAndChangePermission(
|
private Result ClearAttributesAndChangePermission(
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
MemoryState stateMask,
|
MemoryState stateMask,
|
||||||
|
@ -2365,9 +2366,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (newPermission != oldPermission)
|
if (newPermission != oldPermission)
|
||||||
{
|
{
|
||||||
KernelResult result = Reprotect(address, pagesCount, newPermission);
|
Result result = Reprotect(address, pagesCount, newPermission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2377,7 +2378,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
_blockManager.InsertBlock(address, pagesCount, oldState, newPermission, newAttribute);
|
_blockManager.InsertBlock(address, pagesCount, oldState, newPermission, newAttribute);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2915,7 +2916,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="oldSrcPermission">Current protection of the source memory region</param>
|
/// <param name="oldSrcPermission">Current protection of the source memory region</param>
|
||||||
/// <param name="newDstPermission">Desired protection for the destination memory region</param>
|
/// <param name="newDstPermission">Desired protection for the destination memory region</param>
|
||||||
/// <returns>Result of the mapping operation</returns>
|
/// <returns>Result of the mapping operation</returns>
|
||||||
protected abstract KernelResult MapMemory(ulong src, ulong dst, ulong pagesCount, KMemoryPermission oldSrcPermission, KMemoryPermission newDstPermission);
|
protected abstract Result MapMemory(ulong src, ulong dst, ulong pagesCount, KMemoryPermission oldSrcPermission, KMemoryPermission newDstPermission);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unmaps a region of memory that was previously mapped with <see cref="MapMemory"/>.
|
/// Unmaps a region of memory that was previously mapped with <see cref="MapMemory"/>.
|
||||||
|
@ -2926,7 +2927,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="oldDstPermission">Current protection of the destination memory region</param>
|
/// <param name="oldDstPermission">Current protection of the destination memory region</param>
|
||||||
/// <param name="newSrcPermission">Desired protection of the source memory region</param>
|
/// <param name="newSrcPermission">Desired protection of the source memory region</param>
|
||||||
/// <returns>Result of the unmapping operation</returns>
|
/// <returns>Result of the unmapping operation</returns>
|
||||||
protected abstract KernelResult UnmapMemory(ulong dst, ulong src, ulong pagesCount, KMemoryPermission oldDstPermission, KMemoryPermission newSrcPermission);
|
protected abstract Result UnmapMemory(ulong dst, ulong src, ulong pagesCount, KMemoryPermission oldDstPermission, KMemoryPermission newSrcPermission);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps a region of memory into the specified physical memory region.
|
/// Maps a region of memory into the specified physical memory region.
|
||||||
|
@ -2938,7 +2939,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="shouldFillPages">Indicate if the pages should be filled with the <paramref name="fillValue"/> value</param>
|
/// <param name="shouldFillPages">Indicate if the pages should be filled with the <paramref name="fillValue"/> value</param>
|
||||||
/// <param name="fillValue">The value used to fill pages when <paramref name="shouldFillPages"/> is set to true</param>
|
/// <param name="fillValue">The value used to fill pages when <paramref name="shouldFillPages"/> is set to true</param>
|
||||||
/// <returns>Result of the mapping operation</returns>
|
/// <returns>Result of the mapping operation</returns>
|
||||||
protected abstract KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages = false, byte fillValue = 0);
|
protected abstract Result MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages = false, byte fillValue = 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps a region of memory into the specified physical memory region.
|
/// Maps a region of memory into the specified physical memory region.
|
||||||
|
@ -2949,7 +2950,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="shouldFillPages">Indicate if the pages should be filled with the <paramref name="fillValue"/> value</param>
|
/// <param name="shouldFillPages">Indicate if the pages should be filled with the <paramref name="fillValue"/> value</param>
|
||||||
/// <param name="fillValue">The value used to fill pages when <paramref name="shouldFillPages"/> is set to true</param>
|
/// <param name="fillValue">The value used to fill pages when <paramref name="shouldFillPages"/> is set to true</param>
|
||||||
/// <returns>Result of the mapping operation</returns>
|
/// <returns>Result of the mapping operation</returns>
|
||||||
protected abstract KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages = false, byte fillValue = 0);
|
protected abstract Result MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages = false, byte fillValue = 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unmaps a region of memory that was previously mapped with one of the page mapping methods.
|
/// Unmaps a region of memory that was previously mapped with one of the page mapping methods.
|
||||||
|
@ -2957,7 +2958,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="address">Virtual address of the region to unmap</param>
|
/// <param name="address">Virtual address of the region to unmap</param>
|
||||||
/// <param name="pagesCount">Number of pages to unmap</param>
|
/// <param name="pagesCount">Number of pages to unmap</param>
|
||||||
/// <returns>Result of the unmapping operation</returns>
|
/// <returns>Result of the unmapping operation</returns>
|
||||||
protected abstract KernelResult Unmap(ulong address, ulong pagesCount);
|
protected abstract Result Unmap(ulong address, ulong pagesCount);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the permissions of a given virtual memory region.
|
/// Changes the permissions of a given virtual memory region.
|
||||||
|
@ -2966,7 +2967,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="pagesCount">Number of pages to have their permissions changed</param>
|
/// <param name="pagesCount">Number of pages to have their permissions changed</param>
|
||||||
/// <param name="permission">New permission</param>
|
/// <param name="permission">New permission</param>
|
||||||
/// <returns>Result of the permission change operation</returns>
|
/// <returns>Result of the permission change operation</returns>
|
||||||
protected abstract KernelResult Reprotect(ulong address, ulong pagesCount, KMemoryPermission permission);
|
protected abstract Result Reprotect(ulong address, ulong pagesCount, KMemoryPermission permission);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the permissions of a given virtual memory region.
|
/// Changes the permissions of a given virtual memory region.
|
||||||
|
@ -2975,7 +2976,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="pagesCount">Number of pages to have their permissions changed</param>
|
/// <param name="pagesCount">Number of pages to have their permissions changed</param>
|
||||||
/// <param name="permission">New permission</param>
|
/// <param name="permission">New permission</param>
|
||||||
/// <returns>Result of the permission change operation</returns>
|
/// <returns>Result of the permission change operation</returns>
|
||||||
protected abstract KernelResult ReprotectWithAttributes(ulong address, ulong pagesCount, KMemoryPermission permission);
|
protected abstract Result ReprotectWithAttributes(ulong address, ulong pagesCount, KMemoryPermission permission);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Alerts the memory tracking that a given region has been read from or written to.
|
/// Alerts the memory tracking that a given region has been read from or written to.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
|
@ -26,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_userPermission = userPermission;
|
_userPermission = userPermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapIntoProcess(
|
public Result MapIntoProcess(
|
||||||
KPageTableBase memoryManager,
|
KPageTableBase memoryManager,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
|
@ -50,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission);
|
return memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapFromProcess(KPageTableBase memoryManager, ulong address, ulong size, KProcess process)
|
public Result UnmapFromProcess(KPageTableBase memoryManager, ulong address, ulong size, KProcess process)
|
||||||
{
|
{
|
||||||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
|
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
@ -36,15 +37,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
_isMapped = false;
|
_isMapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Initialize(ulong address, ulong size, KMemoryPermission permission)
|
public Result Initialize(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
KProcess creator = KernelStatic.GetCurrentProcess();
|
KProcess creator = KernelStatic.GetCurrentProcess();
|
||||||
|
|
||||||
_creator = creator;
|
_creator = creator;
|
||||||
|
|
||||||
KernelResult result = creator.MemoryManager.BorrowTransferMemory(_pageList, address, size, permission);
|
Result result = creator.MemoryManager.BorrowTransferMemory(_pageList, address, size, permission);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +61,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult MapIntoProcess(
|
public Result MapIntoProcess(
|
||||||
KPageTableBase memoryManager,
|
KPageTableBase memoryManager,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
|
@ -79,9 +80,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;
|
MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;
|
||||||
|
|
||||||
KernelResult result = memoryManager.MapPages(address, _pageList, state, KMemoryPermission.ReadAndWrite);
|
Result result = memoryManager.MapPages(address, _pageList, state, KMemoryPermission.ReadAndWrite);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_isMapped = true;
|
_isMapped = true;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult UnmapFromProcess(
|
public Result UnmapFromProcess(
|
||||||
KPageTableBase memoryManager,
|
KPageTableBase memoryManager,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
|
@ -102,9 +103,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;
|
MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory;
|
||||||
|
|
||||||
KernelResult result = memoryManager.UnmapPages(address, _pageList, state);
|
Result result = memoryManager.UnmapPages(address, _pageList, state);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
_isMapped = false;
|
_isMapped = false;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
if (_hasBeenInitialized)
|
if (_hasBeenInitialized)
|
||||||
{
|
{
|
||||||
if (!_isMapped && _creator.MemoryManager.UnborrowTransferMemory(Address, Size, _pageList) != KernelResult.Success)
|
if (!_isMapped && _creator.MemoryManager.UnborrowTransferMemory(Address, Size, _pageList) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Unexpected failure restoring transfer memory attributes.");
|
throw new InvalidOperationException("Unexpected failure restoring transfer memory attributes.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Process
|
namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
@ -27,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Initialize(int size)
|
public Result Initialize(int size)
|
||||||
{
|
{
|
||||||
if ((uint)size > 1024)
|
if ((uint)size > 1024)
|
||||||
{
|
{
|
||||||
|
@ -62,10 +63,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
_nextFreeEntry = _tableHead;
|
_nextFreeEntry = _tableHead;
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult GenerateHandle(KAutoObject obj, out int handle)
|
public Result GenerateHandle(KAutoObject obj, out int handle)
|
||||||
{
|
{
|
||||||
handle = 0;
|
handle = 0;
|
||||||
|
|
||||||
|
@ -99,10 +100,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult ReserveHandle(out int handle)
|
public Result ReserveHandle(out int handle)
|
||||||
{
|
{
|
||||||
handle = 0;
|
handle = 0;
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CancelHandleReservation(int handle)
|
public void CancelHandleReservation(int handle)
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -116,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
Debugger = new HleProcessDebugger(this);
|
Debugger = new HleProcessDebugger(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult InitializeKip(
|
public Result InitializeKip(
|
||||||
ProcessCreationInfo creationInfo,
|
ProcessCreationInfo creationInfo,
|
||||||
ReadOnlySpan<int> capabilities,
|
ReadOnlySpan<int> capabilities,
|
||||||
KPageList pageList,
|
KPageList pageList,
|
||||||
|
@ -151,7 +152,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
? KernelContext.LargeMemoryBlockSlabManager
|
? KernelContext.LargeMemoryBlockSlabManager
|
||||||
: KernelContext.SmallMemoryBlockSlabManager;
|
: KernelContext.SmallMemoryBlockSlabManager;
|
||||||
|
|
||||||
KernelResult result = MemoryManager.InitializeForProcess(
|
Result result = MemoryManager.InitializeForProcess(
|
||||||
addrSpaceType,
|
addrSpaceType,
|
||||||
aslrEnabled,
|
aslrEnabled,
|
||||||
!aslrEnabled,
|
!aslrEnabled,
|
||||||
|
@ -160,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
codeSize,
|
codeSize,
|
||||||
slabManager);
|
slabManager);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -172,14 +173,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = MemoryManager.MapPages(codeAddress, pageList, MemoryState.CodeStatic, KMemoryPermission.None);
|
result = MemoryManager.MapPages(codeAddress, pageList, MemoryState.CodeStatic, KMemoryPermission.None);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Capabilities.InitializeForKernel(capabilities, MemoryManager);
|
result = Capabilities.InitializeForKernel(capabilities, MemoryManager);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +188,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return ParseProcessInfo(creationInfo);
|
return ParseProcessInfo(creationInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Initialize(
|
public Result Initialize(
|
||||||
ProcessCreationInfo creationInfo,
|
ProcessCreationInfo creationInfo,
|
||||||
ReadOnlySpan<int> capabilities,
|
ReadOnlySpan<int> capabilities,
|
||||||
KResourceLimit resourceLimit,
|
KResourceLimit resourceLimit,
|
||||||
|
@ -255,7 +256,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
ulong codeSize = codePagesCount * KPageTableBase.PageSize;
|
ulong codeSize = codePagesCount * KPageTableBase.PageSize;
|
||||||
|
|
||||||
KernelResult result = MemoryManager.InitializeForProcess(
|
Result result = MemoryManager.InitializeForProcess(
|
||||||
addrSpaceType,
|
addrSpaceType,
|
||||||
aslrEnabled,
|
aslrEnabled,
|
||||||
!aslrEnabled,
|
!aslrEnabled,
|
||||||
|
@ -264,7 +265,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
codeSize,
|
codeSize,
|
||||||
slabManager);
|
slabManager);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -284,7 +285,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
MemoryState.CodeStatic,
|
MemoryState.CodeStatic,
|
||||||
KMemoryPermission.None);
|
KMemoryPermission.None);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -293,7 +294,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = Capabilities.InitializeForUser(capabilities, MemoryManager);
|
result = Capabilities.InitializeForUser(capabilities, MemoryManager);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -302,7 +303,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = ParseProcessInfo(creationInfo);
|
result = ParseProcessInfo(creationInfo);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
}
|
}
|
||||||
|
@ -310,7 +311,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult ParseProcessInfo(ProcessCreationInfo creationInfo)
|
private Result ParseProcessInfo(ProcessCreationInfo creationInfo)
|
||||||
{
|
{
|
||||||
// Ensure that the current kernel version is equal or above to the minimum required.
|
// Ensure that the current kernel version is equal or above to the minimum required.
|
||||||
uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19;
|
uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19;
|
||||||
|
@ -334,9 +335,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = AllocateThreadLocalStorage(out ulong userExceptionContextAddress);
|
Result result = AllocateThreadLocalStorage(out ulong userExceptionContextAddress);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -378,14 +379,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
GenerateRandomEntropy();
|
GenerateRandomEntropy();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult AllocateThreadLocalStorage(out ulong address)
|
public Result AllocateThreadLocalStorage(out ulong address)
|
||||||
{
|
{
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
if (_freeTlsPages.Count > 0)
|
if (_freeTlsPages.Count > 0)
|
||||||
{
|
{
|
||||||
|
@ -404,14 +405,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
_fullTlsPages.Add(pageInfo.PageVirtualAddress, pageInfo);
|
_fullTlsPages.Add(pageInfo.PageVirtualAddress, pageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Otherwise, we need to create a new one.
|
// Otherwise, we need to create a new one.
|
||||||
result = AllocateTlsPage(out KTlsPageInfo pageInfo);
|
result = AllocateTlsPage(out KTlsPageInfo pageInfo);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
if (!pageInfo.TryGetFreePage(out address))
|
if (!pageInfo.TryGetFreePage(out address))
|
||||||
{
|
{
|
||||||
|
@ -431,7 +432,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult AllocateTlsPage(out KTlsPageInfo pageInfo)
|
private Result AllocateTlsPage(out KTlsPageInfo pageInfo)
|
||||||
{
|
{
|
||||||
pageInfo = default;
|
pageInfo = default;
|
||||||
|
|
||||||
|
@ -445,7 +446,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
ulong regionPagesCount = regionSize / KPageTableBase.PageSize;
|
ulong regionPagesCount = regionSize / KPageTableBase.PageSize;
|
||||||
|
|
||||||
KernelResult result = MemoryManager.MapPages(
|
Result result = MemoryManager.MapPages(
|
||||||
1,
|
1,
|
||||||
KPageTableBase.PageSize,
|
KPageTableBase.PageSize,
|
||||||
tlsPagePa,
|
tlsPagePa,
|
||||||
|
@ -456,7 +457,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
KMemoryPermission.ReadAndWrite,
|
KMemoryPermission.ReadAndWrite,
|
||||||
out ulong tlsPageVa);
|
out ulong tlsPageVa);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
KernelContext.UserSlabHeapPages.Free(tlsPagePa);
|
KernelContext.UserSlabHeapPages.Free(tlsPagePa);
|
||||||
}
|
}
|
||||||
|
@ -470,13 +471,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult FreeThreadLocalStorage(ulong tlsSlotAddr)
|
public Result FreeThreadLocalStorage(ulong tlsSlotAddr)
|
||||||
{
|
{
|
||||||
ulong tlsPageAddr = BitUtils.AlignDown<ulong>(tlsSlotAddr, KPageTableBase.PageSize);
|
ulong tlsPageAddr = BitUtils.AlignDown<ulong>(tlsSlotAddr, KPageTableBase.PageSize);
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
KTlsPageInfo pageInfo;
|
KTlsPageInfo pageInfo;
|
||||||
|
|
||||||
|
@ -506,7 +507,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
FreeTlsPage(pageInfo);
|
FreeTlsPage(pageInfo);
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,11 +516,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult FreeTlsPage(KTlsPageInfo pageInfo)
|
private Result FreeTlsPage(KTlsPageInfo pageInfo)
|
||||||
{
|
{
|
||||||
KernelResult result = MemoryManager.UnmapForKernel(pageInfo.PageVirtualAddress, 1, MemoryState.ThreadLocal);
|
Result result = MemoryManager.UnmapForKernel(pageInfo.PageVirtualAddress, 1, MemoryState.ThreadLocal);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
KernelContext.UserSlabHeapPages.Free(pageInfo.PagePhysicalAddress);
|
KernelContext.UserSlabHeapPages.Free(pageInfo.PagePhysicalAddress);
|
||||||
}
|
}
|
||||||
|
@ -532,7 +533,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
// TODO.
|
// TODO.
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Start(int mainThreadPriority, ulong stackSize)
|
public Result Start(int mainThreadPriority, ulong stackSize)
|
||||||
{
|
{
|
||||||
lock (_processLock)
|
lock (_processLock)
|
||||||
{
|
{
|
||||||
|
@ -580,7 +581,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
KThread mainThread = null;
|
KThread mainThread = null;
|
||||||
|
|
||||||
|
@ -627,7 +628,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
KMemoryPermission.ReadAndWrite,
|
KMemoryPermission.ReadAndWrite,
|
||||||
out ulong stackBottom);
|
out ulong stackBottom);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -643,7 +644,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = MemoryManager.SetHeapCapacity(heapCapacity);
|
result = MemoryManager.SetHeapCapacity(heapCapacity);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -654,7 +655,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = HandleTable.Initialize(Capabilities.HandleTableSize);
|
result = HandleTable.Initialize(Capabilities.HandleTableSize);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -673,7 +674,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
ThreadType.User,
|
ThreadType.User,
|
||||||
_customThreadStart);
|
_customThreadStart);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -682,7 +683,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = HandleTable.GenerateHandle(mainThread, out int mainThreadHandle);
|
result = HandleTable.GenerateHandle(mainThread, out int mainThreadHandle);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -700,14 +701,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
result = mainThread.Start();
|
result = mainThread.Start();
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
SetState(oldState);
|
SetState(oldState);
|
||||||
|
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
mainThread.IncrementReferenceCount();
|
mainThread.IncrementReferenceCount();
|
||||||
}
|
}
|
||||||
|
@ -729,7 +730,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult InitializeThread(
|
public Result InitializeThread(
|
||||||
KThread thread,
|
KThread thread,
|
||||||
ulong entrypoint,
|
ulong entrypoint,
|
||||||
ulong argsPtr,
|
ulong argsPtr,
|
||||||
|
@ -888,9 +889,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return _signaled;
|
return _signaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Terminate()
|
public Result Terminate()
|
||||||
{
|
{
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
bool shallTerminate = false;
|
bool shallTerminate = false;
|
||||||
|
|
||||||
|
@ -910,7 +911,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
shallTerminate = true;
|
shallTerminate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1044,9 +1045,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult ClearIfNotExited()
|
public Result ClearIfNotExited()
|
||||||
{
|
{
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -1056,7 +1057,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
_signaled = false;
|
_signaled = false;
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1107,7 +1108,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
protected override void Destroy() => Context.Dispose();
|
protected override void Destroy() => Context.Dispose();
|
||||||
|
|
||||||
public KernelResult SetActivity(bool pause)
|
public Result SetActivity(bool pause)
|
||||||
{
|
{
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -1154,7 +1155,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
IrqAccessMask = new byte[0x80];
|
IrqAccessMask = new byte[0x80];
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult InitializeForKernel(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
|
public Result InitializeForKernel(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
AllowedCpuCoresMask = 0xf;
|
AllowedCpuCoresMask = 0xf;
|
||||||
AllowedThreadPriosMask = ulong.MaxValue;
|
AllowedThreadPriosMask = ulong.MaxValue;
|
||||||
|
@ -35,12 +36,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
return Parse(capabilities, memoryManager);
|
return Parse(capabilities, memoryManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult InitializeForUser(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
|
public Result InitializeForUser(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
return Parse(capabilities, memoryManager);
|
return Parse(capabilities, memoryManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult Parse(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
|
private Result Parse(ReadOnlySpan<int> capabilities, KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
int mask0 = 0;
|
int mask0 = 0;
|
||||||
int mask1 = 0;
|
int mask1 = 0;
|
||||||
|
@ -51,9 +52,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
if (((cap + 1) & ~cap) != 0x40)
|
if (((cap + 1) & ~cap) != 0x40)
|
||||||
{
|
{
|
||||||
KernelResult result = ParseCapability(cap, ref mask0, ref mask1, memoryManager);
|
Result result = ParseCapability(cap, ref mask0, ref mask1, memoryManager);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +97,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
? KMemoryPermission.Read
|
? KMemoryPermission.Read
|
||||||
: KMemoryPermission.ReadAndWrite;
|
: KMemoryPermission.ReadAndWrite;
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
if ((cap >> 31) != 0)
|
if ((cap >> 31) != 0)
|
||||||
{
|
{
|
||||||
|
@ -107,17 +108,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
result = memoryManager.MapIoMemory(address, size, perm);
|
result = memoryManager.MapIoMemory(address, size, perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult ParseCapability(int cap, ref int mask0, ref int mask1, KPageTableBase memoryManager)
|
private Result ParseCapability(int cap, ref int mask0, ref int mask1, KPageTableBase memoryManager)
|
||||||
{
|
{
|
||||||
int code = (cap + 1) & ~cap;
|
int code = (cap + 1) & ~cap;
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
}
|
}
|
||||||
else if (code == 0)
|
else if (code == 0)
|
||||||
{
|
{
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int codeMask = 1 << (32 - BitOperations.LeadingZeroCount((uint)code + 1));
|
int codeMask = 1 << (32 - BitOperations.LeadingZeroCount((uint)code + 1));
|
||||||
|
@ -300,7 +301,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
default: return KernelResult.InvalidCapability;
|
default: return KernelResult.InvalidCapability;
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong GetMaskFromMinMax(int min, int max)
|
private static ulong GetMaskFromMinMax(int min, int max)
|
||||||
|
|
|
@ -7,16 +7,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
public ulong Pc => 0UL;
|
public ulong Pc => 0UL;
|
||||||
|
|
||||||
public ulong CntfrqEl0 { get => 0; set { } }
|
public ulong CntfrqEl0 { get; set; }
|
||||||
public ulong CntpctEl0 => 0UL;
|
public ulong CntpctEl0 => 0UL;
|
||||||
|
|
||||||
public long TpidrEl0 { get => 0; set { } }
|
public long TpidrEl0 { get; set; }
|
||||||
public long TpidrroEl0 { get => 0; set { } }
|
public long TpidrroEl0 { get; set; }
|
||||||
|
|
||||||
public uint Pstate { get => 0; set { } }
|
public uint Pstate { get; set; }
|
||||||
|
|
||||||
public uint Fpcr { get => 0; set { } }
|
public uint Fpcr { get; set; }
|
||||||
public uint Fpsr { get => 0; set { } }
|
public uint Fpsr { get; set; }
|
||||||
|
|
||||||
public bool IsAarch32 { get => false; set { } }
|
public bool IsAarch32 { get => false; set { } }
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -24,14 +25,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
_arbiterThreads = new List<KThread>();
|
_arbiterThreads = new List<KThread>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
|
public Result ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
|
||||||
{
|
{
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
currentThread.SignaledObj = null;
|
currentThread.SignaledObj = null;
|
||||||
currentThread.ObjSyncResult = KernelResult.Success;
|
currentThread.ObjSyncResult = Result.Success;
|
||||||
|
|
||||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
_context.CriticalSection.Leave();
|
_context.CriticalSection.Leave();
|
||||||
|
|
||||||
return 0;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread mutexOwner = currentProcess.HandleTable.GetObject<KThread>(ownerHandle);
|
KThread mutexOwner = currentProcess.HandleTable.GetObject<KThread>(ownerHandle);
|
||||||
|
@ -78,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return currentThread.ObjSyncResult;
|
return currentThread.ObjSyncResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult ArbitrateUnlock(ulong mutexAddress)
|
public Result ArbitrateUnlock(ulong mutexAddress)
|
||||||
{
|
{
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -86,14 +87,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
(int mutexValue, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress);
|
(int mutexValue, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress);
|
||||||
|
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
if (!KernelTransfer.KernelToUser(mutexAddress, mutexValue))
|
if (!KernelTransfer.KernelToUser(mutexAddress, mutexValue))
|
||||||
{
|
{
|
||||||
result = KernelResult.InvalidMemState;
|
result = KernelResult.InvalidMemState;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != KernelResult.Success && newOwnerThread != null)
|
if (result != Result.Success && newOwnerThread != null)
|
||||||
{
|
{
|
||||||
newOwnerThread.SignaledObj = null;
|
newOwnerThread.SignaledObj = null;
|
||||||
newOwnerThread.ObjSyncResult = result;
|
newOwnerThread.ObjSyncResult = result;
|
||||||
|
@ -104,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult WaitProcessWideKeyAtomic(ulong mutexAddress, ulong condVarAddress, int threadHandle, long timeout)
|
public Result WaitProcessWideKeyAtomic(ulong mutexAddress, ulong condVarAddress, int threadHandle, long timeout)
|
||||||
{
|
{
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -185,7 +186,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
}
|
}
|
||||||
|
|
||||||
newOwnerThread.SignaledObj = null;
|
newOwnerThread.SignaledObj = null;
|
||||||
newOwnerThread.ObjSyncResult = KernelResult.Success;
|
newOwnerThread.ObjSyncResult = Result.Success;
|
||||||
|
|
||||||
newOwnerThread.ReleaseAndResume();
|
newOwnerThread.ReleaseAndResume();
|
||||||
}
|
}
|
||||||
|
@ -247,7 +248,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
// We now own the mutex.
|
// We now own the mutex.
|
||||||
requester.SignaledObj = null;
|
requester.SignaledObj = null;
|
||||||
requester.ObjSyncResult = KernelResult.Success;
|
requester.ObjSyncResult = Result.Success;
|
||||||
|
|
||||||
requester.ReleaseAndResume();
|
requester.ReleaseAndResume();
|
||||||
|
|
||||||
|
@ -273,7 +274,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult WaitForAddressIfEqual(ulong address, int value, long timeout)
|
public Result WaitForAddressIfEqual(ulong address, int value, long timeout)
|
||||||
{
|
{
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
|
@ -344,7 +345,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return KernelResult.InvalidState;
|
return KernelResult.InvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult WaitForAddressIfLessThan(ulong address, int value, bool shouldDecrement, long timeout)
|
public Result WaitForAddressIfLessThan(ulong address, int value, bool shouldDecrement, long timeout)
|
||||||
{
|
{
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
|
@ -422,7 +423,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return KernelResult.InvalidState;
|
return KernelResult.InvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Signal(ulong address, int count)
|
public Result Signal(ulong address, int count)
|
||||||
{
|
{
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -430,10 +431,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
_context.CriticalSection.Leave();
|
_context.CriticalSection.Leave();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SignalAndIncrementIfEqual(ulong address, int value, int count)
|
public Result SignalAndIncrementIfEqual(ulong address, int value, int count)
|
||||||
{
|
{
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -467,10 +468,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
_context.CriticalSection.Leave();
|
_context.CriticalSection.Leave();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SignalAndModifyIfEqual(ulong address, int value, int count)
|
public Result SignalAndModifyIfEqual(ulong address, int value, int count)
|
||||||
{
|
{
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -539,7 +540,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
_context.CriticalSection.Leave();
|
_context.CriticalSection.Leave();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WakeArbiterThreads(ulong address, int count)
|
private void WakeArbiterThreads(ulong address, int count)
|
||||||
|
@ -547,7 +548,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
static void RemoveArbiterThread(KThread thread)
|
static void RemoveArbiterThread(KThread thread)
|
||||||
{
|
{
|
||||||
thread.SignaledObj = null;
|
thread.SignaledObj = null;
|
||||||
thread.ObjSyncResult = KernelResult.Success;
|
thread.ObjSyncResult = Result.Success;
|
||||||
|
|
||||||
thread.ReleaseAndResume();
|
thread.ReleaseAndResume();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
|
@ -27,16 +28,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Clear()
|
public Result Clear()
|
||||||
{
|
{
|
||||||
_signaled = false;
|
_signaled = false;
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult ClearIfSignaled()
|
public Result ClearIfSignaled()
|
||||||
{
|
{
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
_signaled = false;
|
_signaled = false;
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -13,11 +14,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult WaitFor(Span<KSynchronizationObject> syncObjs, long timeout, out int handleIndex)
|
public Result WaitFor(Span<KSynchronizationObject> syncObjs, long timeout, out int handleIndex)
|
||||||
{
|
{
|
||||||
handleIndex = 0;
|
handleIndex = 0;
|
||||||
|
|
||||||
KernelResult result = KernelResult.TimedOut;
|
Result result = KernelResult.TimedOut;
|
||||||
|
|
||||||
_context.CriticalSection.Enter();
|
_context.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
_context.CriticalSection.Leave();
|
_context.CriticalSection.Leave();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
|
@ -122,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
||||||
{
|
{
|
||||||
thread.SignaledObj = syncObj;
|
thread.SignaledObj = syncObj;
|
||||||
thread.ObjSyncResult = KernelResult.Success;
|
thread.ObjSyncResult = Result.Success;
|
||||||
|
|
||||||
thread.Reschedule(ThreadSchedState.Running);
|
thread.Reschedule(ThreadSchedState.Running);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
|
using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
@ -79,7 +80,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
private ThreadSchedState _forcePauseFlags;
|
private ThreadSchedState _forcePauseFlags;
|
||||||
private ThreadSchedState _forcePausePermissionFlags;
|
private ThreadSchedState _forcePausePermissionFlags;
|
||||||
|
|
||||||
public KernelResult ObjSyncResult { get; set; }
|
public Result ObjSyncResult { get; set; }
|
||||||
|
|
||||||
public int BasePriority { get; set; }
|
public int BasePriority { get; set; }
|
||||||
public int PreferredCore { get; set; }
|
public int PreferredCore { get; set; }
|
||||||
|
@ -130,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
_activityOperationLock = new object();
|
_activityOperationLock = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Initialize(
|
public Result Initialize(
|
||||||
ulong entrypoint,
|
ulong entrypoint,
|
||||||
ulong argsPtr,
|
ulong argsPtr,
|
||||||
ulong stackTop,
|
ulong stackTop,
|
||||||
|
@ -145,8 +146,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
throw new ArgumentException($"Invalid thread type \"{type}\".");
|
throw new ArgumentException($"Invalid thread type \"{type}\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadContext = new KThreadContext();
|
|
||||||
|
|
||||||
PreferredCore = cpuCore;
|
PreferredCore = cpuCore;
|
||||||
AffinityMask |= 1UL << cpuCore;
|
AffinityMask |= 1UL << cpuCore;
|
||||||
|
|
||||||
|
@ -166,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
if (type == ThreadType.User)
|
if (type == ThreadType.User)
|
||||||
{
|
{
|
||||||
if (owner.AllocateThreadLocalStorage(out _tlsAddress) != KernelResult.Success)
|
if (owner.AllocateThreadLocalStorage(out _tlsAddress) != Result.Success)
|
||||||
{
|
{
|
||||||
return KernelResult.OutOfMemory;
|
return KernelResult.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
@ -194,6 +193,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
||||||
|
|
||||||
|
ThreadContext = new KThreadContext(Context);
|
||||||
|
|
||||||
Context.IsAarch32 = !is64Bits;
|
Context.IsAarch32 = !is64Bits;
|
||||||
|
|
||||||
Context.SetX(0, argsPtr);
|
Context.SetX(0, argsPtr);
|
||||||
|
@ -230,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
_forcePauseFlags |= ThreadSchedState.ProcessPauseFlag;
|
_forcePauseFlags |= ThreadSchedState.ProcessPauseFlag;
|
||||||
|
@ -241,10 +242,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Start()
|
public Result Start()
|
||||||
{
|
{
|
||||||
if (!KernelContext.KernelInitialized)
|
if (!KernelContext.KernelInitialized)
|
||||||
{
|
{
|
||||||
|
@ -260,7 +261,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = KernelResult.ThreadTerminating;
|
Result result = KernelResult.ThreadTerminating;
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -287,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
StartHostThread();
|
StartHostThread();
|
||||||
|
|
||||||
result = KernelResult.Success;
|
result = Result.Success;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -465,7 +466,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Sleep(long timeout)
|
public Result Sleep(long timeout)
|
||||||
{
|
{
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -490,7 +491,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KernelContext.TimeManager.UnscheduleFutureInvocation(this);
|
KernelContext.TimeManager.UnscheduleFutureInvocation(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPriority(int priority)
|
public void SetPriority(int priority)
|
||||||
|
@ -534,11 +535,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetActivity(bool pause)
|
public Result SetActivity(bool pause)
|
||||||
{
|
{
|
||||||
lock (_activityOperationLock)
|
lock (_activityOperationLock)
|
||||||
{
|
{
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
KernelContext.CriticalSection.Enter();
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
@ -581,7 +582,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
|
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
|
|
||||||
if (result == KernelResult.Success && pause)
|
if (result == Result.Success && pause)
|
||||||
{
|
{
|
||||||
bool isThreadRunning = true;
|
bool isThreadRunning = true;
|
||||||
|
|
||||||
|
@ -628,7 +629,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult GetThreadContext3(out ThreadContext context)
|
public Result GetThreadContext3(out ThreadContext context)
|
||||||
{
|
{
|
||||||
context = default;
|
context = default;
|
||||||
|
|
||||||
|
@ -651,7 +652,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint GetPsr(IExecutionContext context)
|
private static uint GetPsr(IExecutionContext context)
|
||||||
|
@ -739,7 +740,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult SetCoreAndAffinityMask(int newCore, ulong newAffinityMask)
|
public Result SetCoreAndAffinityMask(int newCore, ulong newAffinityMask)
|
||||||
{
|
{
|
||||||
lock (_activityOperationLock)
|
lock (_activityOperationLock)
|
||||||
{
|
{
|
||||||
|
@ -838,7 +839,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
KernelContext.CriticalSection.Leave();
|
KernelContext.CriticalSection.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1259,6 +1260,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
if (_customThreadStart != null)
|
if (_customThreadStart != null)
|
||||||
{
|
{
|
||||||
_customThreadStart();
|
_customThreadStart();
|
||||||
|
|
||||||
|
// Ensure that anything trying to join the HLE thread is unblocked.
|
||||||
|
Exit();
|
||||||
|
HandlePostSyscall();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1304,7 +1309,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
Owner?.RemoveThread(this);
|
Owner?.RemoveThread(this);
|
||||||
|
|
||||||
if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != KernelResult.Success)
|
if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Unexpected failure freeing thread local storage.");
|
throw new InvalidOperationException("Unexpected failure freeing thread local storage.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
using System.Threading;
|
using Ryujinx.Cpu;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
class KThreadContext
|
class KThreadContext : IThreadContext
|
||||||
{
|
{
|
||||||
|
private readonly IExecutionContext _context;
|
||||||
|
|
||||||
|
public bool Running => _context.Running;
|
||||||
|
public ulong TlsAddress => (ulong)_context.TpidrroEl0;
|
||||||
|
|
||||||
private int _locked;
|
private int _locked;
|
||||||
|
|
||||||
|
public KThreadContext(IExecutionContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Lock()
|
public bool Lock()
|
||||||
{
|
{
|
||||||
return Interlocked.Exchange(ref _locked, 1) == 0;
|
return Interlocked.Exchange(ref _locked, 1) == 0;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
{
|
{
|
||||||
|
@ -16,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
_parent.ReadableEvent.Signal();
|
_parent.ReadableEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KernelResult Clear()
|
public Result Clear()
|
||||||
{
|
{
|
||||||
return _parent.ReadableEvent.Clear();
|
return _parent.ReadableEvent.Clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
@ -90,9 +91,9 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
KMemoryRegionManager region = context.MemoryManager.MemoryRegions[(int)memoryRegion];
|
KMemoryRegionManager region = context.MemoryManager.MemoryRegions[(int)memoryRegion];
|
||||||
|
|
||||||
KernelResult result = region.AllocatePages(out KPageList pageList, (ulong)codePagesCount);
|
Result result = region.AllocatePages(out KPageList pageList, (ulong)codePagesCount);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
memoryRegion,
|
memoryRegion,
|
||||||
processContextFactory);
|
processContextFactory);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
result = LoadIntoMemory(process, kip, codeBaseAddress);
|
result = LoadIntoMemory(process, kip, codeBaseAddress);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
result = process.Start(kip.Priority, (ulong)kip.StackSize);
|
result = process.Start(kip.Priority, (ulong)kip.StackSize);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process start returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process start returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -230,19 +231,35 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
context.Device.System.LibHacHorizonManager.InitializeApplicationClient(new ProgramId(programInfo.ProgramId), in npdm);
|
context.Device.System.LibHacHorizonManager.InitializeApplicationClient(new ProgramId(programInfo.ProgramId), in npdm);
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
KResourceLimit resourceLimit = new KResourceLimit(context);
|
KResourceLimit resourceLimit = new KResourceLimit(context);
|
||||||
|
|
||||||
long applicationRgSize = (long)context.MemoryManager.MemoryRegions[(int)MemoryRegion.Application].Size;
|
long applicationRgSize = (long)context.MemoryManager.MemoryRegions[(int)MemoryRegion.Application].Size;
|
||||||
|
|
||||||
result = resourceLimit.SetLimitValue(LimitableResource.Memory, applicationRgSize);
|
result = resourceLimit.SetLimitValue(LimitableResource.Memory, applicationRgSize);
|
||||||
result |= resourceLimit.SetLimitValue(LimitableResource.Thread, 608);
|
|
||||||
result |= resourceLimit.SetLimitValue(LimitableResource.Event, 700);
|
|
||||||
result |= resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 128);
|
|
||||||
result |= resourceLimit.SetLimitValue(LimitableResource.Session, 894);
|
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result.IsSuccess)
|
||||||
|
{
|
||||||
|
result = resourceLimit.SetLimitValue(LimitableResource.Thread, 608);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess)
|
||||||
|
{
|
||||||
|
result = resourceLimit.SetLimitValue(LimitableResource.Event, 700);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess)
|
||||||
|
{
|
||||||
|
result = resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess)
|
||||||
|
{
|
||||||
|
result = resourceLimit.SetLimitValue(LimitableResource.Session, 894);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization failed setting resource limit values.");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization failed setting resource limit values.");
|
||||||
|
|
||||||
|
@ -273,7 +290,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
memoryRegion,
|
memoryRegion,
|
||||||
processContextFactory);
|
processContextFactory);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -288,7 +305,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
result = LoadIntoMemory(process, executables[index], nsoBase[index]);
|
result = LoadIntoMemory(process, executables[index], nsoBase[index]);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -302,7 +319,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
result = process.Start(meta.MainThreadPriority, meta.MainThreadStackSize);
|
result = process.Start(meta.MainThreadPriority, meta.MainThreadStackSize);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Loader, $"Process start returned error \"{result}\".");
|
Logger.Error?.Print(LogClass.Loader, $"Process start returned error \"{result}\".");
|
||||||
|
|
||||||
|
@ -322,18 +339,18 @@ namespace Ryujinx.HLE.HOS
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KernelResult LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress)
|
private static Result LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress)
|
||||||
{
|
{
|
||||||
ulong textStart = baseAddress + (ulong)image.TextOffset;
|
ulong textStart = baseAddress + image.TextOffset;
|
||||||
ulong roStart = baseAddress + (ulong)image.RoOffset;
|
ulong roStart = baseAddress + image.RoOffset;
|
||||||
ulong dataStart = baseAddress + (ulong)image.DataOffset;
|
ulong dataStart = baseAddress + image.DataOffset;
|
||||||
ulong bssStart = baseAddress + (ulong)image.BssOffset;
|
ulong bssStart = baseAddress + image.BssOffset;
|
||||||
|
|
||||||
ulong end = dataStart + (ulong)image.Data.Length;
|
ulong end = dataStart + (ulong)image.Data.Length;
|
||||||
|
|
||||||
if (image.BssSize != 0)
|
if (image.BssSize != 0)
|
||||||
{
|
{
|
||||||
end = bssStart + (ulong)image.BssSize;
|
end = bssStart + image.BssSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
process.CpuMemory.Write(textStart, image.Text);
|
process.CpuMemory.Write(textStart, image.Text);
|
||||||
|
@ -342,11 +359,11 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
process.CpuMemory.Fill(bssStart, image.BssSize, 0);
|
process.CpuMemory.Fill(bssStart, image.BssSize, 0);
|
||||||
|
|
||||||
KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
Result SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
return KernelResult.Success;
|
return Result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = BitUtils.AlignUp<ulong>(size, KPageTableBase.PageSize);
|
size = BitUtils.AlignUp<ulong>(size, KPageTableBase.PageSize);
|
||||||
|
@ -354,16 +371,16 @@ namespace Ryujinx.HLE.HOS
|
||||||
return process.MemoryManager.SetProcessMemoryPermission(address, size, permission);
|
return process.MemoryManager.SetProcessMemoryPermission(address, size, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = SetProcessMemoryPermission(textStart, (ulong)image.Text.Length, KMemoryPermission.ReadAndExecute);
|
Result result = SetProcessMemoryPermission(textStart, (ulong)image.Text.Length, KMemoryPermission.ReadAndExecute);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SetProcessMemoryPermission(roStart, (ulong)image.Ro.Length, KMemoryPermission.Read);
|
result = SetProcessMemoryPermission(roStart, (ulong)image.Ro.Length, KMemoryPermission.Read);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
|
using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||||
|
@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
|
||||||
// GetSystemEvent() -> handle<copy>
|
// GetSystemEvent() -> handle<copy>
|
||||||
public ResultCode GetSystemEvent(ServiceCtx context)
|
public ResultCode GetSystemEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(AsyncExecution.SystemEvent.ReadableEvent, out int _systemEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(AsyncExecution.SystemEvent.ReadableEvent, out int _systemEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
using Ryujinx.HLE.HOS.Applets;
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
|
||||||
|
@ -68,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
||||||
{
|
{
|
||||||
if (_stateChangedEventHandle == 0)
|
if (_stateChangedEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out _stateChangedEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out _stateChangedEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
||||||
{
|
{
|
||||||
if (_normalOutDataEventHandle == 0)
|
if (_normalOutDataEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out _normalOutDataEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out _normalOutDataEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
|
||||||
{
|
{
|
||||||
if (_interactiveOutDataEventHandle == 0)
|
if (_interactiveOutDataEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out _interactiveOutDataEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out _interactiveOutDataEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Settings.Types;
|
using Ryujinx.HLE.HOS.Services.Settings.Types;
|
||||||
using Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService;
|
using Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
|
@ -38,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
|
|
||||||
if (_messageEventHandle == 0)
|
if (_messageEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(messageEvent.ReadableEvent, out _messageEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(messageEvent.ReadableEvent, out _messageEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
// NOTE: Original service calls IOperationModeManager::GetDefaultDisplayResolutionChangeEvent of omm service.
|
// NOTE: Original service calls IOperationModeManager::GetDefaultDisplayResolutionChangeEvent of omm service.
|
||||||
if (_displayResolutionChangedEventHandle == 0)
|
if (_displayResolutionChangedEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out _displayResolutionChangedEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out _displayResolutionChangedEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
return ResultCode.BufferAlreadyAcquired;
|
return ResultCode.BufferAlreadyAcquired;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
return ResultCode.BufferAlreadyAcquired;
|
return ResultCode.BufferAlreadyAcquired;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
|
@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
{
|
{
|
||||||
if (_channelEventHandle == 0)
|
if (_channelEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out _channelEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out _channelEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types;
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
|
@ -111,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
|
|
||||||
if (_libraryAppletLaunchableEventHandle == 0)
|
if (_libraryAppletLaunchableEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out _libraryAppletLaunchableEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out _libraryAppletLaunchableEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
|
|
||||||
_accumulatedSuspendedTickChangedEvent.ReadableEvent.Signal();
|
_accumulatedSuspendedTickChangedEvent.ReadableEvent.Signal();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_accumulatedSuspendedTickChangedEvent.ReadableEvent, out _accumulatedSuspendedTickChangedEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_accumulatedSuspendedTickChangedEvent.ReadableEvent, out _accumulatedSuspendedTickChangedEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using LibHac;
|
|
||||||
using LibHac.Account;
|
using LibHac.Account;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
@ -9,13 +8,13 @@ using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage;
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE.Storage;
|
||||||
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
|
||||||
using Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService;
|
using Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
@ -43,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
|
|
||||||
private int _jitLoaded;
|
private int _jitLoaded;
|
||||||
|
|
||||||
private HorizonClient _horizon;
|
private LibHac.HorizonClient _horizon;
|
||||||
|
|
||||||
public IApplicationFunctions(Horizon system)
|
public IApplicationFunctions(Horizon system)
|
||||||
{
|
{
|
||||||
|
@ -136,8 +135,8 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
"No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
|
"No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizonClient hos = context.Device.System.LibHacHorizonManager.AmClient;
|
LibHac.HorizonClient hos = context.Device.System.LibHacHorizonManager.AmClient;
|
||||||
Result result = hos.Fs.EnsureApplicationSaveData(out long requiredSize, applicationId, in control, in userId);
|
LibHac.Result result = hos.Fs.EnsureApplicationSaveData(out long requiredSize, applicationId, in control, in userId);
|
||||||
|
|
||||||
context.ResponseData.Write(requiredSize);
|
context.ResponseData.Write(requiredSize);
|
||||||
|
|
||||||
|
@ -185,7 +184,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
// SetTerminateResult(u32)
|
// SetTerminateResult(u32)
|
||||||
public ResultCode SetTerminateResult(ServiceCtx context)
|
public ResultCode SetTerminateResult(ServiceCtx context)
|
||||||
{
|
{
|
||||||
Result result = new Result(context.RequestData.ReadUInt32());
|
LibHac.Result result = new LibHac.Result(context.RequestData.ReadUInt32());
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.ServiceAm, $"Result = 0x{result.Value:x8} ({result.ToStringWithName()}).");
|
Logger.Info?.Print(LogClass.ServiceAm, $"Result = 0x{result.Value:x8} ({result.ToStringWithName()}).");
|
||||||
|
|
||||||
|
@ -256,7 +255,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
|
|
||||||
BlitStruct<ApplicationControlProperty> controlHolder = context.Device.Application.ControlData;
|
BlitStruct<ApplicationControlProperty> controlHolder = context.Device.Application.ControlData;
|
||||||
|
|
||||||
Result result = _horizon.Fs.CreateApplicationCacheStorage(out long requiredSize,
|
LibHac.Result result = _horizon.Fs.CreateApplicationCacheStorage(out long requiredSize,
|
||||||
out CacheStorageTargetMedia storageTarget, applicationId, in controlHolder.Value, index, saveSize,
|
out CacheStorageTargetMedia storageTarget, applicationId, in controlHolder.Value, index, saveSize,
|
||||||
journalSize);
|
journalSize);
|
||||||
|
|
||||||
|
@ -584,7 +583,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
{
|
{
|
||||||
if (_gpuErrorDetectedSystemEventHandle == 0)
|
if (_gpuErrorDetectedSystemEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_gpuErrorDetectedSystemEvent.ReadableEvent, out _gpuErrorDetectedSystemEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_gpuErrorDetectedSystemEvent.ReadableEvent, out _gpuErrorDetectedSystemEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -605,7 +604,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
{
|
{
|
||||||
if (_friendInvitationStorageChannelEventHandle == 0)
|
if (_friendInvitationStorageChannelEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_friendInvitationStorageChannelEvent.ReadableEvent, out _friendInvitationStorageChannelEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_friendInvitationStorageChannelEvent.ReadableEvent, out _friendInvitationStorageChannelEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -636,7 +635,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
{
|
{
|
||||||
if (_notificationStorageChannelEventHandle == 0)
|
if (_notificationStorageChannelEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_notificationStorageChannelEvent.ReadableEvent, out _notificationStorageChannelEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_notificationStorageChannelEvent.ReadableEvent, out _notificationStorageChannelEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -653,7 +652,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
{
|
{
|
||||||
if (_healthWarningDisappearedSystemEventHandle == 0)
|
if (_healthWarningDisappearedSystemEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_healthWarningDisappearedSystemEvent.ReadableEvent, out _healthWarningDisappearedSystemEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_healthWarningDisappearedSystemEvent.ReadableEvent, out _healthWarningDisappearedSystemEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.Audio.Common;
|
using Ryujinx.Audio.Common;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioIn
|
||||||
{
|
{
|
||||||
KEvent bufferEvent = _impl.RegisterBufferEvent();
|
KEvent bufferEvent = _impl.RegisterBufferEvent();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(bufferEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(bufferEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.Audio.Common;
|
using Ryujinx.Audio.Common;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOut
|
||||||
{
|
{
|
||||||
KEvent bufferEvent = _impl.RegisterBufferEvent();
|
KEvent bufferEvent = _impl.RegisterBufferEvent();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(bufferEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(bufferEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
{
|
{
|
||||||
KEvent deviceSystemEvent = _impl.QueryAudioDeviceSystemEvent();
|
KEvent deviceSystemEvent = _impl.QueryAudioDeviceSystemEvent();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(deviceSystemEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(deviceSystemEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
{
|
{
|
||||||
KEvent deviceInputEvent = _impl.QueryAudioDeviceInputEvent();
|
KEvent deviceInputEvent = _impl.QueryAudioDeviceInputEvent();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(deviceInputEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(deviceInputEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
{
|
{
|
||||||
KEvent deviceOutputEvent = _impl.QueryAudioDeviceOutputEvent();
|
KEvent deviceOutputEvent = _impl.QueryAudioDeviceOutputEvent();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(deviceOutputEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(deviceOutputEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(systemEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(systemEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator.Types;
|
using Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
|
@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
|
||||||
{
|
{
|
||||||
if (_eventHandle == 0)
|
if (_eventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Bluetooth.BluetoothDriver;
|
using Ryujinx.HLE.HOS.Services.Bluetooth.BluetoothDriver;
|
||||||
using Ryujinx.HLE.HOS.Services.Settings;
|
using Ryujinx.HLE.HOS.Services.Settings;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
|
@ -30,7 +30,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
{
|
{
|
||||||
BluetoothEventManager.InitializeBleDebugEvent = new KEvent(context.Device.System.KernelContext);
|
BluetoothEventManager.InitializeBleDebugEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.InitializeBleDebugEvent.ReadableEvent, out BluetoothEventManager.InitializeBleDebugEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.InitializeBleDebugEvent.ReadableEvent, out BluetoothEventManager.InitializeBleDebugEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
{
|
{
|
||||||
BluetoothEventManager.UnknownBleDebugEvent = new KEvent(context.Device.System.KernelContext);
|
BluetoothEventManager.UnknownBleDebugEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.UnknownBleDebugEvent.ReadableEvent, out BluetoothEventManager.UnknownBleDebugEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.UnknownBleDebugEvent.ReadableEvent, out BluetoothEventManager.UnknownBleDebugEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
{
|
{
|
||||||
BluetoothEventManager.RegisterBleDebugEvent = new KEvent(context.Device.System.KernelContext);
|
BluetoothEventManager.RegisterBleDebugEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.RegisterBleDebugEvent.ReadableEvent, out BluetoothEventManager.RegisterBleDebugEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.RegisterBleDebugEvent.ReadableEvent, out BluetoothEventManager.RegisterBleDebugEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
{
|
{
|
||||||
BluetoothEventManager.InitializeBleEvent = new KEvent(context.Device.System.KernelContext);
|
BluetoothEventManager.InitializeBleEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.InitializeBleEvent.ReadableEvent, out BluetoothEventManager.InitializeBleEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.InitializeBleEvent.ReadableEvent, out BluetoothEventManager.InitializeBleEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
{
|
{
|
||||||
BluetoothEventManager.UnknownBleEvent = new KEvent(context.Device.System.KernelContext);
|
BluetoothEventManager.UnknownBleEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.UnknownBleEvent.ReadableEvent, out BluetoothEventManager.UnknownBleEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.UnknownBleEvent.ReadableEvent, out BluetoothEventManager.UnknownBleEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
|
||||||
{
|
{
|
||||||
BluetoothEventManager.RegisterBleEvent = new KEvent(context.Device.System.KernelContext);
|
BluetoothEventManager.RegisterBleEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.RegisterBleEvent.ReadableEvent, out BluetoothEventManager.RegisterBleEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.RegisterBleEvent.ReadableEvent, out BluetoothEventManager.RegisterBleEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
// AcquireBleScanEvent() -> (byte<1>, handle<copy>)
|
// AcquireBleScanEvent() -> (byte<1>, handle<copy>)
|
||||||
public ResultCode AcquireBleScanEvent(ServiceCtx context)
|
public ResultCode AcquireBleScanEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
if (_bleScanEventHandle == 0)
|
if (_bleScanEventHandle == 0)
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
result = context.Process.HandleTable.GenerateHandle(_bleScanEvent.ReadableEvent, out _bleScanEventHandle);
|
result = context.Process.HandleTable.GenerateHandle(_bleScanEvent.ReadableEvent, out _bleScanEventHandle);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
||||||
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
||||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleScanEventHandle);
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleScanEventHandle);
|
||||||
|
|
||||||
context.ResponseData.Write(result == KernelResult.Success ? 1 : 0);
|
context.ResponseData.Write(result == Result.Success ? 1 : 0);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
// AcquireBleConnectionEvent() -> (byte<1>, handle<copy>)
|
// AcquireBleConnectionEvent() -> (byte<1>, handle<copy>)
|
||||||
public ResultCode AcquireBleConnectionEvent(ServiceCtx context)
|
public ResultCode AcquireBleConnectionEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
if (_bleConnectionEventHandle == 0)
|
if (_bleConnectionEventHandle == 0)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
result = context.Process.HandleTable.GenerateHandle(_bleConnectionEvent.ReadableEvent, out _bleConnectionEventHandle);
|
result = context.Process.HandleTable.GenerateHandle(_bleConnectionEvent.ReadableEvent, out _bleConnectionEventHandle);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
||||||
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
||||||
|
@ -68,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleConnectionEventHandle);
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleConnectionEventHandle);
|
||||||
|
|
||||||
context.ResponseData.Write(result == KernelResult.Success ? 1 : 0);
|
context.ResponseData.Write(result == Result.Success ? 1 : 0);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
// AcquireBleServiceDiscoveryEvent() -> (byte<1>, handle<copy>)
|
// AcquireBleServiceDiscoveryEvent() -> (byte<1>, handle<copy>)
|
||||||
public ResultCode AcquireBleServiceDiscoveryEvent(ServiceCtx context)
|
public ResultCode AcquireBleServiceDiscoveryEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
if (_bleServiceDiscoveryEventHandle == 0)
|
if (_bleServiceDiscoveryEventHandle == 0)
|
||||||
{
|
{
|
||||||
|
@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
result = context.Process.HandleTable.GenerateHandle(_bleServiceDiscoveryEvent.ReadableEvent, out _bleServiceDiscoveryEventHandle);
|
result = context.Process.HandleTable.GenerateHandle(_bleServiceDiscoveryEvent.ReadableEvent, out _bleServiceDiscoveryEventHandle);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
||||||
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
||||||
|
@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleServiceDiscoveryEventHandle);
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleServiceDiscoveryEventHandle);
|
||||||
|
|
||||||
context.ResponseData.Write(result == KernelResult.Success ? 1 : 0);
|
context.ResponseData.Write(result == Result.Success ? 1 : 0);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
// AcquireBleMtuConfigEvent() -> (byte<1>, handle<copy>)
|
// AcquireBleMtuConfigEvent() -> (byte<1>, handle<copy>)
|
||||||
public ResultCode AcquireBleMtuConfigEvent(ServiceCtx context)
|
public ResultCode AcquireBleMtuConfigEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
if (_bleMtuConfigEventHandle == 0)
|
if (_bleMtuConfigEventHandle == 0)
|
||||||
{
|
{
|
||||||
|
@ -111,7 +111,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
result = context.Process.HandleTable.GenerateHandle(_bleMtuConfigEvent.ReadableEvent, out _bleMtuConfigEventHandle);
|
result = context.Process.HandleTable.GenerateHandle(_bleMtuConfigEvent.ReadableEvent, out _bleMtuConfigEventHandle);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
// NOTE: We use a Logging instead of an exception because the call return a boolean if succeed or not.
|
||||||
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
Logger.Error?.Print(LogClass.ServiceBsd, "Out of handles!");
|
||||||
|
@ -120,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
|
||||||
|
|
||||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleMtuConfigEventHandle);
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_bleMtuConfigEventHandle);
|
||||||
|
|
||||||
context.ResponseData.Write(result == KernelResult.Success ? 1 : 0);
|
context.ResponseData.Write(result == Result.Success ? 1 : 0);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,11 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.FriendService;
|
using Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.FriendService;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
||||||
|
@ -33,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
||||||
_completionEvent = new KEvent(context.Device.System.KernelContext);
|
_completionEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_completionEvent.ReadableEvent, out int completionEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_completionEvent.ReadableEvent, out int completionEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.NotificationService;
|
using Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.NotificationService;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
||||||
{
|
{
|
||||||
if (_notificationEventHandle == 0)
|
if (_notificationEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_notificationEvent.ReadableEvent, out _notificationEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_notificationEvent.ReadableEvent, out _notificationEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
|
namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
|
||||||
|
@ -21,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
|
||||||
{
|
{
|
||||||
if (_hidSharedMemHandle == 0)
|
if (_hidSharedMemHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_hidSharedMem, out _hidSharedMemHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_hidSharedMem, out _hidSharedMemHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid.Types;
|
using Ryujinx.HLE.HOS.Services.Hid.Types;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
|
using Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
@ -170,7 +170,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
{
|
{
|
||||||
long xpadId = context.RequestData.ReadInt64();
|
long xpadId = context.RequestData.ReadInt64();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_xpadIdEvent.ReadableEvent, out _xpadIdEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_xpadIdEvent.ReadableEvent, out _xpadIdEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -761,7 +761,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
long npadStyleSet = context.RequestData.ReadInt64();
|
long npadStyleSet = context.RequestData.ReadInt64();
|
||||||
|
|
||||||
KEvent evnt = context.Device.Hid.Npads.GetStyleSetUpdateEvent(npadId);
|
KEvent evnt = context.Device.Hid.Npads.GetStyleSetUpdateEvent(npadId);
|
||||||
if (context.Process.HandleTable.GenerateHandle(evnt.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(evnt.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -1597,7 +1597,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
{
|
{
|
||||||
int palmaConnectionHandle = context.RequestData.ReadInt32();
|
int palmaConnectionHandle = context.RequestData.ReadInt32();
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_palmaOperationCompleteEvent.ReadableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_palmaOperationCompleteEvent.ReadableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid.Irs.Types;
|
using Ryujinx.HLE.HOS.Services.Hid.Irs.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Hid.Irs
|
namespace Ryujinx.HLE.HOS.Services.Hid.Irs
|
||||||
|
@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Irs
|
||||||
|
|
||||||
if (_irsensorSharedMemoryHandle == 0)
|
if (_irsensorSharedMemoryHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.IirsSharedMem, out _irsensorSharedMemoryHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.IirsSharedMem, out _irsensorSharedMemoryHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Ldn.Types;
|
using Ryujinx.HLE.HOS.Services.Ldn.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
||||||
{
|
{
|
||||||
if (_stateChangeEventHandle == 0)
|
if (_stateChangeEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_networkInterface.StateChangeEvent.ReadableEvent, out _stateChangeEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_networkInterface.StateChangeEvent.ReadableEvent, out _stateChangeEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid;
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
||||||
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
|
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -851,7 +851,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
||||||
{
|
{
|
||||||
context.Device.System.NfpDevices[i].ActivateEvent = new KEvent(context.Device.System.KernelContext);
|
context.Device.System.NfpDevices[i].ActivateEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.NfpDevices[i].ActivateEvent.ReadableEvent, out int activateEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.NfpDevices[i].ActivateEvent.ReadableEvent, out int activateEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -877,7 +877,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
||||||
{
|
{
|
||||||
context.Device.System.NfpDevices[i].DeactivateEvent = new KEvent(context.Device.System.KernelContext);
|
context.Device.System.NfpDevices[i].DeactivateEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.NfpDevices[i].DeactivateEvent.ReadableEvent, out int deactivateEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.NfpDevices[i].DeactivateEvent.ReadableEvent, out int deactivateEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -960,7 +960,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
||||||
{
|
{
|
||||||
_availabilityChangeEvent = new KEvent(context.Device.System.KernelContext);
|
_availabilityChangeEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(_availabilityChangeEvent.ReadableEvent, out int availabilityChangeEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_availabilityChangeEvent.ReadableEvent, out int availabilityChangeEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
{
|
{
|
||||||
if (_event0Handle == 0)
|
if (_event0Handle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out _event0Handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out _event0Handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
|
||||||
|
|
||||||
if (_event1Handle == 0)
|
if (_event1Handle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out _event1Handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out _event1Handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer.ShopServiceAccessor;
|
using Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer.ShopServiceAccessor;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer
|
namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer
|
||||||
|
@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServ
|
||||||
|
|
||||||
if (_eventHandle == 0)
|
if (_eventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService
|
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService
|
||||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService
|
||||||
// GetFinishNotificationEvent() -> handle<copy>
|
// GetFinishNotificationEvent() -> handle<copy>
|
||||||
public ResultCode GetFinishNotificationEvent(ServiceCtx context)
|
public ResultCode GetFinishNotificationEvent(ServiceCtx context)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_finishNotificationEvent.ReadableEvent, out int finishNotificationEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_finishNotificationEvent.ReadableEvent, out int finishNotificationEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
|
||||||
{
|
{
|
||||||
if (_addOnContentListChangedEventHandle == 0)
|
if (_addOnContentListChangedEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out _addOnContentListChangedEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out _addOnContentListChangedEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
|
namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
|
||||||
|
@ -38,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
|
||||||
// GetPurchasedEventReadableHandle() -> handle<copy, event>
|
// GetPurchasedEventReadableHandle() -> handle<copy, event>
|
||||||
public ResultCode GetPurchasedEventReadableHandle(ServiceCtx context)
|
public ResultCode GetPurchasedEventReadableHandle(ServiceCtx context)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_purchasedEvent.ReadableEvent, out int purchasedEventReadableHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_purchasedEvent.ReadableEvent, out int purchasedEventReadableHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
|
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
|
||||||
{
|
{
|
||||||
KEvent evnt = new KEvent(context.Device.System.KernelContext);
|
KEvent evnt = new KEvent(context.Device.System.KernelContext);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(evnt.ReadableEvent, out handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(evnt.ReadableEvent, out handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
using Ryujinx.Graphics.Gpu.Synchronization;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.Types;
|
using Ryujinx.HLE.HOS.Services.Nv.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
|
||||||
|
|
||||||
Event = new KEvent(system.KernelContext);
|
Event = new KEvent(system.KernelContext);
|
||||||
|
|
||||||
if (KernelStatic.GetCurrentProcess().HandleTable.GenerateHandle(Event.ReadableEvent, out EventHandle) != KernelResult.Success)
|
if (KernelStatic.GetCurrentProcess().HandleTable.GenerateHandle(Event.ReadableEvent, out EventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types;
|
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -99,7 +99,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
|
||||||
|
|
||||||
if (targetEvent != null)
|
if (targetEvent != null)
|
||||||
{
|
{
|
||||||
if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
|
if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Pcv.Clkrst.ClkrstManager;
|
using Ryujinx.HLE.HOS.Services.Pcv.Clkrst.ClkrstManager;
|
||||||
using Ryujinx.HLE.HOS.Services.Pcv.Types;
|
using Ryujinx.HLE.HOS.Services.Pcv.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Pcv.Clkrst
|
namespace Ryujinx.HLE.HOS.Services.Pcv.Clkrst
|
||||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Services.Pcv.Clkrst
|
||||||
{
|
{
|
||||||
if (_moduleStateTableEventHandle == 0)
|
if (_moduleStateTableEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.IirsSharedMem, out _moduleStateTableEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.IirsSharedMem, out _moduleStateTableEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Pm
|
namespace Ryujinx.HLE.HOS.Services.Pm
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Pm
|
||||||
|
|
||||||
KProcess process = KernelStatic.GetProcessByPid(pid);
|
KProcess process = KernelStatic.GetProcessByPid(pid);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(process, out int processHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(process, out int processHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new System.Exception("Out of handles!");
|
throw new System.Exception("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Ptm.Psm
|
namespace Ryujinx.HLE.HOS.Services.Ptm.Psm
|
||||||
{
|
{
|
||||||
|
@ -22,11 +22,11 @@ namespace Ryujinx.HLE.HOS.Services.Ptm.Psm
|
||||||
{
|
{
|
||||||
if (_stateChangeEventHandle == -1)
|
if (_stateChangeEventHandle == -1)
|
||||||
{
|
{
|
||||||
KernelResult resultCode = context.Process.HandleTable.GenerateHandle(_stateChangeEvent.ReadableEvent, out _stateChangeEventHandle);
|
Result resultCode = context.Process.HandleTable.GenerateHandle(_stateChangeEvent.ReadableEvent, out _stateChangeEventHandle);
|
||||||
|
|
||||||
if (resultCode != KernelResult.Success)
|
if (resultCode != Result.Success)
|
||||||
{
|
{
|
||||||
return (ResultCode)resultCode;
|
return (ResultCode)resultCode.ErrorCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -217,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
|
|
||||||
if (info.BssSize > 0)
|
if (info.BssSize > 0)
|
||||||
{
|
{
|
||||||
KernelResult bssMappingResult = memMgr.MapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize);
|
Result bssMappingResult = memMgr.MapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize);
|
||||||
|
|
||||||
if (bssMappingResult == KernelResult.InvalidMemState)
|
if (bssMappingResult == KernelResult.InvalidMemState)
|
||||||
{
|
{
|
||||||
|
@ -226,12 +226,12 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (bssMappingResult != KernelResult.Success)
|
else if (bssMappingResult != Result.Success)
|
||||||
{
|
{
|
||||||
memMgr.UnmapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize);
|
memMgr.UnmapProcessCodeMemory(nroMappedAddress + info.NroSize, info.BssAddress, info.BssSize);
|
||||||
memMgr.UnmapProcessCodeMemory(nroMappedAddress, info.NroAddress, info.NroSize);
|
memMgr.UnmapProcessCodeMemory(nroMappedAddress, info.NroAddress, info.NroSize);
|
||||||
|
|
||||||
return (ResultCode)bssMappingResult;
|
return (ResultCode)bssMappingResult.ErrorCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,15 +286,15 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KernelResult result = memMgr.MapProcessCodeMemory(targetAddress, baseAddress, size);
|
Result result = memMgr.MapProcessCodeMemory(targetAddress, baseAddress, size);
|
||||||
|
|
||||||
if (result == KernelResult.InvalidMemState)
|
if (result == KernelResult.InvalidMemState)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (result != KernelResult.Success)
|
else if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return (ResultCode)result;
|
return (ResultCode)result.ErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanAddGuardRegionsInProcess(process, targetAddress, size))
|
if (!CanAddGuardRegionsInProcess(process, targetAddress, size))
|
||||||
|
@ -313,11 +313,11 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KernelResult SetNroMemoryPermissions(KProcess process, IExecutable relocatableObject, ulong baseAddress)
|
private Result SetNroMemoryPermissions(KProcess process, IExecutable relocatableObject, ulong baseAddress)
|
||||||
{
|
{
|
||||||
ulong textStart = baseAddress + (ulong)relocatableObject.TextOffset;
|
ulong textStart = baseAddress + relocatableObject.TextOffset;
|
||||||
ulong roStart = baseAddress + (ulong)relocatableObject.RoOffset;
|
ulong roStart = baseAddress + relocatableObject.RoOffset;
|
||||||
ulong dataStart = baseAddress + (ulong)relocatableObject.DataOffset;
|
ulong dataStart = baseAddress + relocatableObject.DataOffset;
|
||||||
|
|
||||||
ulong bssStart = dataStart + (ulong)relocatableObject.Data.Length;
|
ulong bssStart = dataStart + (ulong)relocatableObject.Data.Length;
|
||||||
|
|
||||||
|
@ -329,18 +329,18 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
|
|
||||||
MemoryHelper.FillWithZeros(process.CpuMemory, bssStart, (int)(bssEnd - bssStart));
|
MemoryHelper.FillWithZeros(process.CpuMemory, bssStart, (int)(bssEnd - bssStart));
|
||||||
|
|
||||||
KernelResult result;
|
Result result;
|
||||||
|
|
||||||
result = process.MemoryManager.SetProcessMemoryPermission(textStart, roStart - textStart, KMemoryPermission.ReadAndExecute);
|
result = process.MemoryManager.SetProcessMemoryPermission(textStart, roStart - textStart, KMemoryPermission.ReadAndExecute);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = process.MemoryManager.SetProcessMemoryPermission(roStart, dataStart - roStart, KMemoryPermission.Read);
|
result = process.MemoryManager.SetProcessMemoryPermission(roStart, dataStart - roStart, KMemoryPermission.Read);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
ulong dataSize = (ulong)info.Executable.Data.Length;
|
ulong dataSize = (ulong)info.Executable.Data.Length;
|
||||||
ulong bssSize = (ulong)info.Executable.BssSize;
|
ulong bssSize = (ulong)info.Executable.BssSize;
|
||||||
|
|
||||||
KernelResult result = KernelResult.Success;
|
Result result = Result.Success;
|
||||||
|
|
||||||
if (info.Executable.BssSize != 0)
|
if (info.Executable.BssSize != 0)
|
||||||
{
|
{
|
||||||
|
@ -395,14 +395,14 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
bssSize);
|
bssSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
||||||
info.NroMappedAddress + textSize + roSize,
|
info.NroMappedAddress + textSize + roSize,
|
||||||
info.Executable.SourceAddress + textSize + roSize,
|
info.Executable.SourceAddress + textSize + roSize,
|
||||||
dataSize);
|
dataSize);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
||||||
info.NroMappedAddress,
|
info.NroMappedAddress,
|
||||||
|
@ -411,7 +411,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ResultCode)result;
|
return (ResultCode)result.ErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultCode IsInitialized(ulong pid)
|
private ResultCode IsInitialized(ulong pid)
|
||||||
|
@ -452,7 +452,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
result = (ResultCode)SetNroMemoryPermissions(_owner, info.Executable, nroMappedAddress);
|
result = (ResultCode)SetNroMemoryPermissions(_owner, info.Executable, nroMappedAddress).ErrorCode;
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Sdb.Pl.Types;
|
using Ryujinx.HLE.HOS.Services.Sdb.Pl.Types;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
|
namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
|
||||||
|
@ -67,7 +67,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
|
||||||
|
|
||||||
if (_fontSharedMemHandle == 0)
|
if (_fontSharedMemHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.FontSharedMem, out _fontSharedMemHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.FontSharedMem, out _fontSharedMemHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -129,7 +129,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
replyTargetHandle = 0;
|
replyTargetHandle = 0;
|
||||||
|
|
||||||
if (rc == KernelResult.Success && signaledIndex >= portHandles.Length)
|
if (rc == Result.Success && signaledIndex >= portHandles.Length)
|
||||||
{
|
{
|
||||||
// We got a IPC request, process it, pass to the appropriate service if needed.
|
// We got a IPC request, process it, pass to the appropriate service if needed.
|
||||||
int signaledHandle = handles[signaledIndex];
|
int signaledHandle = handles[signaledIndex];
|
||||||
|
@ -141,10 +141,10 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (rc == KernelResult.Success)
|
if (rc == Result.Success)
|
||||||
{
|
{
|
||||||
// We got a new connection, accept the session to allow servicing future requests.
|
// We got a new connection, accept the session to allow servicing future requests.
|
||||||
if (_context.Syscall.AcceptSession(out int serverSessionHandle, handles[signaledIndex]) == KernelResult.Success)
|
if (_context.Syscall.AcceptSession(out int serverSessionHandle, handles[signaledIndex]) == Result.Success)
|
||||||
{
|
{
|
||||||
IpcService obj = _ports[handles[signaledIndex]].Invoke();
|
IpcService obj = _ports[handles[signaledIndex]].Invoke();
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -72,14 +72,14 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
|
|
||||||
if (_registry.TryGetService(name, out KPort port))
|
if (_registry.TryGetService(name, out KPort port))
|
||||||
{
|
{
|
||||||
KernelResult result = port.EnqueueIncomingSession(session.ServerSession);
|
Result result = port.EnqueueIncomingSession(session.ServerSession);
|
||||||
|
|
||||||
if (result != KernelResult.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Session enqueue on port returned error \"{result}\".");
|
throw new InvalidOperationException($"Session enqueue on port returned error \"{result}\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
@ -182,14 +182,14 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
|
|
||||||
Logger.Info?.Print(LogClass.ServiceSm, $"Register \"{name}\".");
|
Logger.Info?.Print(LogClass.ServiceSm, $"Register \"{name}\".");
|
||||||
|
|
||||||
KPort port = new KPort(context.Device.System.KernelContext, maxSessions, isLight, 0);
|
KPort port = new KPort(context.Device.System.KernelContext, maxSessions, isLight, null);
|
||||||
|
|
||||||
if (!_registry.TryRegister(name, port))
|
if (!_registry.TryRegister(name, port))
|
||||||
{
|
{
|
||||||
return ResultCode.AlreadyRegistered;
|
return ResultCode.AlreadyRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(port.ServerPort, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(port.ServerPort, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
||||||
|
|
||||||
GetNativeHandle(binderId, typeId, out KReadableEvent readableEvent);
|
GetNativeHandle(binderId, typeId, out KReadableEvent readableEvent);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(readableEvent, out int handle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(readableEvent, out int handle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.StaticService;
|
using Ryujinx.HLE.HOS.Services.Time.StaticService;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -102,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
{
|
{
|
||||||
if (_timeSharedMemoryNativeHandle == 0)
|
if (_timeSharedMemoryNativeHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_timeManager.SharedMemory.GetSharedMemory(), out _timeSharedMemoryNativeHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_timeManager.SharedMemory.GetSharedMemory(), out _timeSharedMemoryNativeHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||||
using Ryujinx.HLE.Utilities;
|
using Ryujinx.HLE.Utilities;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
{
|
{
|
||||||
if (_automaticCorrectionEvent == 0)
|
if (_automaticCorrectionEvent == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(_timeManager.StandardUserSystemClock.GetAutomaticCorrectionReadableEvent(), out _automaticCorrectionEvent) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(_timeManager.StandardUserSystemClock.GetAutomaticCorrectionReadableEvent(), out _automaticCorrectionEvent) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
|
@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
|
|
||||||
_clockCore.RegisterOperationEvent(kEvent.WritableEvent);
|
_clockCore.RegisterOperationEvent(kEvent.WritableEvent);
|
||||||
|
|
||||||
if (context.Process.HandleTable.GenerateHandle(kEvent.ReadableEvent, out _operationEventReadableHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(kEvent.ReadableEvent, out _operationEventReadableHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||||
{
|
{
|
||||||
|
@ -471,7 +472,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
|
||||||
|
|
||||||
if (_vsyncEventHandle == 0)
|
if (_vsyncEventHandle == 0)
|
||||||
{
|
{
|
||||||
if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out _vsyncEventHandle) != KernelResult.Success)
|
if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out _vsyncEventHandle) != Result.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
|
<ProjectReference Include="..\Ryujinx.Horizon\Ryujinx.Horizon.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||||
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Ryujinx.HLE
|
||||||
public MemoryBlock Memory { get; }
|
public MemoryBlock Memory { get; }
|
||||||
public GpuContext Gpu { get; }
|
public GpuContext Gpu { get; }
|
||||||
public VirtualFileSystem FileSystem { get; }
|
public VirtualFileSystem FileSystem { get; }
|
||||||
public Horizon System { get; }
|
public HOS.Horizon System { get; }
|
||||||
public ApplicationLoader Application { get; }
|
public ApplicationLoader Application { get; }
|
||||||
public PerformanceStatistics Statistics { get; }
|
public PerformanceStatistics Statistics { get; }
|
||||||
public Hid Hid { get; }
|
public Hid Hid { get; }
|
||||||
|
@ -47,7 +47,7 @@ namespace Ryujinx.HLE
|
||||||
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
|
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
|
||||||
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
|
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
|
||||||
Gpu = new GpuContext(Configuration.GpuRenderer);
|
Gpu = new GpuContext(Configuration.GpuRenderer);
|
||||||
System = new Horizon(this);
|
System = new HOS.Horizon(this);
|
||||||
Statistics = new PerformanceStatistics();
|
Statistics = new PerformanceStatistics();
|
||||||
Hid = new Hid(this, System.HidStorage);
|
Hid = new Hid(this, System.HidStorage);
|
||||||
Application = new ApplicationLoader(this);
|
Application = new ApplicationLoader(this);
|
||||||
|
|
32
Ryujinx.Horizon.Common/ISyscallApi.cs
Normal file
32
Ryujinx.Horizon.Common/ISyscallApi.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Common
|
||||||
|
{
|
||||||
|
public interface ISyscallApi
|
||||||
|
{
|
||||||
|
Result SetHeapSize(out ulong address, ulong size);
|
||||||
|
|
||||||
|
void SleepThread(long timeout);
|
||||||
|
|
||||||
|
Result CloseHandle(int handle);
|
||||||
|
|
||||||
|
Result WaitSynchronization(out int handleIndex, ReadOnlySpan<int> handles, long timeout);
|
||||||
|
|
||||||
|
Result GetProcessId(out ulong pid, int handle);
|
||||||
|
|
||||||
|
Result ConnectToNamedPort(out int handle, string name);
|
||||||
|
Result SendSyncRequest(int handle);
|
||||||
|
Result CreateSession(out int serverSessionHandle, out int clientSessionHandle, bool isLight, string name);
|
||||||
|
Result AcceptSession(out int sessionHandle, int portHandle);
|
||||||
|
Result ReplyAndReceive(out int handleIndex, ReadOnlySpan<int> handles, int replyTargetHandle, long timeout);
|
||||||
|
|
||||||
|
Result CreateEvent(out int writableHandle, out int readableHandle);
|
||||||
|
Result SignalEvent(int handle);
|
||||||
|
Result ClearEvent(int handle);
|
||||||
|
Result ResetSignal(int handle);
|
||||||
|
|
||||||
|
Result CreatePort(out int serverPortHandle, out int clientPortHandle, int maxSessions, bool isLight, string name);
|
||||||
|
Result ManageNamedPort(out int handle, string name, int maxSessions);
|
||||||
|
Result ConnectToPort(out int clientSessionHandle, int clientPortHandle);
|
||||||
|
}
|
||||||
|
}
|
11
Ryujinx.Horizon.Common/IThreadContext.cs
Normal file
11
Ryujinx.Horizon.Common/IThreadContext.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Common
|
||||||
|
{
|
||||||
|
public interface IThreadContext
|
||||||
|
{
|
||||||
|
bool Running { get; }
|
||||||
|
|
||||||
|
ulong TlsAddress { get; }
|
||||||
|
}
|
||||||
|
}
|
25
Ryujinx.Horizon.Common/InvalidResultException.cs
Normal file
25
Ryujinx.Horizon.Common/InvalidResultException.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Common
|
||||||
|
{
|
||||||
|
class InvalidResultException : Exception
|
||||||
|
{
|
||||||
|
public InvalidResultException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidResultException(Result result) : base($"Unexpected result code {result} returned.")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidResultException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidResultException(string message, Exception innerException) : base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
39
Ryujinx.Horizon.Common/KernelResult.cs
Normal file
39
Ryujinx.Horizon.Common/KernelResult.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
namespace Ryujinx.Horizon.Common
|
||||||
|
{
|
||||||
|
public static class KernelResult
|
||||||
|
{
|
||||||
|
private const int ModuleId = 1;
|
||||||
|
|
||||||
|
public static Result SessionCountExceeded => new Result(ModuleId, 7);
|
||||||
|
public static Result InvalidCapability => new Result(ModuleId, 14);
|
||||||
|
public static Result ThreadNotStarted => new Result(ModuleId, 57);
|
||||||
|
public static Result ThreadTerminating => new Result(ModuleId, 59);
|
||||||
|
public static Result InvalidSize => new Result(ModuleId, 101);
|
||||||
|
public static Result InvalidAddress => new Result(ModuleId, 102);
|
||||||
|
public static Result OutOfResource => new Result(ModuleId, 103);
|
||||||
|
public static Result OutOfMemory => new Result(ModuleId, 104);
|
||||||
|
public static Result HandleTableFull => new Result(ModuleId, 105);
|
||||||
|
public static Result InvalidMemState => new Result(ModuleId, 106);
|
||||||
|
public static Result InvalidPermission => new Result(ModuleId, 108);
|
||||||
|
public static Result InvalidMemRange => new Result(ModuleId, 110);
|
||||||
|
public static Result InvalidPriority => new Result(ModuleId, 112);
|
||||||
|
public static Result InvalidCpuCore => new Result(ModuleId, 113);
|
||||||
|
public static Result InvalidHandle => new Result(ModuleId, 114);
|
||||||
|
public static Result UserCopyFailed => new Result(ModuleId, 115);
|
||||||
|
public static Result InvalidCombination => new Result(ModuleId, 116);
|
||||||
|
public static Result TimedOut => new Result(ModuleId, 117);
|
||||||
|
public static Result Cancelled => new Result(ModuleId, 118);
|
||||||
|
public static Result MaximumExceeded => new Result(ModuleId, 119);
|
||||||
|
public static Result InvalidEnumValue => new Result(ModuleId, 120);
|
||||||
|
public static Result NotFound => new Result(ModuleId, 121);
|
||||||
|
public static Result InvalidThread => new Result(ModuleId, 122);
|
||||||
|
public static Result PortRemoteClosed => new Result(ModuleId, 123);
|
||||||
|
public static Result InvalidState => new Result(ModuleId, 125);
|
||||||
|
public static Result ReservedValue => new Result(ModuleId, 126);
|
||||||
|
public static Result PortClosed => new Result(ModuleId, 131);
|
||||||
|
public static Result ResLimitExceeded => new Result(ModuleId, 132);
|
||||||
|
public static Result ReceiveListBroken => new Result(ModuleId, 258);
|
||||||
|
public static Result OutOfVaSpace => new Result(ModuleId, 259);
|
||||||
|
public static Result CmdBufferTooSmall => new Result(ModuleId, 260);
|
||||||
|
}
|
||||||
|
}
|
19
Ryujinx.Horizon.Common/OnScopeExit.cs
Normal file
19
Ryujinx.Horizon.Common/OnScopeExit.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Common
|
||||||
|
{
|
||||||
|
public struct OnScopeExit : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Action _action;
|
||||||
|
|
||||||
|
public OnScopeExit(Action action)
|
||||||
|
{
|
||||||
|
_action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_action();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
Ryujinx.Horizon.Common/Result.cs
Normal file
113
Ryujinx.Horizon.Common/Result.cs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Common
|
||||||
|
{
|
||||||
|
public struct Result : IEquatable<Result>
|
||||||
|
{
|
||||||
|
private const int ModuleBits = 9;
|
||||||
|
private const int DescriptionBits = 13;
|
||||||
|
private const int ModuleMax = 1 << ModuleBits;
|
||||||
|
private const int DescriptionMax = 1 << DescriptionBits;
|
||||||
|
|
||||||
|
public static Result Success { get; } = new Result(0, 0);
|
||||||
|
|
||||||
|
public int ErrorCode { get; }
|
||||||
|
|
||||||
|
public bool IsSuccess => ErrorCode == 0;
|
||||||
|
public bool IsFailure => ErrorCode != 0;
|
||||||
|
|
||||||
|
public int Module => ErrorCode & (ModuleMax - 1);
|
||||||
|
public int Description => (ErrorCode >> ModuleBits) & (DescriptionMax - 1);
|
||||||
|
|
||||||
|
public string PrintableResult => $"{2000 + Module:D4}-{Description:D4}";
|
||||||
|
|
||||||
|
public Result(int module, int description)
|
||||||
|
{
|
||||||
|
if ((uint)module >= ModuleMax)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(module));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uint)description >= DescriptionMax)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(description));
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode = module | (description << ModuleBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is Result result && result.Equals(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Result other)
|
||||||
|
{
|
||||||
|
return other.ErrorCode == ErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Result lhs, Result rhs)
|
||||||
|
{
|
||||||
|
return lhs.Equals(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Result lhs, Result rhs)
|
||||||
|
{
|
||||||
|
return !lhs.Equals(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool InRange(int minInclusive, int maxInclusive)
|
||||||
|
{
|
||||||
|
return (uint)(Description - minInclusive) <= (uint)(maxInclusive - minInclusive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AbortOnSuccess()
|
||||||
|
{
|
||||||
|
if (IsSuccess)
|
||||||
|
{
|
||||||
|
ThrowInvalidResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AbortOnFailure()
|
||||||
|
{
|
||||||
|
AbortUnless(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AbortUnless(Result result)
|
||||||
|
{
|
||||||
|
if (this != result)
|
||||||
|
{
|
||||||
|
ThrowInvalidResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AbortUnless(Result result, Result result2)
|
||||||
|
{
|
||||||
|
if (this != result && this != result2)
|
||||||
|
{
|
||||||
|
ThrowInvalidResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThrowInvalidResult()
|
||||||
|
{
|
||||||
|
throw new InvalidResultException(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (ResultNames.TryGet(ErrorCode, out string name))
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PrintableResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1701
Ryujinx.Horizon.Common/ResultNames.cs
Normal file
1701
Ryujinx.Horizon.Common/ResultNames.cs
Normal file
File diff suppressed because it is too large
Load diff
11
Ryujinx.Horizon.Common/Ryujinx.Horizon.Common.csproj
Normal file
11
Ryujinx.Horizon.Common/Ryujinx.Horizon.Common.csproj
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -24,10 +24,10 @@ namespace Ryujinx.Horizon.Generators
|
||||||
IncreaseIndentation();
|
IncreaseIndentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LeaveScope()
|
public void LeaveScope(string suffix = "")
|
||||||
{
|
{
|
||||||
DecreaseIndentation();
|
DecreaseIndentation();
|
||||||
AppendLine("}");
|
AppendLine("}" + suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IncreaseIndentation()
|
public void IncreaseIndentation()
|
||||||
|
|
18
Ryujinx.Horizon.Generators/Hipc/CommandArgType.cs
Normal file
18
Ryujinx.Horizon.Generators/Hipc/CommandArgType.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Ryujinx.Horizon.Generators.Hipc
|
||||||
|
{
|
||||||
|
enum CommandArgType : byte
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
|
||||||
|
Buffer,
|
||||||
|
InArgument,
|
||||||
|
InCopyHandle,
|
||||||
|
InMoveHandle,
|
||||||
|
InObject,
|
||||||
|
OutArgument,
|
||||||
|
OutCopyHandle,
|
||||||
|
OutMoveHandle,
|
||||||
|
OutObject,
|
||||||
|
ProcessId
|
||||||
|
}
|
||||||
|
}
|
17
Ryujinx.Horizon.Generators/Hipc/CommandInterface.cs
Normal file
17
Ryujinx.Horizon.Generators/Hipc/CommandInterface.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Generators.Hipc
|
||||||
|
{
|
||||||
|
class CommandInterface
|
||||||
|
{
|
||||||
|
public ClassDeclarationSyntax ClassDeclarationSyntax { get; }
|
||||||
|
public List<MethodDeclarationSyntax> CommandImplementations { get; }
|
||||||
|
|
||||||
|
public CommandInterface(ClassDeclarationSyntax classDeclarationSyntax)
|
||||||
|
{
|
||||||
|
ClassDeclarationSyntax = classDeclarationSyntax;
|
||||||
|
CommandImplementations = new List<MethodDeclarationSyntax>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
745
Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs
Normal file
745
Ryujinx.Horizon.Generators/Hipc/HipcGenerator.cs
Normal file
|
@ -0,0 +1,745 @@
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Generators.Hipc
|
||||||
|
{
|
||||||
|
[Generator]
|
||||||
|
class HipcGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
private const string ArgVariablePrefix = "arg";
|
||||||
|
private const string ResultVariableName = "result";
|
||||||
|
private const string IsBufferMapAliasVariableName = "isBufferMapAlias";
|
||||||
|
private const string InObjectsVariableName = "inObjects";
|
||||||
|
private const string OutObjectsVariableName = "outObjects";
|
||||||
|
private const string ResponseVariableName = "response";
|
||||||
|
private const string OutRawDataVariableName = "outRawData";
|
||||||
|
|
||||||
|
private const string TypeSystemReadOnlySpan = "System.ReadOnlySpan";
|
||||||
|
private const string TypeSystemSpan = "System.Span";
|
||||||
|
private const string TypeStructLayoutAttribute = "System.Runtime.InteropServices.StructLayoutAttribute";
|
||||||
|
|
||||||
|
public const string CommandAttributeName = "CmifCommandAttribute";
|
||||||
|
|
||||||
|
private const string TypeResult = "Ryujinx.Horizon.Common.Result";
|
||||||
|
private const string TypeBufferAttribute = "Ryujinx.Horizon.Sdk.Sf.BufferAttribute";
|
||||||
|
private const string TypeCopyHandleAttribute = "Ryujinx.Horizon.Sdk.Sf.CopyHandleAttribute";
|
||||||
|
private const string TypeMoveHandleAttribute = "Ryujinx.Horizon.Sdk.Sf.MoveHandleAttribute";
|
||||||
|
private const string TypeClientProcessIdAttribute = "Ryujinx.Horizon.Sdk.Sf.ClientProcessIdAttribute";
|
||||||
|
private const string TypeCommandAttribute = "Ryujinx.Horizon.Sdk.Sf." + CommandAttributeName;
|
||||||
|
private const string TypeIServiceObject = "Ryujinx.Horizon.Sdk.Sf.IServiceObject";
|
||||||
|
|
||||||
|
private enum Modifier
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Ref,
|
||||||
|
Out,
|
||||||
|
In
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct OutParameter
|
||||||
|
{
|
||||||
|
public readonly string Name;
|
||||||
|
public readonly string TypeName;
|
||||||
|
public readonly int Index;
|
||||||
|
public readonly CommandArgType Type;
|
||||||
|
|
||||||
|
public OutParameter(string name, string typeName, int index, CommandArgType type)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
TypeName = typeName;
|
||||||
|
Index = index;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
HipcSyntaxReceiver syntaxReceiver = (HipcSyntaxReceiver)context.SyntaxReceiver;
|
||||||
|
|
||||||
|
foreach (var commandInterface in syntaxReceiver.CommandInterfaces)
|
||||||
|
{
|
||||||
|
if (!NeedsIServiceObjectImplementation(context.Compilation, commandInterface.ClassDeclarationSyntax))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeGenerator generator = new CodeGenerator();
|
||||||
|
string className = commandInterface.ClassDeclarationSyntax.Identifier.ToString();
|
||||||
|
|
||||||
|
generator.AppendLine("using Ryujinx.Horizon.Common;");
|
||||||
|
generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf;");
|
||||||
|
generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Cmif;");
|
||||||
|
generator.AppendLine("using Ryujinx.Horizon.Sdk.Sf.Hipc;");
|
||||||
|
generator.AppendLine("using System;");
|
||||||
|
generator.AppendLine("using System.Collections.Generic;");
|
||||||
|
generator.AppendLine("using System.Runtime.CompilerServices;");
|
||||||
|
generator.AppendLine("using System.Runtime.InteropServices;");
|
||||||
|
generator.AppendLine();
|
||||||
|
generator.EnterScope($"namespace {GetNamespaceName(commandInterface.ClassDeclarationSyntax)}");
|
||||||
|
generator.EnterScope($"partial class {className}");
|
||||||
|
|
||||||
|
GenerateMethodTable(generator, context.Compilation, commandInterface);
|
||||||
|
|
||||||
|
foreach (var method in commandInterface.CommandImplementations)
|
||||||
|
{
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
GenerateMethod(generator, context.Compilation, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.LeaveScope();
|
||||||
|
generator.LeaveScope();
|
||||||
|
|
||||||
|
context.AddSource($"{className}.g.cs", generator.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetNamespaceName(SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
while (syntaxNode != null && !(syntaxNode is NamespaceDeclarationSyntax))
|
||||||
|
{
|
||||||
|
syntaxNode = syntaxNode.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntaxNode == null)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((NamespaceDeclarationSyntax)syntaxNode).Name.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateMethodTable(CodeGenerator generator, Compilation compilation, CommandInterface commandInterface)
|
||||||
|
{
|
||||||
|
generator.EnterScope($"public IReadOnlyDictionary<int, CommandHandler> GetCommandHandlers()");
|
||||||
|
generator.EnterScope($"return new Dictionary<int, CommandHandler>()");
|
||||||
|
|
||||||
|
foreach (var method in commandInterface.CommandImplementations)
|
||||||
|
{
|
||||||
|
foreach (var commandId in GetAttributeAguments(compilation, method, TypeCommandAttribute, 0))
|
||||||
|
{
|
||||||
|
string[] args = new string[method.ParameterList.Parameters.Count];
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
foreach (var parameter in method.ParameterList.Parameters)
|
||||||
|
{
|
||||||
|
string canonicalTypeName = GetCanonicalTypeNameWithGenericArguments(compilation, parameter.Type);
|
||||||
|
CommandArgType argType = GetCommandArgType(compilation, parameter);
|
||||||
|
|
||||||
|
string arg;
|
||||||
|
|
||||||
|
if (argType == CommandArgType.Buffer)
|
||||||
|
{
|
||||||
|
string bufferFlags = GetFirstAttributeAgument(compilation, parameter, TypeBufferAttribute, 0);
|
||||||
|
string bufferFixedSize = GetFirstAttributeAgument(compilation, parameter, TypeBufferAttribute, 1);
|
||||||
|
|
||||||
|
if (bufferFixedSize != null)
|
||||||
|
{
|
||||||
|
arg = $"new CommandArg({bufferFlags}, {bufferFixedSize})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arg = $"new CommandArg({bufferFlags})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (argType == CommandArgType.InArgument || argType == CommandArgType.OutArgument)
|
||||||
|
{
|
||||||
|
string alignment = GetTypeAlignmentExpression(compilation, parameter.Type);
|
||||||
|
|
||||||
|
arg = $"new CommandArg(CommandArgType.{argType}, Unsafe.SizeOf<{canonicalTypeName}>(), {alignment})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arg = $"new CommandArg(CommandArgType.{argType})";
|
||||||
|
}
|
||||||
|
|
||||||
|
args[index++] = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine($"{{ {commandId}, new CommandHandler({method.Identifier.Text}, {string.Join(", ", args)}) }},");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.LeaveScope(";");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GetAttributeAguments(Compilation compilation, SyntaxNode syntaxNode, string attributeName, int argIndex)
|
||||||
|
{
|
||||||
|
ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
|
||||||
|
|
||||||
|
foreach (var attribute in symbol.GetAttributes())
|
||||||
|
{
|
||||||
|
if (attribute.AttributeClass.ToDisplayString() == attributeName && (uint)argIndex < (uint)attribute.ConstructorArguments.Length)
|
||||||
|
{
|
||||||
|
yield return attribute.ConstructorArguments[argIndex].ToCSharpString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFirstAttributeAgument(Compilation compilation, SyntaxNode syntaxNode, string attributeName, int argIndex)
|
||||||
|
{
|
||||||
|
return GetAttributeAguments(compilation, syntaxNode, attributeName, argIndex).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateMethod(CodeGenerator generator, Compilation compilation, MethodDeclarationSyntax method)
|
||||||
|
{
|
||||||
|
int inObjectsCount = 0;
|
||||||
|
int outObjectsCount = 0;
|
||||||
|
int buffersCount = 0;
|
||||||
|
|
||||||
|
foreach (var parameter in method.ParameterList.Parameters)
|
||||||
|
{
|
||||||
|
if (IsObject(compilation, parameter))
|
||||||
|
{
|
||||||
|
if (IsIn(parameter))
|
||||||
|
{
|
||||||
|
inObjectsCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outObjectsCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsBuffer(compilation, parameter))
|
||||||
|
{
|
||||||
|
buffersCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.EnterScope($"private Result {method.Identifier.Text}(" +
|
||||||
|
"ref ServiceDispatchContext context, " +
|
||||||
|
"HipcCommandProcessor processor, " +
|
||||||
|
"ServerMessageRuntimeMetadata runtimeMetadata, " +
|
||||||
|
"ReadOnlySpan<byte> inRawData, " +
|
||||||
|
"ref Span<CmifOutHeader> outHeader)");
|
||||||
|
|
||||||
|
bool returnsResult = method.ReturnType != null && GetCanonicalTypeName(compilation, method.ReturnType) == TypeResult;
|
||||||
|
|
||||||
|
if (returnsResult || buffersCount != 0 || inObjectsCount != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"Result {ResultVariableName};");
|
||||||
|
|
||||||
|
if (buffersCount != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"bool[] {IsBufferMapAliasVariableName} = new bool[{method.ParameterList.Parameters.Count}];");
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
generator.AppendLine($"{ResultVariableName} = processor.ProcessBuffers(ref context, {IsBufferMapAliasVariableName}, runtimeMetadata);");
|
||||||
|
generator.EnterScope($"if ({ResultVariableName}.IsFailure)");
|
||||||
|
generator.AppendLine($"return {ResultVariableName};");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<OutParameter> outParameters = new List<OutParameter>();
|
||||||
|
|
||||||
|
string[] args = new string[method.ParameterList.Parameters.Count];
|
||||||
|
|
||||||
|
if (inObjectsCount != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"var {InObjectsVariableName} = new IServiceObject[{inObjectsCount}];");
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
generator.AppendLine($"{ResultVariableName} = processor.GetInObjects(context.Processor, {InObjectsVariableName});");
|
||||||
|
generator.EnterScope($"if ({ResultVariableName}.IsFailure)");
|
||||||
|
generator.AppendLine($"return {ResultVariableName};");
|
||||||
|
generator.LeaveScope();
|
||||||
|
generator.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outObjectsCount != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"var {OutObjectsVariableName} = new IServiceObject[{outObjectsCount}];");
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
int inCopyHandleIndex = 0;
|
||||||
|
int inMoveHandleIndex = 0;
|
||||||
|
int inObjectIndex = 0;
|
||||||
|
|
||||||
|
foreach (var parameter in method.ParameterList.Parameters)
|
||||||
|
{
|
||||||
|
string name = parameter.Identifier.Text;
|
||||||
|
string argName = GetPrefixedArgName(name);
|
||||||
|
string canonicalTypeName = GetCanonicalTypeNameWithGenericArguments(compilation, parameter.Type);
|
||||||
|
CommandArgType argType = GetCommandArgType(compilation, parameter);
|
||||||
|
Modifier modifier = GetModifier(parameter);
|
||||||
|
bool isNonSpanBuffer = false;
|
||||||
|
|
||||||
|
if (modifier == Modifier.Out)
|
||||||
|
{
|
||||||
|
if (IsNonSpanOutBuffer(compilation, parameter))
|
||||||
|
{
|
||||||
|
generator.AppendLine($"using var {argName} = CommandSerialization.GetWritableRegion(processor.GetBufferRange({index}));");
|
||||||
|
|
||||||
|
argName = $"out {GenerateSpanCastElement0(canonicalTypeName, $"{argName}.Memory.Span")}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outParameters.Add(new OutParameter(argName, canonicalTypeName, index, argType));
|
||||||
|
|
||||||
|
argName = $"out {canonicalTypeName} {argName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string value = $"default({canonicalTypeName})";
|
||||||
|
|
||||||
|
switch (argType)
|
||||||
|
{
|
||||||
|
case CommandArgType.InArgument:
|
||||||
|
value = $"CommandSerialization.DeserializeArg<{canonicalTypeName}>(inRawData, processor.GetInArgOffset({index}))";
|
||||||
|
break;
|
||||||
|
case CommandArgType.InCopyHandle:
|
||||||
|
value = $"CommandSerialization.DeserializeCopyHandle(ref context, {inCopyHandleIndex++})";
|
||||||
|
break;
|
||||||
|
case CommandArgType.InMoveHandle:
|
||||||
|
value = $"CommandSerialization.DeserializeMoveHandle(ref context, {inMoveHandleIndex++})";
|
||||||
|
break;
|
||||||
|
case CommandArgType.ProcessId:
|
||||||
|
value = "CommandSerialization.DeserializeClientProcessId(ref context)";
|
||||||
|
break;
|
||||||
|
case CommandArgType.InObject:
|
||||||
|
value = $"{InObjectsVariableName}[{inObjectIndex++}]";
|
||||||
|
break;
|
||||||
|
case CommandArgType.Buffer:
|
||||||
|
if (IsReadOnlySpan(compilation, parameter))
|
||||||
|
{
|
||||||
|
string spanGenericTypeName = GetCanonicalTypeNameOfGenericArgument(compilation, parameter.Type, 0);
|
||||||
|
value = GenerateSpanCast(spanGenericTypeName, $"CommandSerialization.GetReadOnlySpan(processor.GetBufferRange({index}))");
|
||||||
|
}
|
||||||
|
else if (IsSpan(compilation, parameter))
|
||||||
|
{
|
||||||
|
value = $"CommandSerialization.GetWritableRegion(processor.GetBufferRange({index}))";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = $"CommandSerialization.GetRef<{canonicalTypeName}>(processor.GetBufferRange({index}))";
|
||||||
|
isNonSpanBuffer = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSpan(compilation, parameter))
|
||||||
|
{
|
||||||
|
generator.AppendLine($"using var {argName} = {value};");
|
||||||
|
|
||||||
|
string spanGenericTypeName = GetCanonicalTypeNameOfGenericArgument(compilation, parameter.Type, 0);
|
||||||
|
argName = GenerateSpanCast(spanGenericTypeName, $"{argName}.Memory.Span"); ;
|
||||||
|
}
|
||||||
|
else if (isNonSpanBuffer)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"ref var {argName} = ref {value};");
|
||||||
|
}
|
||||||
|
else if (argType == CommandArgType.InObject)
|
||||||
|
{
|
||||||
|
generator.EnterScope($"if (!({value} is {canonicalTypeName} {argName}))");
|
||||||
|
generator.AppendLine("return SfResult.InvalidInObject;");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generator.AppendLine($"var {argName} = {value};");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifier == Modifier.Ref)
|
||||||
|
{
|
||||||
|
argName = $"ref {argName}";
|
||||||
|
}
|
||||||
|
else if (modifier == Modifier.In)
|
||||||
|
{
|
||||||
|
argName = $"in {argName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
args[index++] = argName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Length - outParameters.Count > 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnsResult)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"{ResultVariableName} = {method.Identifier.Text}({string.Join(", ", args)});");
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
generator.AppendLine($"Span<byte> {OutRawDataVariableName};");
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
generator.EnterScope($"if ({ResultVariableName}.IsFailure)");
|
||||||
|
generator.AppendLine($"context.Processor.PrepareForErrorReply(ref context, out {OutRawDataVariableName}, runtimeMetadata);");
|
||||||
|
generator.AppendLine($"CommandHandler.GetCmifOutHeaderPointer(ref outHeader, ref {OutRawDataVariableName});");
|
||||||
|
generator.AppendLine($"return {ResultVariableName};");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generator.AppendLine($"{method.Identifier.Text}({string.Join(", ", args)});");
|
||||||
|
|
||||||
|
generator.AppendLine();
|
||||||
|
generator.AppendLine($"Span<byte> {OutRawDataVariableName};");
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
generator.AppendLine($"var {ResponseVariableName} = context.Processor.PrepareForReply(ref context, out {OutRawDataVariableName}, runtimeMetadata);");
|
||||||
|
generator.AppendLine($"CommandHandler.GetCmifOutHeaderPointer(ref outHeader, ref {OutRawDataVariableName});");
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
generator.EnterScope($"if ({OutRawDataVariableName}.Length < processor.OutRawDataSize)");
|
||||||
|
generator.AppendLine("return SfResult.InvalidOutRawSize;");
|
||||||
|
generator.LeaveScope();
|
||||||
|
|
||||||
|
if (outParameters.Count != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
int outCopyHandleIndex = 0;
|
||||||
|
int outMoveHandleIndex = outObjectsCount;
|
||||||
|
int outObjectIndex = 0;
|
||||||
|
|
||||||
|
for (int outIndex = 0; outIndex < outParameters.Count; outIndex++)
|
||||||
|
{
|
||||||
|
OutParameter outParameter = outParameters[outIndex];
|
||||||
|
|
||||||
|
switch (outParameter.Type)
|
||||||
|
{
|
||||||
|
case CommandArgType.OutArgument:
|
||||||
|
generator.AppendLine($"CommandSerialization.SerializeArg<{outParameter.TypeName}>({OutRawDataVariableName}, processor.GetOutArgOffset({outParameter.Index}), {outParameter.Name});");
|
||||||
|
break;
|
||||||
|
case CommandArgType.OutCopyHandle:
|
||||||
|
generator.AppendLine($"CommandSerialization.SerializeCopyHandle({ResponseVariableName}, {outCopyHandleIndex++}, {outParameter.Name});");
|
||||||
|
break;
|
||||||
|
case CommandArgType.OutMoveHandle:
|
||||||
|
generator.AppendLine($"CommandSerialization.SerializeMoveHandle({ResponseVariableName}, {outMoveHandleIndex++}, {outParameter.Name});");
|
||||||
|
break;
|
||||||
|
case CommandArgType.OutObject:
|
||||||
|
generator.AppendLine($"{OutObjectsVariableName}[{outObjectIndex++}] = {outParameter.Name};");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine();
|
||||||
|
|
||||||
|
if (outObjectsCount != 0 || buffersCount != 0)
|
||||||
|
{
|
||||||
|
if (outObjectsCount != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"processor.SetOutObjects(ref context, {ResponseVariableName}, {OutObjectsVariableName});");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffersCount != 0)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"processor.SetOutBuffers({ResponseVariableName}, {IsBufferMapAliasVariableName});");
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine("return Result.Success;");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetPrefixedArgName(string name)
|
||||||
|
{
|
||||||
|
return ArgVariablePrefix + name[0].ToString().ToUpperInvariant() + name.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetCanonicalTypeNameOfGenericArgument(Compilation compilation, SyntaxNode syntaxNode, int argIndex)
|
||||||
|
{
|
||||||
|
if (syntaxNode is GenericNameSyntax genericNameSyntax)
|
||||||
|
{
|
||||||
|
if ((uint)argIndex < (uint)genericNameSyntax.TypeArgumentList.Arguments.Count)
|
||||||
|
{
|
||||||
|
return GetCanonicalTypeNameWithGenericArguments(compilation, genericNameSyntax.TypeArgumentList.Arguments[argIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetCanonicalTypeName(compilation, syntaxNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetCanonicalTypeNameWithGenericArguments(Compilation compilation, SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
|
||||||
|
return typeInfo.Type.ToDisplayString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetCanonicalTypeName(Compilation compilation, SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
|
||||||
|
string typeName = typeInfo.Type.ToDisplayString();
|
||||||
|
|
||||||
|
int genericArgsStartIndex = typeName.IndexOf('<');
|
||||||
|
if (genericArgsStartIndex >= 0)
|
||||||
|
{
|
||||||
|
return typeName.Substring(0, genericArgsStartIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SpecialType GetSpecialTypeName(Compilation compilation, SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
|
||||||
|
return typeInfo.Type.SpecialType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTypeAlignmentExpression(Compilation compilation, SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
|
||||||
|
|
||||||
|
// Since there's no way to get the alignment for a arbitrary type here, let's assume that all
|
||||||
|
// "special" types are primitive types aligned to their own length.
|
||||||
|
// Otherwise, assume that the type is a custom struct, that either defines an explicit alignment
|
||||||
|
// or has an alignment of 1 which is the lowest possible value.
|
||||||
|
if (typeInfo.Type.SpecialType == SpecialType.None)
|
||||||
|
{
|
||||||
|
string pack = GetTypeFirstNamedAttributeAgument(compilation, syntaxNode, TypeStructLayoutAttribute, "Pack");
|
||||||
|
return pack ?? "1";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $"Unsafe.SizeOf<{typeInfo.Type.ToDisplayString()}>()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTypeFirstNamedAttributeAgument(Compilation compilation, SyntaxNode syntaxNode, string attributeName, string argName)
|
||||||
|
{
|
||||||
|
ISymbol symbol = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode).Type;
|
||||||
|
|
||||||
|
foreach (var attribute in symbol.GetAttributes())
|
||||||
|
{
|
||||||
|
if (attribute.AttributeClass.ToDisplayString() == attributeName)
|
||||||
|
{
|
||||||
|
foreach (var kv in attribute.NamedArguments)
|
||||||
|
{
|
||||||
|
if (kv.Key == argName)
|
||||||
|
{
|
||||||
|
return kv.Value.ToCSharpString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CommandArgType GetCommandArgType(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
CommandArgType type = CommandArgType.Invalid;
|
||||||
|
|
||||||
|
if (IsIn(parameter))
|
||||||
|
{
|
||||||
|
if (IsArgument(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.InArgument;
|
||||||
|
}
|
||||||
|
else if (IsBuffer(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.Buffer;
|
||||||
|
}
|
||||||
|
else if (IsCopyHandle(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.InCopyHandle;
|
||||||
|
}
|
||||||
|
else if (IsMoveHandle(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.InMoveHandle;
|
||||||
|
}
|
||||||
|
else if (IsObject(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.InObject;
|
||||||
|
}
|
||||||
|
else if (IsProcessId(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.ProcessId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsOut(parameter))
|
||||||
|
{
|
||||||
|
if (IsArgument(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.OutArgument;
|
||||||
|
}
|
||||||
|
else if (IsNonSpanOutBuffer(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.Buffer;
|
||||||
|
}
|
||||||
|
else if (IsCopyHandle(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.OutCopyHandle;
|
||||||
|
}
|
||||||
|
else if (IsMoveHandle(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.OutMoveHandle;
|
||||||
|
}
|
||||||
|
else if (IsObject(compilation, parameter))
|
||||||
|
{
|
||||||
|
type = CommandArgType.OutObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsArgument(Compilation compilation,ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return !IsBuffer(compilation, parameter) &&
|
||||||
|
!IsHandle(compilation, parameter) &&
|
||||||
|
!IsObject(compilation, parameter) &&
|
||||||
|
!IsProcessId(compilation, parameter) &&
|
||||||
|
IsUnmanagedType(compilation, parameter.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsBuffer(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return HasAttribute(compilation, parameter, TypeBufferAttribute) &&
|
||||||
|
IsValidTypeForBuffer(compilation, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsNonSpanOutBuffer(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return HasAttribute(compilation, parameter, TypeBufferAttribute) &&
|
||||||
|
IsUnmanagedType(compilation, parameter.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidTypeForBuffer(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return IsReadOnlySpan(compilation, parameter) ||
|
||||||
|
IsSpan(compilation, parameter) ||
|
||||||
|
IsUnmanagedType(compilation, parameter.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsUnmanagedType(Compilation compilation, SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
|
||||||
|
return typeInfo.Type.IsUnmanagedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsReadOnlySpan(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return GetCanonicalTypeName(compilation, parameter.Type) == TypeSystemReadOnlySpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSpan(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return GetCanonicalTypeName(compilation, parameter.Type) == TypeSystemSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsHandle(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return IsCopyHandle(compilation, parameter) || IsMoveHandle(compilation, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsCopyHandle(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return HasAttribute(compilation, parameter, TypeCopyHandleAttribute) &&
|
||||||
|
GetSpecialTypeName(compilation, parameter.Type) == SpecialType.System_Int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsMoveHandle(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return HasAttribute(compilation, parameter, TypeMoveHandleAttribute) &&
|
||||||
|
GetSpecialTypeName(compilation, parameter.Type) == SpecialType.System_Int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsObject(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
SyntaxNode syntaxNode = parameter.Type;
|
||||||
|
TypeInfo typeInfo = compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetTypeInfo(syntaxNode);
|
||||||
|
|
||||||
|
return typeInfo.Type.ToDisplayString() == TypeIServiceObject ||
|
||||||
|
typeInfo.Type.AllInterfaces.Any(x => x.ToDisplayString() == TypeIServiceObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsProcessId(Compilation compilation, ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return HasAttribute(compilation, parameter, TypeClientProcessIdAttribute) &&
|
||||||
|
GetSpecialTypeName(compilation, parameter.Type) == SpecialType.System_UInt64;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsIn(ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return !IsOut(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsOut(ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
return parameter.Modifiers.Any(SyntaxKind.OutKeyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Modifier GetModifier(ParameterSyntax parameter)
|
||||||
|
{
|
||||||
|
foreach (SyntaxToken syntaxToken in parameter.Modifiers)
|
||||||
|
{
|
||||||
|
if (syntaxToken.IsKind(SyntaxKind.RefKeyword))
|
||||||
|
{
|
||||||
|
return Modifier.Ref;
|
||||||
|
}
|
||||||
|
else if (syntaxToken.IsKind(SyntaxKind.OutKeyword))
|
||||||
|
{
|
||||||
|
return Modifier.Out;
|
||||||
|
}
|
||||||
|
else if (syntaxToken.IsKind(SyntaxKind.InKeyword))
|
||||||
|
{
|
||||||
|
return Modifier.In;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Modifier.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GenerateSpanCastElement0(string targetType, string input)
|
||||||
|
{
|
||||||
|
return $"{GenerateSpanCast(targetType, input)}[0]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GenerateSpanCast(string targetType, string input)
|
||||||
|
{
|
||||||
|
return $"MemoryMarshal.Cast<byte, {targetType}>({input})";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HasAttribute(Compilation compilation, ParameterSyntax parameterSyntax, string fullAttributeName)
|
||||||
|
{
|
||||||
|
foreach (var attributeList in parameterSyntax.AttributeLists)
|
||||||
|
{
|
||||||
|
foreach (var attribute in attributeList.Attributes)
|
||||||
|
{
|
||||||
|
if (GetCanonicalTypeName(compilation, attribute) == fullAttributeName)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool NeedsIServiceObjectImplementation(Compilation compilation, ClassDeclarationSyntax classDeclarationSyntax)
|
||||||
|
{
|
||||||
|
ITypeSymbol type = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree).GetDeclaredSymbol(classDeclarationSyntax);
|
||||||
|
var serviceObjectInterface = type.AllInterfaces.FirstOrDefault(x => x.ToDisplayString() == TypeIServiceObject);
|
||||||
|
var interfaceMember = serviceObjectInterface?.GetMembers().FirstOrDefault(x => x.Name == "GetCommandHandlers");
|
||||||
|
|
||||||
|
// Return true only if the class implements IServiceObject but does not actually implement the method
|
||||||
|
// that the interface defines, since this is the only case we want to handle, if the method already exists
|
||||||
|
// we have nothing to do.
|
||||||
|
return serviceObjectInterface != null && type.FindImplementationForInterfaceMember(interfaceMember) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
context.RegisterForSyntaxNotifications(() => new HipcSyntaxReceiver());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
Ryujinx.Horizon.Generators/Hipc/HipcSyntaxReceiver.cs
Normal file
59
Ryujinx.Horizon.Generators/Hipc/HipcSyntaxReceiver.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Generators.Hipc
|
||||||
|
{
|
||||||
|
class HipcSyntaxReceiver : ISyntaxReceiver
|
||||||
|
{
|
||||||
|
public List<CommandInterface> CommandInterfaces { get; }
|
||||||
|
|
||||||
|
public HipcSyntaxReceiver()
|
||||||
|
{
|
||||||
|
CommandInterfaces = new List<CommandInterface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
|
||||||
|
{
|
||||||
|
if (!classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword) ||
|
||||||
|
classDeclaration.BaseList == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandInterface commandInterface = new CommandInterface(classDeclaration);
|
||||||
|
|
||||||
|
foreach (var memberDeclaration in classDeclaration.Members)
|
||||||
|
{
|
||||||
|
if (memberDeclaration is MethodDeclarationSyntax methodDeclaration)
|
||||||
|
{
|
||||||
|
VisitMethod(commandInterface, methodDeclaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandInterfaces.Add(commandInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VisitMethod(CommandInterface commandInterface, MethodDeclarationSyntax methodDeclaration)
|
||||||
|
{
|
||||||
|
string attributeName = HipcGenerator.CommandAttributeName.Replace("Attribute", string.Empty);
|
||||||
|
|
||||||
|
if (methodDeclaration.AttributeLists.Count != 0)
|
||||||
|
{
|
||||||
|
foreach (var attributeList in methodDeclaration.AttributeLists)
|
||||||
|
{
|
||||||
|
if (attributeList.Attributes.Any(x => x.Name.ToString().Contains(attributeName)))
|
||||||
|
{
|
||||||
|
commandInterface.CommandImplementations.Add(methodDeclaration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
Ryujinx.Horizon.Kernel.Generators/CodeGenerator.cs
Normal file
58
Ryujinx.Horizon.Kernel.Generators/CodeGenerator.cs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.Generators
|
||||||
|
{
|
||||||
|
class CodeGenerator
|
||||||
|
{
|
||||||
|
private const string Indent = " ";
|
||||||
|
private readonly StringBuilder _sb;
|
||||||
|
private string _currentIndent;
|
||||||
|
|
||||||
|
public CodeGenerator()
|
||||||
|
{
|
||||||
|
_sb = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnterScope(string header = null)
|
||||||
|
{
|
||||||
|
if (header != null)
|
||||||
|
{
|
||||||
|
AppendLine(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendLine("{");
|
||||||
|
IncreaseIndentation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LeaveScope()
|
||||||
|
{
|
||||||
|
DecreaseIndentation();
|
||||||
|
AppendLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncreaseIndentation()
|
||||||
|
{
|
||||||
|
_currentIndent += Indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecreaseIndentation()
|
||||||
|
{
|
||||||
|
_currentIndent = _currentIndent.Substring(0, _currentIndent.Length - Indent.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AppendLine()
|
||||||
|
{
|
||||||
|
_sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AppendLine(string text)
|
||||||
|
{
|
||||||
|
_sb.AppendLine(_currentIndent + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return _sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,15 +25,17 @@ namespace Ryujinx.Horizon.Generators.Kernel
|
||||||
private const string TypeSystemUInt64 = "System.UInt64";
|
private const string TypeSystemUInt64 = "System.UInt64";
|
||||||
|
|
||||||
private const string NamespaceKernel = "Ryujinx.HLE.HOS.Kernel";
|
private const string NamespaceKernel = "Ryujinx.HLE.HOS.Kernel";
|
||||||
|
private const string NamespaceHorizonCommon = "Ryujinx.Horizon.Common";
|
||||||
private const string TypeSvcAttribute = NamespaceKernel + ".SupervisorCall.SvcAttribute";
|
private const string TypeSvcAttribute = NamespaceKernel + ".SupervisorCall.SvcAttribute";
|
||||||
private const string TypePointerSizedAttribute = NamespaceKernel + ".SupervisorCall.PointerSizedAttribute";
|
private const string TypePointerSizedAttribute = NamespaceKernel + ".SupervisorCall.PointerSizedAttribute";
|
||||||
|
private const string TypeResultName = "Result";
|
||||||
private const string TypeKernelResultName = "KernelResult";
|
private const string TypeKernelResultName = "KernelResult";
|
||||||
private const string TypeKernelResult = NamespaceKernel + ".Common." + TypeKernelResultName;
|
private const string TypeResult = NamespaceHorizonCommon + "." + TypeResultName;
|
||||||
private const string TypeExecutionContext = "IExecutionContext";
|
private const string TypeExecutionContext = "IExecutionContext";
|
||||||
|
|
||||||
private static readonly string[] _expectedResults = new string[]
|
private static readonly string[] _expectedResults = new string[]
|
||||||
{
|
{
|
||||||
$"{TypeKernelResultName}.Success",
|
$"{TypeResultName}.Success",
|
||||||
$"{TypeKernelResultName}.TimedOut",
|
$"{TypeKernelResultName}.TimedOut",
|
||||||
$"{TypeKernelResultName}.Cancelled",
|
$"{TypeKernelResultName}.Cancelled",
|
||||||
$"{TypeKernelResultName}.PortRemoteClosed",
|
$"{TypeKernelResultName}.PortRemoteClosed",
|
||||||
|
@ -133,6 +135,7 @@ namespace Ryujinx.Horizon.Generators.Kernel
|
||||||
generator.AppendLine($"using {NamespaceKernel}.Memory;");
|
generator.AppendLine($"using {NamespaceKernel}.Memory;");
|
||||||
generator.AppendLine($"using {NamespaceKernel}.Process;");
|
generator.AppendLine($"using {NamespaceKernel}.Process;");
|
||||||
generator.AppendLine($"using {NamespaceKernel}.Threading;");
|
generator.AppendLine($"using {NamespaceKernel}.Threading;");
|
||||||
|
generator.AppendLine($"using {NamespaceHorizonCommon};");
|
||||||
generator.AppendLine("using System;");
|
generator.AppendLine("using System;");
|
||||||
generator.AppendLine();
|
generator.AppendLine();
|
||||||
generator.EnterScope($"namespace {ClassNamespace}");
|
generator.EnterScope($"namespace {ClassNamespace}");
|
||||||
|
@ -183,7 +186,7 @@ namespace Ryujinx.Horizon.Generators.Kernel
|
||||||
|
|
||||||
private static void GenerateResultCheckHelper(CodeGenerator generator)
|
private static void GenerateResultCheckHelper(CodeGenerator generator)
|
||||||
{
|
{
|
||||||
generator.EnterScope($"private static bool {ResultCheckHelperName}({TypeKernelResultName} {ResultVariableName})");
|
generator.EnterScope($"private static bool {ResultCheckHelperName}({TypeResultName} {ResultVariableName})");
|
||||||
|
|
||||||
string[] expectedChecks = new string[_expectedResults.Length];
|
string[] expectedChecks = new string[_expectedResults.Length];
|
||||||
|
|
||||||
|
@ -266,19 +269,25 @@ namespace Ryujinx.Horizon.Generators.Kernel
|
||||||
|
|
||||||
GenerateLogPrintBeforeCall(generator, method.Identifier.Text, logInArgs);
|
GenerateLogPrintBeforeCall(generator, method.Identifier.Text, logInArgs);
|
||||||
|
|
||||||
string returnTypeName = method.ReturnType.ToString();
|
|
||||||
string argsList = string.Join(", ", args);
|
string argsList = string.Join(", ", args);
|
||||||
int returnRegisterIndex = 0;
|
int returnRegisterIndex = 0;
|
||||||
string result = null;
|
string result = null;
|
||||||
string canonicalReturnTypeName = null;
|
string canonicalReturnTypeName = null;
|
||||||
|
|
||||||
if (returnTypeName != "void")
|
if (method.ReturnType.ToString() != "void")
|
||||||
{
|
{
|
||||||
generator.AppendLine($"var {ResultVariableName} = syscall.{method.Identifier.Text}({argsList});");
|
generator.AppendLine($"var {ResultVariableName} = syscall.{method.Identifier.Text}({argsList});");
|
||||||
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (uint){ResultVariableName});");
|
|
||||||
|
|
||||||
canonicalReturnTypeName = GetCanonicalTypeName(compilation, method.ReturnType);
|
canonicalReturnTypeName = GetCanonicalTypeName(compilation, method.ReturnType);
|
||||||
|
|
||||||
|
if (canonicalReturnTypeName == TypeResult)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (uint){ResultVariableName}.ErrorCode);");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (uint){ResultVariableName});");
|
||||||
|
}
|
||||||
|
|
||||||
if (Is64BitInteger(canonicalReturnTypeName))
|
if (Is64BitInteger(canonicalReturnTypeName))
|
||||||
{
|
{
|
||||||
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (uint)({ResultVariableName} >> 32));");
|
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (uint)({ResultVariableName} >> 32));");
|
||||||
|
@ -358,8 +367,17 @@ namespace Ryujinx.Horizon.Generators.Kernel
|
||||||
if (method.ReturnType.ToString() != "void")
|
if (method.ReturnType.ToString() != "void")
|
||||||
{
|
{
|
||||||
generator.AppendLine($"var {ResultVariableName} = syscall.{method.Identifier.Text}({argsList});");
|
generator.AppendLine($"var {ResultVariableName} = syscall.{method.Identifier.Text}({argsList});");
|
||||||
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (ulong){ResultVariableName});");
|
|
||||||
canonicalReturnTypeName = GetCanonicalTypeName(compilation, method.ReturnType);
|
canonicalReturnTypeName = GetCanonicalTypeName(compilation, method.ReturnType);
|
||||||
|
|
||||||
|
if (canonicalReturnTypeName == TypeResult)
|
||||||
|
{
|
||||||
|
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (ulong){ResultVariableName}.ErrorCode);");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generator.AppendLine($"context.SetX({returnRegisterIndex++}, (ulong){ResultVariableName});");
|
||||||
|
}
|
||||||
|
|
||||||
result = GetFormattedLogValue(ResultVariableName, canonicalReturnTypeName);
|
result = GetFormattedLogValue(ResultVariableName, canonicalReturnTypeName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -433,7 +451,7 @@ namespace Ryujinx.Horizon.Generators.Kernel
|
||||||
log += $" = {result}";
|
log += $" = {result}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canonicalResultTypeName == TypeKernelResult)
|
if (canonicalResultTypeName == TypeResult)
|
||||||
{
|
{
|
||||||
generator.EnterScope($"if ({ResultCheckHelperName}({ResultVariableName}))");
|
generator.EnterScope($"if ({ResultCheckHelperName}({ResultVariableName}))");
|
||||||
GenerateLogPrint(generator, "Trace", "KernelSvc", log);
|
GenerateLogPrint(generator, "Trace", "KernelSvc", log);
|
|
@ -0,0 +1,15 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
143
Ryujinx.Horizon/HeapAllocator.cs
Normal file
143
Ryujinx.Horizon/HeapAllocator.cs
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon
|
||||||
|
{
|
||||||
|
class HeapAllocator
|
||||||
|
{
|
||||||
|
private const ulong InvalidAddress = ulong.MaxValue;
|
||||||
|
|
||||||
|
private struct Range : IComparable<Range>
|
||||||
|
{
|
||||||
|
public ulong Offset { get; }
|
||||||
|
public ulong Size { get; }
|
||||||
|
|
||||||
|
public Range(ulong offset, ulong size)
|
||||||
|
{
|
||||||
|
Offset = offset;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(Range other)
|
||||||
|
{
|
||||||
|
return Offset.CompareTo(other.Offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<Range> _freeRanges;
|
||||||
|
private ulong _currentHeapSize;
|
||||||
|
|
||||||
|
public HeapAllocator()
|
||||||
|
{
|
||||||
|
_freeRanges = new List<Range>();
|
||||||
|
_currentHeapSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong Allocate(ulong size, ulong alignment = 1UL)
|
||||||
|
{
|
||||||
|
ulong address = AllocateImpl(size, alignment);
|
||||||
|
|
||||||
|
if (address == InvalidAddress)
|
||||||
|
{
|
||||||
|
ExpandHeap(size + alignment - 1UL);
|
||||||
|
|
||||||
|
address = AllocateImpl(size, alignment);
|
||||||
|
|
||||||
|
Debug.Assert(address != InvalidAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExpandHeap(ulong expansionSize)
|
||||||
|
{
|
||||||
|
ulong oldHeapSize = _currentHeapSize;
|
||||||
|
ulong newHeapSize = BitUtils.AlignUp(oldHeapSize + expansionSize, 0x200000);
|
||||||
|
|
||||||
|
_currentHeapSize = newHeapSize;
|
||||||
|
|
||||||
|
HorizonStatic.Syscall.SetHeapSize(out ulong heapAddress, newHeapSize).AbortOnFailure();
|
||||||
|
|
||||||
|
Free(heapAddress + oldHeapSize, newHeapSize - oldHeapSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong AllocateImpl(ulong size, ulong alignment)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _freeRanges.Count; i++)
|
||||||
|
{
|
||||||
|
var range = _freeRanges[i];
|
||||||
|
|
||||||
|
ulong alignedOffset = BitUtils.AlignUp(range.Offset, alignment);
|
||||||
|
ulong sizeDelta = alignedOffset - range.Offset;
|
||||||
|
ulong usableSize = range.Size - sizeDelta;
|
||||||
|
|
||||||
|
if (sizeDelta < range.Size && usableSize >= size)
|
||||||
|
{
|
||||||
|
_freeRanges.RemoveAt(i);
|
||||||
|
|
||||||
|
if (sizeDelta != 0)
|
||||||
|
{
|
||||||
|
InsertFreeRange(range.Offset, sizeDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong endOffset = range.Offset + range.Size;
|
||||||
|
ulong remainingSize = endOffset - (alignedOffset + size);
|
||||||
|
if (remainingSize != 0)
|
||||||
|
{
|
||||||
|
InsertFreeRange(endOffset - remainingSize, remainingSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return alignedOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Free(ulong offset, ulong size)
|
||||||
|
{
|
||||||
|
InsertFreeRangeComingled(offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InsertFreeRange(ulong offset, ulong size)
|
||||||
|
{
|
||||||
|
var range = new Range(offset, size);
|
||||||
|
int index = _freeRanges.BinarySearch(range);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
index = ~index;
|
||||||
|
}
|
||||||
|
|
||||||
|
_freeRanges.Insert(index, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InsertFreeRangeComingled(ulong offset, ulong size)
|
||||||
|
{
|
||||||
|
ulong endOffset = offset + size;
|
||||||
|
var range = new Range(offset, size);
|
||||||
|
int index = _freeRanges.BinarySearch(range);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
index = ~index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < _freeRanges.Count && _freeRanges[index].Offset == endOffset)
|
||||||
|
{
|
||||||
|
endOffset = _freeRanges[index].Offset + _freeRanges[index].Size;
|
||||||
|
_freeRanges.RemoveAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index > 0 && _freeRanges[index - 1].Offset + _freeRanges[index - 1].Size == offset)
|
||||||
|
{
|
||||||
|
offset = _freeRanges[index - 1].Offset;
|
||||||
|
_freeRanges.RemoveAt(--index);
|
||||||
|
}
|
||||||
|
|
||||||
|
range = new Range(offset, endOffset - offset);
|
||||||
|
|
||||||
|
_freeRanges.Insert(index, range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.Horizon/HorizonOptions.cs
Normal file
12
Ryujinx.Horizon/HorizonOptions.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Horizon
|
||||||
|
{
|
||||||
|
public struct HorizonOptions
|
||||||
|
{
|
||||||
|
public bool IgnoreMissingServices { get; }
|
||||||
|
|
||||||
|
public HorizonOptions(bool ignoreMissingServices)
|
||||||
|
{
|
||||||
|
IgnoreMissingServices = ignoreMissingServices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
Ryujinx.Horizon/HorizonStatic.cs
Normal file
38
Ryujinx.Horizon/HorizonStatic.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
using Ryujinx.Memory;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon
|
||||||
|
{
|
||||||
|
static class HorizonStatic
|
||||||
|
{
|
||||||
|
[ThreadStatic]
|
||||||
|
private static HorizonOptions _options;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ISyscallApi _syscall;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static IVirtualMemoryManager _addressSpace;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static IThreadContext _threadContext;
|
||||||
|
|
||||||
|
public static HorizonOptions Options => _options;
|
||||||
|
public static ISyscallApi Syscall => _syscall;
|
||||||
|
public static IVirtualMemoryManager AddressSpace => _addressSpace;
|
||||||
|
public static IThreadContext ThreadContext => _threadContext;
|
||||||
|
|
||||||
|
public static void Register(
|
||||||
|
HorizonOptions options,
|
||||||
|
ISyscallApi syscallApi,
|
||||||
|
IVirtualMemoryManager addressSpace,
|
||||||
|
IThreadContext threadContext)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
_syscall = syscallApi;
|
||||||
|
_addressSpace = addressSpace;
|
||||||
|
_threadContext = threadContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
Ryujinx.Horizon/IService.cs
Normal file
7
Ryujinx.Horizon/IService.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Ryujinx.Horizon
|
||||||
|
{
|
||||||
|
interface IService
|
||||||
|
{
|
||||||
|
abstract static void Main();
|
||||||
|
}
|
||||||
|
}
|
54
Ryujinx.Horizon/LogManager/LmIpcServer.cs
Normal file
54
Ryujinx.Horizon/LogManager/LmIpcServer.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sm;
|
||||||
|
using Ryujinx.Horizon.Sm;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.LogManager
|
||||||
|
{
|
||||||
|
class LmIpcServer
|
||||||
|
{
|
||||||
|
private const int LogMaxSessionsCount = 42;
|
||||||
|
|
||||||
|
private const int PointerBufferSize = 0x400;
|
||||||
|
private const int MaxDomains = 31;
|
||||||
|
private const int MaxDomainObjects = 61;
|
||||||
|
|
||||||
|
private const int MaxPortsCount = 1;
|
||||||
|
|
||||||
|
private static readonly ManagerOptions _logManagerOptions = new ManagerOptions(
|
||||||
|
PointerBufferSize,
|
||||||
|
MaxDomains,
|
||||||
|
MaxDomainObjects,
|
||||||
|
false);
|
||||||
|
|
||||||
|
private static readonly ServiceName _logServiceName = ServiceName.Encode("lm");
|
||||||
|
|
||||||
|
private SmApi _sm;
|
||||||
|
private ServerManager _serverManager;
|
||||||
|
|
||||||
|
private LmLog _logServiceObject;
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
HeapAllocator allocator = new HeapAllocator();
|
||||||
|
|
||||||
|
_sm = new SmApi();
|
||||||
|
_sm.Initialize().AbortOnFailure();
|
||||||
|
|
||||||
|
_serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _logManagerOptions, LogMaxSessionsCount);
|
||||||
|
|
||||||
|
_logServiceObject = new LmLog();
|
||||||
|
|
||||||
|
_serverManager.RegisterObjectForServer(_logServiceObject, _logServiceName, LogMaxSessionsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServiceRequests()
|
||||||
|
{
|
||||||
|
_serverManager.ServiceRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shutdown()
|
||||||
|
{
|
||||||
|
_serverManager.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
Ryujinx.Horizon/LogManager/LmLog.cs
Normal file
19
Ryujinx.Horizon/LogManager/LmLog.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
using Ryujinx.Horizon.Sdk.Lm;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.LogManager
|
||||||
|
{
|
||||||
|
partial class LmLog : IServiceObject
|
||||||
|
{
|
||||||
|
public LogDestination LogDestination { get; set; } = LogDestination.TargetManager;
|
||||||
|
|
||||||
|
[CmifCommand(0)]
|
||||||
|
public Result OpenLogger(out LmLogger logger, [ClientProcessId] ulong clientProcessId)
|
||||||
|
{
|
||||||
|
logger = new LmLogger(this, clientProcessId);
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
173
Ryujinx.Horizon/LogManager/LmLogger.cs
Normal file
173
Ryujinx.Horizon/LogManager/LmLogger.cs
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Horizon.Common;
|
||||||
|
using Ryujinx.Horizon.Sdk.Lm;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf;
|
||||||
|
using Ryujinx.Horizon.Sdk.Sf.Hipc;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.Horizon.LogManager
|
||||||
|
{
|
||||||
|
partial class LmLogger : IServiceObject
|
||||||
|
{
|
||||||
|
private readonly LmLog _log;
|
||||||
|
private readonly ulong _clientProcessId;
|
||||||
|
|
||||||
|
private ref struct Reader
|
||||||
|
{
|
||||||
|
private ReadOnlySpan<byte> _message;
|
||||||
|
|
||||||
|
public int Length => _message.Length;
|
||||||
|
|
||||||
|
public Reader(ReadOnlySpan<byte> message)
|
||||||
|
{
|
||||||
|
_message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Read<T>() where T : unmanaged
|
||||||
|
{
|
||||||
|
T value = MemoryMarshal.Cast<byte, T>(_message)[0];
|
||||||
|
|
||||||
|
_message = _message.Slice(Unsafe.SizeOf<T>());
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlySpan<byte> GetSpan(int size)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> data = _message.Slice(0, size);
|
||||||
|
|
||||||
|
_message = _message.Slice(size);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Skip(int size)
|
||||||
|
{
|
||||||
|
_message = _message.Slice(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LmLogger(LmLog log, ulong clientProcessId)
|
||||||
|
{
|
||||||
|
_log = log;
|
||||||
|
_clientProcessId = clientProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CmifCommand(0)]
|
||||||
|
public Result Log([Buffer(HipcBufferFlags.In | HipcBufferFlags.AutoSelect)] Span<byte> message)
|
||||||
|
{
|
||||||
|
if (!SetProcessId(message, _clientProcessId))
|
||||||
|
{
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Guest?.Print(LogClass.ServiceLm, LogImpl(message));
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CmifCommand(1)]
|
||||||
|
public Result SetDestination(LogDestination destination)
|
||||||
|
{
|
||||||
|
_log.LogDestination = destination;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool SetProcessId(Span<byte> message, ulong processId)
|
||||||
|
{
|
||||||
|
ref LogPacketHeader header = ref MemoryMarshal.Cast<byte, LogPacketHeader>(message)[0];
|
||||||
|
|
||||||
|
uint expectedMessageSize = (uint)Unsafe.SizeOf<LogPacketHeader>() + header.PayloadSize;
|
||||||
|
|
||||||
|
if (expectedMessageSize != (uint)message.Length)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.ServiceLm, $"Invalid message size (expected 0x{expectedMessageSize:X} but got 0x{message.Length:X}).");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.ProcessId = processId;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string LogImpl(ReadOnlySpan<byte> message)
|
||||||
|
{
|
||||||
|
Reader reader = new Reader(message);
|
||||||
|
|
||||||
|
LogPacketHeader header = reader.Read<LogPacketHeader>();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.AppendLine($"Guest Log:\n Log level: {header.Severity}");
|
||||||
|
|
||||||
|
while (reader.Length > 0)
|
||||||
|
{
|
||||||
|
int type = ReadUleb128(ref reader);
|
||||||
|
int size = ReadUleb128(ref reader);
|
||||||
|
|
||||||
|
LogDataChunkKey field = (LogDataChunkKey)type;
|
||||||
|
|
||||||
|
string fieldStr = string.Empty;
|
||||||
|
|
||||||
|
if (field == LogDataChunkKey.Start)
|
||||||
|
{
|
||||||
|
reader.Skip(size);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (field == LogDataChunkKey.Stop)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (field == LogDataChunkKey.Line)
|
||||||
|
{
|
||||||
|
fieldStr = $"{field}: {reader.Read<int>()}";
|
||||||
|
}
|
||||||
|
else if (field == LogDataChunkKey.DropCount)
|
||||||
|
{
|
||||||
|
fieldStr = $"{field}: {reader.Read<long>()}";
|
||||||
|
}
|
||||||
|
else if (field == LogDataChunkKey.Time)
|
||||||
|
{
|
||||||
|
fieldStr = $"{field}: {reader.Read<long>()}s";
|
||||||
|
}
|
||||||
|
else if (field < LogDataChunkKey.Count)
|
||||||
|
{
|
||||||
|
fieldStr = $"{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fieldStr = $"Field{field}: '{Encoding.UTF8.GetString(reader.GetSpan(size)).TrimEnd()}'";
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine($" {fieldStr}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ReadUleb128(ref Reader reader)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
byte encoded;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
encoded = reader.Read<byte>();
|
||||||
|
|
||||||
|
result += (encoded & 0x7F) << (7 * count);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
} while ((encoded & 0x80) != 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
Ryujinx.Horizon/LogManager/LmMain.cs
Normal file
14
Ryujinx.Horizon/LogManager/LmMain.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
namespace Ryujinx.Horizon.LogManager
|
||||||
|
{
|
||||||
|
class LmMain : IService
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
LmIpcServer ipcServer = new LmIpcServer();
|
||||||
|
|
||||||
|
ipcServer.Initialize();
|
||||||
|
ipcServer.ServiceRequests();
|
||||||
|
ipcServer.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue