aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/OsHle/Kernel
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-08-16 20:47:36 -0300
committerGitHub <noreply@github.com>2018-08-16 20:47:36 -0300
commit521751795a1c97c0d97f6f8904a3be69b13d3a9d (patch)
tree942a05899c40e2de6d92a38b93a494bd96ee64b8 /Ryujinx.HLE/OsHle/Kernel
parent182d716867ae477c2b15a5332430dc2641fa1cc3 (diff)
Code style fixes and nits on the HLE project (#355)
* Some style fixes and nits on ITimeZoneService * Remove some unneeded usings * Remove the Ryujinx.HLE.OsHle.Handles namespace * Remove hbmenu automatic load on process exit * Rename Ns to Device, rename Os to System, rename SystemState to State * Move Exceptions and Utilities out of OsHle * Rename OsHle to HOS * Rename OsHle folder to HOS * IManagerDisplayService and ISystemDisplayService style fixes * BsdError shouldn't be public * Add a empty new line before using static * Remove unused file * Some style fixes on NPDM * Exit gracefully when the application is closed * Code style fixes on IGeneralService * Add 0x prefix on values printed as hex * Small improvements on finalization code * Move ProcessId and ThreadId out of AThreadState * Rename VFs to FileSystem * FsAccessHeader shouldn't be public. Also fix file names casing * More case changes on NPDM * Remove unused files * Move using to the correct place on NPDM * Use properties on KernelAccessControlMmio * Address PR feedback
Diffstat (limited to 'Ryujinx.HLE/OsHle/Kernel')
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs112
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/KernelErr.cs22
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs19
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs124
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs578
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs374
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/SvcThread.cs386
-rw-r--r--Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs524
8 files changed, 0 insertions, 2139 deletions
diff --git a/Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs b/Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs
deleted file mode 100644
index ce9ef0cd..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/AddressArbiter.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using Ryujinx.HLE.OsHle.Handles;
-
-using static Ryujinx.HLE.OsHle.ErrorCode;
-
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- static class AddressArbiter
- {
- static ulong WaitForAddress(Process Process, AThreadState ThreadState, long Address, ulong Timeout)
- {
- KThread CurrentThread = Process.GetThread(ThreadState.Tpidr);
-
- Process.Scheduler.SetReschedule(CurrentThread.ProcessorId);
-
- CurrentThread.ArbiterWaitAddress = Address;
- CurrentThread.ArbiterSignaled = false;
-
- Process.Scheduler.EnterWait(CurrentThread, NsTimeConverter.GetTimeMs(Timeout));
-
- if (!CurrentThread.ArbiterSignaled)
- {
- return MakeError(ErrorModule.Kernel, KernelErr.Timeout);
- }
-
- return 0;
- }
-
- public static ulong WaitForAddressIfLessThan(Process Process,
- AThreadState ThreadState,
- AMemory Memory,
- long Address,
- int Value,
- ulong Timeout,
- bool ShouldDecrement)
- {
- Memory.SetExclusive(ThreadState, Address);
-
- int CurrentValue = Memory.ReadInt32(Address);
-
- while (true)
- {
- if (Memory.TestExclusive(ThreadState, Address))
- {
- if (CurrentValue < Value)
- {
- if (ShouldDecrement)
- {
- Memory.WriteInt32(Address, CurrentValue - 1);
- }
-
- Memory.ClearExclusiveForStore(ThreadState);
- }
- else
- {
- Memory.ClearExclusiveForStore(ThreadState);
-
- return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
- }
-
- break;
- }
-
- Memory.SetExclusive(ThreadState, Address);
-
- CurrentValue = Memory.ReadInt32(Address);
- }
-
- if (Timeout == 0)
- {
- return MakeError(ErrorModule.Kernel, KernelErr.Timeout);
- }
-
- return WaitForAddress(Process, ThreadState, Address, Timeout);
- }
-
- public static ulong WaitForAddressIfEqual(Process Process,
- AThreadState ThreadState,
- AMemory Memory,
- long Address,
- int Value,
- ulong Timeout)
- {
- if (Memory.ReadInt32(Address) != Value)
- {
- return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
- }
-
- if (Timeout == 0)
- {
- return MakeError(ErrorModule.Kernel, KernelErr.Timeout);
- }
-
- return WaitForAddress(Process, ThreadState, Address, Timeout);
- }
- }
-
- enum ArbitrationType : int
- {
- WaitIfLessThan,
- DecrementAndWaitIfLessThan,
- WaitIfEqual
- }
-
- enum SignalType : int
- {
- Signal,
- IncrementAndSignalIfEqual,
- ModifyByWaitingCountAndSignalIfEqual
- }
-}
diff --git a/Ryujinx.HLE/OsHle/Kernel/KernelErr.cs b/Ryujinx.HLE/OsHle/Kernel/KernelErr.cs
deleted file mode 100644
index a62fc1bf..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/KernelErr.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- static class KernelErr
- {
- public const int InvalidSize = 101;
- public const int InvalidAddress = 102;
- public const int OutOfMemory = 104;
- public const int NoAccessPerm = 106;
- public const int InvalidPermission = 108;
- public const int InvalidMemRange = 110;
- public const int InvalidPriority = 112;
- public const int InvalidCoreId = 113;
- public const int InvalidHandle = 114;
- public const int InvalidMaskValue = 116;
- public const int Timeout = 117;
- public const int Canceled = 118;
- public const int CountOutOfRange = 119;
- public const int InvalidEnumValue = 120;
- public const int InvalidThread = 122;
- public const int InvalidState = 125;
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs b/Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs
deleted file mode 100644
index 966fdaca..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/NsTimeConverter.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- static class NsTimeConverter
- {
- public static int GetTimeMs(ulong Ns)
- {
- ulong Ms = Ns / 1_000_000;
-
- if (Ms < int.MaxValue)
- {
- return (int)Ms;
- }
- else
- {
- return int.MaxValue;
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs b/Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs
deleted file mode 100644
index a33ffe5e..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/SvcHandler.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-using ChocolArm64.Events;
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using Ryujinx.HLE.Logging;
-using Ryujinx.HLE.OsHle.Handles;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- partial class SvcHandler
- {
- private delegate void SvcFunc(AThreadState ThreadState);
-
- private Dictionary<int, SvcFunc> SvcFuncs;
-
- private Switch Ns;
- private Process Process;
- private AMemory Memory;
-
- private ConcurrentDictionary<KThread, AutoResetEvent> SyncWaits;
-
- private const uint SelfThreadHandle = 0xffff8000;
- private const uint SelfProcessHandle = 0xffff8001;
-
- private static Random Rng;
-
- public SvcHandler(Switch Ns, Process Process)
- {
- SvcFuncs = new Dictionary<int, SvcFunc>()
- {
- { 0x01, SvcSetHeapSize },
- { 0x03, SvcSetMemoryAttribute },
- { 0x04, SvcMapMemory },
- { 0x05, SvcUnmapMemory },
- { 0x06, SvcQueryMemory },
- { 0x07, SvcExitProcess },
- { 0x08, SvcCreateThread },
- { 0x09, SvcStartThread },
- { 0x0a, SvcExitThread },
- { 0x0b, SvcSleepThread },
- { 0x0c, SvcGetThreadPriority },
- { 0x0d, SvcSetThreadPriority },
- { 0x0e, SvcGetThreadCoreMask },
- { 0x0f, SvcSetThreadCoreMask },
- { 0x10, SvcGetCurrentProcessorNumber },
- { 0x12, SvcClearEvent },
- { 0x13, SvcMapSharedMemory },
- { 0x14, SvcUnmapSharedMemory },
- { 0x15, SvcCreateTransferMemory },
- { 0x16, SvcCloseHandle },
- { 0x17, SvcResetSignal },
- { 0x18, SvcWaitSynchronization },
- { 0x19, SvcCancelSynchronization },
- { 0x1a, SvcArbitrateLock },
- { 0x1b, SvcArbitrateUnlock },
- { 0x1c, SvcWaitProcessWideKeyAtomic },
- { 0x1d, SvcSignalProcessWideKey },
- { 0x1e, SvcGetSystemTick },
- { 0x1f, SvcConnectToNamedPort },
- { 0x21, SvcSendSyncRequest },
- { 0x22, SvcSendSyncRequestWithUserBuffer },
- { 0x25, SvcGetThreadId },
- { 0x26, SvcBreak },
- { 0x27, SvcOutputDebugString },
- { 0x29, SvcGetInfo },
- { 0x2c, SvcMapPhysicalMemory },
- { 0x2d, SvcUnmapPhysicalMemory },
- { 0x32, SvcSetThreadActivity },
- { 0x33, SvcGetThreadContext3 },
- { 0x34, SvcWaitForAddress }
- };
-
- this.Ns = Ns;
- this.Process = Process;
- this.Memory = Process.Memory;
-
- SyncWaits = new ConcurrentDictionary<KThread, AutoResetEvent>();
- }
-
- static SvcHandler()
- {
- Rng = new Random();
- }
-
- public void SvcCall(object sender, AInstExceptionEventArgs e)
- {
- AThreadState ThreadState = (AThreadState)sender;
-
- Process.GetThread(ThreadState.Tpidr).LastPc = e.Position;
-
- if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func))
- {
- Ns.Log.PrintDebug(LogClass.KernelSvc, $"{Func.Method.Name} called.");
-
- Func(ThreadState);
-
- Process.Scheduler.Reschedule(Process.GetThread(ThreadState.Tpidr));
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, $"{Func.Method.Name} ended.");
- }
- else
- {
- Process.PrintStackTrace(ThreadState);
-
- throw new NotImplementedException(e.Id.ToString("x4"));
- }
- }
-
- private KThread GetThread(long Tpidr, int Handle)
- {
- if ((uint)Handle == SelfThreadHandle)
- {
- return Process.GetThread(Tpidr);
- }
- else
- {
- return Process.HandleTable.GetData<KThread>(Handle);
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs b/Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs
deleted file mode 100644
index 68d87293..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/SvcMemory.cs
+++ /dev/null
@@ -1,578 +0,0 @@
-using ChocolArm64.State;
-using Ryujinx.HLE.Logging;
-using Ryujinx.HLE.OsHle.Handles;
-
-using static Ryujinx.HLE.OsHle.ErrorCode;
-
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- partial class SvcHandler
- {
- private void SvcSetHeapSize(AThreadState ThreadState)
- {
- long Size = (long)ThreadState.X1;
-
- if ((Size & 0x1fffff) != 0 || Size != (uint)Size)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Heap size 0x{Size:x16} is not aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- long Result = Process.MemoryManager.TrySetHeapSize(Size, out long Position);
-
- ThreadState.X0 = (ulong)Result;
-
- if (Result == 0)
- {
- ThreadState.X1 = (ulong)Position;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- }
-
- private void SvcSetMemoryAttribute(AThreadState ThreadState)
- {
- long Position = (long)ThreadState.X0;
- long Size = (long)ThreadState.X1;
-
- if (!PageAligned(Position))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- MemoryAttribute AttributeMask = (MemoryAttribute)ThreadState.X2;
- MemoryAttribute AttributeValue = (MemoryAttribute)ThreadState.X3;
-
- MemoryAttribute Attributes = AttributeMask | AttributeValue;
-
- if (Attributes != AttributeMask ||
- (Attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, "Invalid memory attributes!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue);
-
- return;
- }
-
- long Result = Process.MemoryManager.SetMemoryAttribute(
- Position,
- Size,
- AttributeMask,
- AttributeValue);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- else
- {
- Memory.StopObservingRegion(Position, Size);
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private void SvcMapMemory(AThreadState ThreadState)
- {
- long Dst = (long)ThreadState.X0;
- long Src = (long)ThreadState.X1;
- long Size = (long)ThreadState.X2;
-
- if (!PageAligned(Src | Dst))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- if ((ulong)(Src + Size) <= (ulong)Src || (ulong)(Dst + Size) <= (ulong)Dst)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (!InsideAddrSpace(Src, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Src address 0x{Src:x16} out of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (!InsideNewMapRegion(Dst, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{Dst:x16} out of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
-
- return;
- }
-
- long Result = Process.MemoryManager.Map(Src, Dst, Size);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private void SvcUnmapMemory(AThreadState ThreadState)
- {
- long Dst = (long)ThreadState.X0;
- long Src = (long)ThreadState.X1;
- long Size = (long)ThreadState.X2;
-
- if (!PageAligned(Src | Dst))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- if ((ulong)(Src + Size) <= (ulong)Src || (ulong)(Dst + Size) <= (ulong)Dst)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (!InsideAddrSpace(Src, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Src address 0x{Src:x16} out of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (!InsideNewMapRegion(Dst, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{Dst:x16} out of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
-
- return;
- }
-
- long Result = Process.MemoryManager.Unmap(Src, Dst, Size);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private void SvcQueryMemory(AThreadState ThreadState)
- {
- long InfoPtr = (long)ThreadState.X0;
- long Position = (long)ThreadState.X2;
-
- KMemoryInfo BlkInfo = Process.MemoryManager.QueryMemory(Position);
-
- Memory.WriteInt64(InfoPtr + 0x00, BlkInfo.Position);
- Memory.WriteInt64(InfoPtr + 0x08, BlkInfo.Size);
- Memory.WriteInt32(InfoPtr + 0x10, (int)BlkInfo.State & 0xff);
- Memory.WriteInt32(InfoPtr + 0x14, (int)BlkInfo.Attribute);
- Memory.WriteInt32(InfoPtr + 0x18, (int)BlkInfo.Permission);
- Memory.WriteInt32(InfoPtr + 0x1c, BlkInfo.IpcRefCount);
- Memory.WriteInt32(InfoPtr + 0x20, BlkInfo.DeviceRefCount);
- Memory.WriteInt32(InfoPtr + 0x24, 0);
-
- ThreadState.X0 = 0;
- ThreadState.X1 = 0;
- }
-
- private void SvcMapSharedMemory(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
- long Position = (long)ThreadState.X1;
- long Size = (long)ThreadState.X2;
-
- if (!PageAligned(Position))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- if ((ulong)(Position + Size) <= (ulong)Position)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- MemoryPermission Permission = (MemoryPermission)ThreadState.X3;
-
- if ((Permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);
-
- return;
- }
-
- KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle);
-
- if (SharedMemory == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- if (!InsideAddrSpace(Position, Size) || InsideMapRegion(Position, Size) || InsideHeapRegion(Position, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} out of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (SharedMemory.Size != Size)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} does not match shared memory size 0x{SharedMemory.Size:16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- long Result = Process.MemoryManager.MapSharedMemory(SharedMemory, Permission, Position);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private void SvcUnmapSharedMemory(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
- long Position = (long)ThreadState.X1;
- long Size = (long)ThreadState.X2;
-
- if (!PageAligned(Position))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- if ((ulong)(Position + Size) <= (ulong)Position)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle);
-
- if (SharedMemory == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- if (!InsideAddrSpace(Position, Size) || InsideMapRegion(Position, Size) || InsideHeapRegion(Position, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} out of range!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- long Result = Process.MemoryManager.UnmapSharedMemory(Position, Size);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private void SvcCreateTransferMemory(AThreadState ThreadState)
- {
- long Position = (long)ThreadState.X1;
- long Size = (long)ThreadState.X2;
-
- if (!PageAligned(Position))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if ((ulong)(Position + Size) <= (ulong)Position)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- MemoryPermission Permission = (MemoryPermission)ThreadState.X3;
-
- if (Permission > MemoryPermission.ReadAndWrite || Permission == MemoryPermission.Write)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);
-
- return;
- }
-
- Process.MemoryManager.ReserveTransferMemory(Position, Size, Permission);
-
- KTransferMemory TransferMemory = new KTransferMemory(Position, Size);
-
- int Handle = Process.HandleTable.OpenHandle(TransferMemory);
-
- ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Handle;
- }
-
- private void SvcMapPhysicalMemory(AThreadState ThreadState)
- {
- long Position = (long)ThreadState.X0;
- long Size = (long)ThreadState.X1;
-
- if (!PageAligned(Position))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- if ((ulong)(Position + Size) <= (ulong)Position)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (!InsideAddrSpace(Position, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Position:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- long Result = Process.MemoryManager.MapPhysicalMemory(Position, Size);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private void SvcUnmapPhysicalMemory(AThreadState ThreadState)
- {
- long Position = (long)ThreadState.X0;
- long Size = (long)ThreadState.X1;
-
- if (!PageAligned(Position))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- if (!PageAligned(Size) || Size == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
-
- return;
- }
-
- if ((ulong)(Position + Size) <= (ulong)Position)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (!InsideAddrSpace(Position, Size))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Position:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- long Result = Process.MemoryManager.UnmapPhysicalMemory(Position, Size);
-
- if (Result != 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
-
- ThreadState.X0 = (ulong)Result;
- }
-
- private static bool PageAligned(long Position)
- {
- return (Position & (KMemoryManager.PageSize - 1)) == 0;
- }
-
- private bool InsideAddrSpace(long Position, long Size)
- {
- ulong Start = (ulong)Position;
- ulong End = (ulong)Size + Start;
-
- return Start >= (ulong)Process.MemoryManager.AddrSpaceStart &&
- End < (ulong)Process.MemoryManager.AddrSpaceEnd;
- }
-
- private bool InsideMapRegion(long Position, long Size)
- {
- ulong Start = (ulong)Position;
- ulong End = (ulong)Size + Start;
-
- return Start >= (ulong)Process.MemoryManager.MapRegionStart &&
- End < (ulong)Process.MemoryManager.MapRegionEnd;
- }
-
- private bool InsideHeapRegion(long Position, long Size)
- {
- ulong Start = (ulong)Position;
- ulong End = (ulong)Size + Start;
-
- return Start >= (ulong)Process.MemoryManager.HeapRegionStart &&
- End < (ulong)Process.MemoryManager.HeapRegionEnd;
- }
-
- private bool InsideNewMapRegion(long Position, long Size)
- {
- ulong Start = (ulong)Position;
- ulong End = (ulong)Size + Start;
-
- return Start >= (ulong)Process.MemoryManager.NewMapRegionStart &&
- End < (ulong)Process.MemoryManager.NewMapRegionEnd;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs b/Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs
deleted file mode 100644
index f833745b..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/SvcSystem.cs
+++ /dev/null
@@ -1,374 +0,0 @@
-using ChocolArm64.Memory;
-using ChocolArm64.State;
-using Ryujinx.HLE.Logging;
-using Ryujinx.HLE.OsHle.Exceptions;
-using Ryujinx.HLE.OsHle.Handles;
-using Ryujinx.HLE.OsHle.Ipc;
-using Ryujinx.HLE.OsHle.Services;
-using System;
-using System.Threading;
-
-using static Ryujinx.HLE.OsHle.ErrorCode;
-
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- partial class SvcHandler
- {
- private const int AllowedCpuIdBitmask = 0b1111;
-
- private const bool EnableProcessDebugging = false;
-
- private void SvcExitProcess(AThreadState ThreadState)
- {
- Ns.Os.ExitProcess(ThreadState.ProcessId);
- }
-
- private void SvcClearEvent(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
-
- //TODO: Implement events.
-
- ThreadState.X0 = 0;
- }
-
- private void SvcCloseHandle(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
-
- object Obj = Process.HandleTable.CloseHandle(Handle);
-
- if (Obj == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- if (Obj is KSession Session)
- {
- Session.Dispose();
- }
- else if (Obj is KTransferMemory TransferMemory)
- {
- Process.MemoryManager.ResetTransferMemory(
- TransferMemory.Position,
- TransferMemory.Size);
- }
-
- ThreadState.X0 = 0;
- }
-
- private void SvcResetSignal(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
-
- KEvent Event = Process.HandleTable.GetData<KEvent>(Handle);
-
- if (Event != null)
- {
- Event.WaitEvent.Reset();
-
- ThreadState.X0 = 0;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid event handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcWaitSynchronization(AThreadState ThreadState)
- {
- long HandlesPtr = (long)ThreadState.X1;
- int HandlesCount = (int)ThreadState.X2;
- ulong Timeout = ThreadState.X3;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "HandlesPtr = " + HandlesPtr .ToString("x16") + ", " +
- "HandlesCount = " + HandlesCount.ToString("x8") + ", " +
- "Timeout = " + Timeout .ToString("x16"));
-
- if ((uint)HandlesCount > 0x40)
- {
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange);
-
- return;
- }
-
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- WaitHandle[] Handles = new WaitHandle[HandlesCount + 1];
-
- for (int Index = 0; Index < HandlesCount; Index++)
- {
- int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
-
- KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle);
-
- if (SyncObj == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- Handles[Index] = SyncObj.WaitEvent;
- }
-
- using (AutoResetEvent WaitEvent = new AutoResetEvent(false))
- {
- if (!SyncWaits.TryAdd(CurrThread, WaitEvent))
- {
- throw new InvalidOperationException();
- }
-
- Handles[HandlesCount] = WaitEvent;
-
- Process.Scheduler.Suspend(CurrThread);
-
- int HandleIndex;
-
- ulong Result = 0;
-
- if (Timeout != ulong.MaxValue)
- {
- HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout));
- }
- else
- {
- HandleIndex = WaitHandle.WaitAny(Handles);
- }
-
- if (HandleIndex == WaitHandle.WaitTimeout)
- {
- Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
- }
- else if (HandleIndex == HandlesCount)
- {
- Result = MakeError(ErrorModule.Kernel, KernelErr.Canceled);
- }
-
- SyncWaits.TryRemove(CurrThread, out _);
-
- Process.Scheduler.Resume(CurrThread);
-
- ThreadState.X0 = Result;
-
- if (Result == 0)
- {
- ThreadState.X1 = (ulong)HandleIndex;
- }
- }
- }
-
- private void SvcCancelSynchronization(AThreadState ThreadState)
- {
- int ThreadHandle = (int)ThreadState.X0;
-
- KThread Thread = GetThread(ThreadState.Tpidr, ThreadHandle);
-
- if (Thread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- if (SyncWaits.TryRemove(Thread, out AutoResetEvent WaitEvent))
- {
- WaitEvent.Set();
- }
-
- ThreadState.X0 = 0;
- }
-
- private void SvcGetSystemTick(AThreadState ThreadState)
- {
- ThreadState.X0 = ThreadState.CntpctEl0;
- }
-
- private void SvcConnectToNamedPort(AThreadState ThreadState)
- {
- long StackPtr = (long)ThreadState.X0;
- long NamePtr = (long)ThreadState.X1;
-
- string Name = AMemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
-
- //TODO: Validate that app has perms to access the service, and that the service
- //actually exists, return error codes otherwise.
- KSession Session = new KSession(ServiceFactory.MakeService(Name), Name);
-
- ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
-
- ThreadState.X0 = 0;
- ThreadState.X1 = Handle;
- }
-
- private void SvcSendSyncRequest(AThreadState ThreadState)
- {
- SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
- }
-
- private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
- {
- SendSyncRequest(
- ThreadState,
- (long)ThreadState.X0,
- (long)ThreadState.X1,
- (int)ThreadState.X2);
- }
-
- private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle)
- {
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- byte[] CmdData = Memory.ReadBytes(CmdPtr, Size);
-
- KSession Session = Process.HandleTable.GetData<KSession>(Handle);
-
- if (Session != null)
- {
- Process.Scheduler.Suspend(CurrThread);
-
- IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
-
- long Result = IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
-
- Thread.Yield();
-
- Process.Scheduler.Resume(CurrThread);
-
- ThreadState.X0 = (ulong)Result;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcBreak(AThreadState ThreadState)
- {
- long Reason = (long)ThreadState.X0;
- long Unknown = (long)ThreadState.X1;
- long Info = (long)ThreadState.X2;
-
- Process.PrintStackTrace(ThreadState);
-
- throw new GuestBrokeExecutionException();
- }
-
- private void SvcOutputDebugString(AThreadState ThreadState)
- {
- long Position = (long)ThreadState.X0;
- long Size = (long)ThreadState.X1;
-
- string Str = AMemoryHelper.ReadAsciiString(Memory, Position, Size);
-
- Ns.Log.PrintWarning(LogClass.KernelSvc, Str);
-
- ThreadState.X0 = 0;
- }
-
- private void SvcGetInfo(AThreadState ThreadState)
- {
- long StackPtr = (long)ThreadState.X0;
- int InfoType = (int)ThreadState.X1;
- long Handle = (long)ThreadState.X2;
- int InfoId = (int)ThreadState.X3;
-
- //Fail for info not available on older Kernel versions.
- if (InfoType == 18 ||
- InfoType == 19 ||
- InfoType == 20)
- {
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
-
- return;
- }
-
- switch (InfoType)
- {
- case 0:
- ThreadState.X1 = AllowedCpuIdBitmask;
- break;
-
- case 2:
- ThreadState.X1 = (ulong)Process.MemoryManager.MapRegionStart;
- break;
-
- case 3:
- ThreadState.X1 = (ulong)Process.MemoryManager.MapRegionEnd -
- (ulong)Process.MemoryManager.MapRegionStart;
- break;
-
- case 4:
- ThreadState.X1 = (ulong)Process.MemoryManager.HeapRegionStart;
- break;
-
- case 5:
- ThreadState.X1 = (ulong)Process.MemoryManager.HeapRegionEnd -
- (ulong)Process.MemoryManager.HeapRegionStart;
- break;
-
- case 6:
- ThreadState.X1 = (ulong)Process.Ns.Memory.Allocator.TotalAvailableSize;
- break;
-
- case 7:
- ThreadState.X1 = (ulong)Process.Ns.Memory.Allocator.TotalUsedSize;
- break;
-
- case 8:
- ThreadState.X1 = EnableProcessDebugging ? 1 : 0;
- break;
-
- case 11:
- ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
- break;
-
- case 12:
- ThreadState.X1 = (ulong)Process.MemoryManager.AddrSpaceStart;
- break;
-
- case 13:
- ThreadState.X1 = (ulong)Process.MemoryManager.AddrSpaceEnd -
- (ulong)Process.MemoryManager.AddrSpaceStart;
- break;
-
- case 14:
- ThreadState.X1 = (ulong)Process.MemoryManager.NewMapRegionStart;
- break;
-
- case 15:
- ThreadState.X1 = (ulong)Process.MemoryManager.NewMapRegionEnd -
- (ulong)Process.MemoryManager.NewMapRegionStart;
- break;
-
- case 16:
- ThreadState.X1 = (ulong)(Process.MetaData?.SystemResourceSize ?? 0);
- break;
-
- case 17:
- ThreadState.X1 = (ulong)Process.MemoryManager.PersonalMmHeapUsage;
- break;
-
- default:
- Process.PrintStackTrace(ThreadState);
-
- throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle:x8} {InfoId}");
- }
-
- ThreadState.X0 = 0;
- }
- }
-}
diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcThread.cs b/Ryujinx.HLE/OsHle/Kernel/SvcThread.cs
deleted file mode 100644
index 04524850..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/SvcThread.cs
+++ /dev/null
@@ -1,386 +0,0 @@
-using ChocolArm64.State;
-using Ryujinx.HLE.Logging;
-using Ryujinx.HLE.OsHle.Handles;
-using System.Threading;
-
-using static Ryujinx.HLE.OsHle.ErrorCode;
-
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- partial class SvcHandler
- {
- private void SvcCreateThread(AThreadState ThreadState)
- {
- long EntryPoint = (long)ThreadState.X1;
- long ArgsPtr = (long)ThreadState.X2;
- long StackTop = (long)ThreadState.X3;
- int Priority = (int)ThreadState.X4;
- int ProcessorId = (int)ThreadState.X5;
-
- if ((uint)Priority > 0x3f)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid priority 0x{Priority:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPriority);
-
- return;
- }
-
- if (ProcessorId == -2)
- {
- //TODO: Get this value from the NPDM file.
- ProcessorId = 0;
- }
- else if ((uint)ProcessorId > 3)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{ProcessorId:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId);
-
- return;
- }
-
- int Handle = Process.MakeThread(
- EntryPoint,
- StackTop,
- ArgsPtr,
- Priority,
- ProcessorId);
-
- ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Handle;
- }
-
- private void SvcStartThread(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
-
- KThread NewThread = Process.HandleTable.GetData<KThread>(Handle);
-
- if (NewThread != null)
- {
- Process.Scheduler.StartThread(NewThread);
- Process.Scheduler.SetReschedule(NewThread.ProcessorId);
-
- ThreadState.X0 = 0;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcExitThread(AThreadState ThreadState)
- {
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- CurrThread.Thread.StopExecution();
- }
-
- private void SvcSleepThread(AThreadState ThreadState)
- {
- ulong TimeoutNs = ThreadState.X0;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "Timeout = " + TimeoutNs.ToString("x16"));
-
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- if (TimeoutNs == 0 || TimeoutNs == ulong.MaxValue)
- {
- Process.Scheduler.Yield(CurrThread);
- }
- else
- {
- Process.Scheduler.Suspend(CurrThread);
-
- Thread.Sleep(NsTimeConverter.GetTimeMs(TimeoutNs));
-
- Process.Scheduler.Resume(CurrThread);
- }
- }
-
- private void SvcGetThreadPriority(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X1;
-
- KThread Thread = GetThread(ThreadState.Tpidr, Handle);
-
- if (Thread != null)
- {
- ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Thread.ActualPriority;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcSetThreadPriority(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
- int Priority = (int)ThreadState.X1;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "Handle = " + Handle .ToString("x8") + ", " +
- "Priority = " + Priority.ToString("x8"));
-
- KThread Thread = GetThread(ThreadState.Tpidr, Handle);
-
- if (Thread != null)
- {
- Thread.SetPriority(Priority);
-
- ThreadState.X0 = 0;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcGetThreadCoreMask(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X2;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "Handle = " + Handle.ToString("x8"));
-
- KThread Thread = GetThread(ThreadState.Tpidr, Handle);
-
- if (Thread != null)
- {
- ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Thread.IdealCore;
- ThreadState.X2 = (ulong)Thread.CoreMask;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcSetThreadCoreMask(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
- int IdealCore = (int)ThreadState.X1;
- long CoreMask = (long)ThreadState.X2;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "Handle = " + Handle .ToString("x8") + ", " +
- "IdealCore = " + IdealCore.ToString("x8") + ", " +
- "CoreMask = " + CoreMask .ToString("x16"));
-
- KThread Thread = GetThread(ThreadState.Tpidr, Handle);
-
- if (IdealCore == -2)
- {
- //TODO: Get this value from the NPDM file.
- IdealCore = 0;
-
- CoreMask = 1 << IdealCore;
- }
- else
- {
- if ((uint)IdealCore > 3)
- {
- if ((IdealCore | 2) != -1)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{IdealCore:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId);
-
- return;
- }
- }
- else if ((CoreMask & (1 << IdealCore)) == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue);
-
- return;
- }
- }
-
- if (Thread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- //-1 is used as "don't care", so the IdealCore value is ignored.
- //-2 is used as "use NPDM default core id" (handled above).
- //-3 is used as "don't update", the old IdealCore value is kept.
- if (IdealCore == -3 && (CoreMask & (1 << Thread.IdealCore)) == 0)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue);
-
- return;
- }
-
- Process.Scheduler.ChangeCore(Thread, IdealCore, (int)CoreMask);
-
- ThreadState.X0 = 0;
- }
-
- private void SvcGetCurrentProcessorNumber(AThreadState ThreadState)
- {
- ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ActualCore;
- }
-
- private void SvcGetThreadId(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X1;
-
- KThread Thread = GetThread(ThreadState.Tpidr, Handle);
-
- if (Thread != null)
- {
- ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Thread.ThreadId;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcSetThreadActivity(AThreadState ThreadState)
- {
- int Handle = (int)ThreadState.X0;
- bool Active = (int)ThreadState.X1 == 0;
-
- KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
-
- if (Thread != null)
- {
- Process.Scheduler.SetThreadActivity(Thread, Active);
-
- ThreadState.X0 = 0;
- }
- else
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- }
- }
-
- private void SvcGetThreadContext3(AThreadState ThreadState)
- {
- long Position = (long)ThreadState.X0;
- int Handle = (int)ThreadState.X1;
-
- KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
-
- if (Thread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- if (Process.GetThread(ThreadState.Tpidr) == Thread)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is current thread!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);
-
- return;
- }
-
- Memory.WriteUInt64(Position + 0x0, ThreadState.X0);
- Memory.WriteUInt64(Position + 0x8, ThreadState.X1);
- Memory.WriteUInt64(Position + 0x10, ThreadState.X2);
- Memory.WriteUInt64(Position + 0x18, ThreadState.X3);
- Memory.WriteUInt64(Position + 0x20, ThreadState.X4);
- Memory.WriteUInt64(Position + 0x28, ThreadState.X5);
- Memory.WriteUInt64(Position + 0x30, ThreadState.X6);
- Memory.WriteUInt64(Position + 0x38, ThreadState.X7);
- Memory.WriteUInt64(Position + 0x40, ThreadState.X8);
- Memory.WriteUInt64(Position + 0x48, ThreadState.X9);
- Memory.WriteUInt64(Position + 0x50, ThreadState.X10);
- Memory.WriteUInt64(Position + 0x58, ThreadState.X11);
- Memory.WriteUInt64(Position + 0x60, ThreadState.X12);
- Memory.WriteUInt64(Position + 0x68, ThreadState.X13);
- Memory.WriteUInt64(Position + 0x70, ThreadState.X14);
- Memory.WriteUInt64(Position + 0x78, ThreadState.X15);
- Memory.WriteUInt64(Position + 0x80, ThreadState.X16);
- Memory.WriteUInt64(Position + 0x88, ThreadState.X17);
- Memory.WriteUInt64(Position + 0x90, ThreadState.X18);
- Memory.WriteUInt64(Position + 0x98, ThreadState.X19);
- Memory.WriteUInt64(Position + 0xa0, ThreadState.X20);
- Memory.WriteUInt64(Position + 0xa8, ThreadState.X21);
- Memory.WriteUInt64(Position + 0xb0, ThreadState.X22);
- Memory.WriteUInt64(Position + 0xb8, ThreadState.X23);
- Memory.WriteUInt64(Position + 0xc0, ThreadState.X24);
- Memory.WriteUInt64(Position + 0xc8, ThreadState.X25);
- Memory.WriteUInt64(Position + 0xd0, ThreadState.X26);
- Memory.WriteUInt64(Position + 0xd8, ThreadState.X27);
- Memory.WriteUInt64(Position + 0xe0, ThreadState.X28);
- Memory.WriteUInt64(Position + 0xe8, ThreadState.X29);
- Memory.WriteUInt64(Position + 0xf0, ThreadState.X30);
- Memory.WriteUInt64(Position + 0xf8, ThreadState.X31);
-
- Memory.WriteInt64(Position + 0x100, Thread.LastPc);
-
- Memory.WriteUInt64(Position + 0x108, (ulong)ThreadState.Psr);
-
- Memory.WriteVector128(Position + 0x110, ThreadState.V0);
- Memory.WriteVector128(Position + 0x120, ThreadState.V1);
- Memory.WriteVector128(Position + 0x130, ThreadState.V2);
- Memory.WriteVector128(Position + 0x140, ThreadState.V3);
- Memory.WriteVector128(Position + 0x150, ThreadState.V4);
- Memory.WriteVector128(Position + 0x160, ThreadState.V5);
- Memory.WriteVector128(Position + 0x170, ThreadState.V6);
- Memory.WriteVector128(Position + 0x180, ThreadState.V7);
- Memory.WriteVector128(Position + 0x190, ThreadState.V8);
- Memory.WriteVector128(Position + 0x1a0, ThreadState.V9);
- Memory.WriteVector128(Position + 0x1b0, ThreadState.V10);
- Memory.WriteVector128(Position + 0x1c0, ThreadState.V11);
- Memory.WriteVector128(Position + 0x1d0, ThreadState.V12);
- Memory.WriteVector128(Position + 0x1e0, ThreadState.V13);
- Memory.WriteVector128(Position + 0x1f0, ThreadState.V14);
- Memory.WriteVector128(Position + 0x200, ThreadState.V15);
- Memory.WriteVector128(Position + 0x210, ThreadState.V16);
- Memory.WriteVector128(Position + 0x220, ThreadState.V17);
- Memory.WriteVector128(Position + 0x230, ThreadState.V18);
- Memory.WriteVector128(Position + 0x240, ThreadState.V19);
- Memory.WriteVector128(Position + 0x250, ThreadState.V20);
- Memory.WriteVector128(Position + 0x260, ThreadState.V21);
- Memory.WriteVector128(Position + 0x270, ThreadState.V22);
- Memory.WriteVector128(Position + 0x280, ThreadState.V23);
- Memory.WriteVector128(Position + 0x290, ThreadState.V24);
- Memory.WriteVector128(Position + 0x2a0, ThreadState.V25);
- Memory.WriteVector128(Position + 0x2b0, ThreadState.V26);
- Memory.WriteVector128(Position + 0x2c0, ThreadState.V27);
- Memory.WriteVector128(Position + 0x2d0, ThreadState.V28);
- Memory.WriteVector128(Position + 0x2e0, ThreadState.V29);
- Memory.WriteVector128(Position + 0x2f0, ThreadState.V30);
- Memory.WriteVector128(Position + 0x300, ThreadState.V31);
-
- Memory.WriteInt32(Position + 0x310, ThreadState.Fpcr);
- Memory.WriteInt32(Position + 0x314, ThreadState.Fpsr);
- Memory.WriteInt64(Position + 0x318, ThreadState.Tpidr);
-
- ThreadState.X0 = 0;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs
deleted file mode 100644
index 164a85ca..00000000
--- a/Ryujinx.HLE/OsHle/Kernel/SvcThreadSync.cs
+++ /dev/null
@@ -1,524 +0,0 @@
-using ChocolArm64.State;
-using Ryujinx.HLE.Logging;
-using Ryujinx.HLE.OsHle.Handles;
-using System;
-
-using static Ryujinx.HLE.OsHle.ErrorCode;
-
-namespace Ryujinx.HLE.OsHle.Kernel
-{
- partial class SvcHandler
- {
- private const int MutexHasListenersMask = 0x40000000;
-
- private void SvcArbitrateLock(AThreadState ThreadState)
- {
- int OwnerThreadHandle = (int)ThreadState.X0;
- long MutexAddress = (long)ThreadState.X1;
- int WaitThreadHandle = (int)ThreadState.X2;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "OwnerThreadHandle = " + OwnerThreadHandle.ToString("x8") + ", " +
- "MutexAddress = " + MutexAddress .ToString("x16") + ", " +
- "WaitThreadHandle = " + WaitThreadHandle .ToString("x8"));
-
- if (IsPointingInsideKernel(MutexAddress))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (IsWordAddressUnaligned(MutexAddress))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle);
-
- if (OwnerThread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid owner thread handle 0x{OwnerThreadHandle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- KThread WaitThread = Process.HandleTable.GetData<KThread>(WaitThreadHandle);
-
- if (WaitThread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid requesting thread handle 0x{WaitThreadHandle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- MutexLock(CurrThread, WaitThread, OwnerThreadHandle, WaitThreadHandle, MutexAddress);
-
- ThreadState.X0 = 0;
- }
-
- private void SvcArbitrateUnlock(AThreadState ThreadState)
- {
- long MutexAddress = (long)ThreadState.X0;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexAddress = " + MutexAddress.ToString("x16"));
-
- if (IsPointingInsideKernel(MutexAddress))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (IsWordAddressUnaligned(MutexAddress))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- MutexUnlock(Process.GetThread(ThreadState.Tpidr), MutexAddress);
-
- ThreadState.X0 = 0;
- }
-
- private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
- {
- long MutexAddress = (long)ThreadState.X0;
- long CondVarAddress = (long)ThreadState.X1;
- int ThreadHandle = (int)ThreadState.X2;
- ulong Timeout = ThreadState.X3;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "MutexAddress = " + MutexAddress .ToString("x16") + ", " +
- "CondVarAddress = " + CondVarAddress.ToString("x16") + ", " +
- "ThreadHandle = " + ThreadHandle .ToString("x8") + ", " +
- "Timeout = " + Timeout .ToString("x16"));
-
- if (IsPointingInsideKernel(MutexAddress))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (IsWordAddressUnaligned(MutexAddress))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
-
- if (Thread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
-
- return;
- }
-
- KThread WaitThread = Process.GetThread(ThreadState.Tpidr);
-
- if (!CondVarWait(WaitThread, ThreadHandle, MutexAddress, CondVarAddress, Timeout))
- {
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
-
- return;
- }
-
- ThreadState.X0 = 0;
- }
-
- private void SvcSignalProcessWideKey(AThreadState ThreadState)
- {
- long CondVarAddress = (long)ThreadState.X0;
- int Count = (int)ThreadState.X1;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "CondVarAddress = " + CondVarAddress.ToString("x16") + ", " +
- "Count = " + Count .ToString("x8"));
-
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- CondVarSignal(ThreadState, CurrThread, CondVarAddress, Count);
-
- ThreadState.X0 = 0;
- }
-
- private void MutexLock(
- KThread CurrThread,
- KThread WaitThread,
- int OwnerThreadHandle,
- int WaitThreadHandle,
- long MutexAddress)
- {
- lock (Process.ThreadSyncLock)
- {
- int MutexValue = Memory.ReadInt32(MutexAddress);
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
-
- if (MutexValue != (OwnerThreadHandle | MutexHasListenersMask))
- {
- return;
- }
-
- CurrThread.WaitHandle = WaitThreadHandle;
- CurrThread.MutexAddress = MutexAddress;
-
- InsertWaitingMutexThreadUnsafe(OwnerThreadHandle, WaitThread);
- }
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state...");
-
- Process.Scheduler.EnterWait(CurrThread);
- }
-
- private void SvcWaitForAddress(AThreadState ThreadState)
- {
- long Address = (long)ThreadState.X0;
- ArbitrationType Type = (ArbitrationType)ThreadState.X1;
- int Value = (int)ThreadState.X2;
- ulong Timeout = ThreadState.X3;
-
- Ns.Log.PrintDebug(LogClass.KernelSvc,
- "Address = " + Address.ToString("x16") + ", " +
- "ArbitrationType = " + Type .ToString() + ", " +
- "Value = " + Value .ToString("x8") + ", " +
- "Timeout = " + Timeout.ToString("x16"));
-
- if (IsPointingInsideKernel(Address))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
-
- return;
- }
-
- if (IsWordAddressUnaligned(Address))
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!");
-
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
-
- return;
- }
-
- switch (Type)
- {
- case ArbitrationType.WaitIfLessThan:
- ThreadState.X0 = AddressArbiter.WaitForAddressIfLessThan(Process, ThreadState, Memory, Address, Value, Timeout, false);
- break;
-
- case ArbitrationType.DecrementAndWaitIfLessThan:
- ThreadState.X0 = AddressArbiter.WaitForAddressIfLessThan(Process, ThreadState, Memory, Address, Value, Timeout, true);
- break;
-
- case ArbitrationType.WaitIfEqual:
- ThreadState.X0 = AddressArbiter.WaitForAddressIfEqual(Process, ThreadState, Memory, Address, Value, Timeout);
- break;
-
- default:
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
- break;
- }
- }
-
- private void MutexUnlock(KThread CurrThread, long MutexAddress)
- {
- lock (Process.ThreadSyncLock)
- {
- //This is the new thread that will now own the mutex.
- //If no threads are waiting for the lock, then it should be null.
- (KThread OwnerThread, int Count) = PopMutexThreadUnsafe(CurrThread, MutexAddress);
-
- if (OwnerThread == CurrThread)
- {
- throw new InvalidOperationException();
- }
-
- if (OwnerThread != null)
- {
- //Remove all waiting mutex from the old owner,
- //and insert then on the new owner.
- UpdateMutexOwnerUnsafe(CurrThread, OwnerThread, MutexAddress);
-
- CurrThread.UpdatePriority();
-
- int HasListeners = Count >= 2 ? MutexHasListenersMask : 0;
-
- Memory.WriteInt32ToSharedAddr(MutexAddress, HasListeners | OwnerThread.WaitHandle);
-
- OwnerThread.WaitHandle = 0;
- OwnerThread.MutexAddress = 0;
- OwnerThread.CondVarAddress = 0;
- OwnerThread.MutexOwner = null;
-
- OwnerThread.UpdatePriority();
-
- Process.Scheduler.WakeUp(OwnerThread);
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "Gave mutex to thread id " + OwnerThread.ThreadId + "!");
- }
- else
- {
- Memory.WriteInt32ToSharedAddr(MutexAddress, 0);
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!");
- }
- }
- }
-
- private bool CondVarWait(
- KThread WaitThread,
- int WaitThreadHandle,
- long MutexAddress,
- long CondVarAddress,
- ulong Timeout)
- {
- WaitThread.WaitHandle = WaitThreadHandle;
- WaitThread.MutexAddress = MutexAddress;
- WaitThread.CondVarAddress = CondVarAddress;
-
- lock (Process.ThreadSyncLock)
- {
- MutexUnlock(WaitThread, MutexAddress);
-
- WaitThread.CondVarSignaled = false;
-
- Process.ThreadArbiterList.Add(WaitThread);
- }
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "Entering wait state...");
-
- if (Timeout != ulong.MaxValue)
- {
- Process.Scheduler.EnterWait(WaitThread, NsTimeConverter.GetTimeMs(Timeout));
-
- lock (Process.ThreadSyncLock)
- {
- if (!WaitThread.CondVarSignaled || WaitThread.MutexOwner != null)
- {
- if (WaitThread.MutexOwner != null)
- {
- WaitThread.MutexOwner.MutexWaiters.Remove(WaitThread);
- WaitThread.MutexOwner.UpdatePriority();
-
- WaitThread.MutexOwner = null;
- }
-
- Process.ThreadArbiterList.Remove(WaitThread);
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "Timed out...");
-
- return false;
- }
- }
- }
- else
- {
- Process.Scheduler.EnterWait(WaitThread);
- }
-
- return true;
- }
-
- private void CondVarSignal(
- AThreadState ThreadState,
- KThread CurrThread,
- long CondVarAddress,
- int Count)
- {
- lock (Process.ThreadSyncLock)
- {
- while (Count == -1 || Count-- > 0)
- {
- KThread WaitThread = PopCondVarThreadUnsafe(CondVarAddress);
-
- if (WaitThread == null)
- {
- Ns.Log.PrintDebug(LogClass.KernelSvc, "No more threads to wake up!");
-
- break;
- }
-
- WaitThread.CondVarSignaled = true;
-
- long MutexAddress = WaitThread.MutexAddress;
-
- Memory.SetExclusive(ThreadState, MutexAddress);
-
- int MutexValue = Memory.ReadInt32(MutexAddress);
-
- while (MutexValue != 0)
- {
- if (Memory.TestExclusive(ThreadState, MutexAddress))
- {
- //Wait until the lock is released.
- InsertWaitingMutexThreadUnsafe(MutexValue & ~MutexHasListenersMask, WaitThread);
-
- Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask);
-
- Memory.ClearExclusiveForStore(ThreadState);
-
- break;
- }
-
- Memory.SetExclusive(ThreadState, MutexAddress);
-
- MutexValue = Memory.ReadInt32(MutexAddress);
- }
-
- Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
-
- if (MutexValue == 0)
- {
- //Give the lock to this thread.
- Memory.WriteInt32ToSharedAddr(MutexAddress, WaitThread.WaitHandle);
-
- WaitThread.WaitHandle = 0;
- WaitThread.MutexAddress = 0;
- WaitThread.CondVarAddress = 0;
-
- WaitThread.MutexOwner?.UpdatePriority();
-
- WaitThread.MutexOwner = null;
-
- Process.Scheduler.WakeUp(WaitThread);
- }
- }
- }
- }
-
- private void UpdateMutexOwnerUnsafe(KThread CurrThread, KThread NewOwner, long MutexAddress)
- {
- //Go through all threads waiting for the mutex,
- //and update the MutexOwner field to point to the new owner.
- for (int Index = 0; Index < CurrThread.MutexWaiters.Count; Index++)
- {
- KThread Thread = CurrThread.MutexWaiters[Index];
-
- if (Thread.MutexAddress == MutexAddress)
- {
- CurrThread.MutexWaiters.RemoveAt(Index--);
-
- InsertWaitingMutexThreadUnsafe(NewOwner, Thread);
- }
- }
- }
-
- private void InsertWaitingMutexThreadUnsafe(int OwnerThreadHandle, KThread WaitThread)
- {
- KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle);
-
- if (OwnerThread == null)
- {
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{OwnerThreadHandle:x8}!");
-
- return;
- }
-
- InsertWaitingMutexThreadUnsafe(OwnerThread, WaitThread);
- }
-
- private void InsertWaitingMutexThreadUnsafe(KThread OwnerThread, KThread WaitThread)
- {
- WaitThread.MutexOwner = OwnerThread;
-
- if (!OwnerThread.MutexWaiters.Contains(WaitThread))
- {
- OwnerThread.MutexWaiters.Add(WaitThread);
-
- OwnerThread.UpdatePriority();
- }
- }
-
- private (KThread, int) PopMutexThreadUnsafe(KThread OwnerThread, long MutexAddress)
- {
- int Count = 0;
-
- KThread WakeThread = null;
-
- foreach (KThread Thread in OwnerThread.MutexWaiters)
- {
- if (Thread.MutexAddress != MutexAddress)
- {
- continue;
- }
-
- if (WakeThread == null || Thread.ActualPriority < WakeThread.ActualPriority)
- {
- WakeThread = Thread;
- }
-
- Count++;
- }
-
- if (WakeThread != null)
- {
- OwnerThread.MutexWaiters.Remove(WakeThread);
- }
-
- return (WakeThread, Count);
- }
-
- private KThread PopCondVarThreadUnsafe(long CondVarAddress)
- {
- KThread WakeThread = null;
-
- foreach (KThread Thread in Process.ThreadArbiterList)
- {
- if (Thread.CondVarAddress != CondVarAddress)
- {
- continue;
- }
-
- if (WakeThread == null || Thread.ActualPriority < WakeThread.ActualPriority)
- {
- WakeThread = Thread;
- }
- }
-
- if (WakeThread != null)
- {
- Process.ThreadArbiterList.Remove(WakeThread);
- }
-
- return WakeThread;
- }
-
- private bool IsPointingInsideKernel(long Address)
- {
- return ((ulong)Address + 0x1000000000) < 0xffffff000;
- }
-
- private bool IsWordAddressUnaligned(long Address)
- {
- return (Address & 3) != 0;
- }
- }
-} \ No newline at end of file