diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2019-01-18 20:26:39 -0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-01-18 20:26:39 -0200 |
| commit | 22bacc618815170c0d186a82e1ea4558e36b7063 (patch) | |
| tree | 79b97959481fea1ac301da6d4e9dea9b991ece6f /Ryujinx.HLE/HOS/Kernel/Threading | |
| parent | 3731d0ce8412c3c48286c242842bcb4940b4ca6d (diff) | |
Improve kernel IPC implementation (#550)
* Implement some IPC related kernel SVCs properly
* Fix BLZ decompression when the segment also has a uncompressed chunck
* Set default cpu core on process start from ProgramLoader, remove debug message
* Load process capabilities properly on KIPs
* Fix a copy/paste error in UnmapPhysicalMemory64
* Implement smarter switching between old and new IPC system to support the old HLE services implementation without the manual switch
* Implement RegisterService on sm and AcceptSession (partial)
* Misc fixes and improvements on new IPC methods
* Move IPC related SVCs into a separate file, and logging on RegisterService (sm)
* Some small fixes related to receive list buffers and error cases
* Load NSOs using the correct pool partition
* Fix corner case on GetMaskFromMinMax where range is 64, doesn't happen in pratice however
* Fix send static buffer copy
* Session release, implement closing requests on client disconnect
* Implement ConnectToPort SVC
* KLightSession init
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Threading')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs | 20 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 62 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs | 4 |
5 files changed, 74 insertions, 16 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs index 5bdb9c1d..dd982291 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs @@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KEvent(Horizon system) { ReadableEvent = new KReadableEvent(system, this); - WritableEvent = new KWritableEvent(this); + WritableEvent = new KWritableEvent(system, this); } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index 60e15efa..c9686df3 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -210,9 +210,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } + return GetDummyThread(); + throw new InvalidOperationException("Current thread is not scheduled!"); } + private KThread _dummyThread; + + private KThread GetDummyThread() + { + if (_dummyThread != null) + { + return _dummyThread; + } + + KProcess dummyProcess = new KProcess(_system); + + KThread dummyThread = new KThread(_system); + + dummyThread.Initialize(0, 0, 0, 44, 0, dummyProcess, ThreadType.Dummy); + + return _dummyThread = dummyThread; + } + public KProcess GetCurrentProcess() { return GetCurrentThread().Owner; diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs index 450155ce..327b0418 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs @@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _system.CriticalSection.Leave(); - return 0; + return KernelResult.Success; } if (timeout == 0) diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 3ad64024..302e8f41 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -30,6 +30,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private ulong _tlsAddress; + public ulong TlsAddress => _tlsAddress; + public ulong TlsDramAddress { get; private set; } + public long LastScheduledTime { get; set; } public LinkedListNode<KThread>[] SiblingsPerCore { get; private set; } @@ -67,6 +70,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public bool WaitingSync { get; set; } private bool _hasExited; + private bool _hasBeenInitialized; + private bool _hasBeenReleased; public bool WaitingInArbitration { get; set; } @@ -124,6 +129,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return KernelResult.OutOfMemory; } + TlsDramAddress = owner.MemoryManager.GetDramAddressFromVa(_tlsAddress); + MemoryHelper.FillWithZeros(owner.CpuMemory, (long)_tlsAddress, KTlsPageInfo.TlsEntrySize); } @@ -133,6 +140,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { Owner = owner; + owner.IncrementReferenceCount(); owner.IncrementThreadCount(); is64Bits = (owner.MmuFlags & 1) != 0; @@ -156,6 +164,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ThreadUid = System.GetThreadUid(); + _hasBeenInitialized = true; + if (owner != null) { owner.AddThread(this); @@ -252,6 +262,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public void Exit() { + //TODO: Debug event. + + if (Owner != null) + { + Owner.ResourceLimit?.Release(LimitableResource.Thread, 0, 1); + + _hasBeenReleased = true; + } + System.CriticalSection.Enter(); _forcePauseFlags &= ~ThreadSchedState.ForcePauseMask; @@ -259,6 +278,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading ExitImpl(); System.CriticalSection.Leave(); + + DecrementReferenceCount(); } private void ExitImpl() @@ -930,7 +951,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return; } - //Remove from old queues. + //Remove thread from the old priority queues. for (int core = 0; core < KScheduler.CpuCoresCount; core++) { if (((oldAffinityMask >> core) & 1) != 0) @@ -946,7 +967,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - //Insert on new queues. + //Add thread to the new priority queues. for (int core = 0; core < KScheduler.CpuCoresCount; core++) { if (((AffinityMask >> core) & 1) != 0) @@ -965,11 +986,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _scheduler.ThreadReselectionRequested = true; } - public override bool IsSignaled() - { - return _hasExited; - } - public void SetEntryArguments(long argsPtr, int threadHandle) { Context.ThreadState.X0 = (ulong)argsPtr; @@ -994,13 +1010,36 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private void ThreadFinishedHandler(object sender, EventArgs e) { System.Scheduler.ExitThread(this); + System.Scheduler.RemoveThread(this); + } - Terminate(); + public override bool IsSignaled() + { + return _hasExited; + } - System.Scheduler.RemoveThread(this); + protected override void Destroy() + { + if (_hasBeenInitialized) + { + FreeResources(); + + bool released = Owner != null || _hasBeenReleased; + + if (Owner != null) + { + Owner.ResourceLimit?.Release(LimitableResource.Thread, 1, released ? 0 : 1); + + Owner.DecrementReferenceCount(); + } + else + { + System.ResourceLimit.Release(LimitableResource.Thread, 1, released ? 0 : 1); + } + } } - public void Terminate() + private void FreeResources() { Owner?.RemoveThread(this); @@ -1011,8 +1050,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading System.CriticalSection.Enter(); - //Wake up all threads that may be waiting for a mutex being held - //by this thread. + //Wake up all threads that may be waiting for a mutex being held by this thread. foreach (KThread thread in _mutexWaiters) { thread.MutexOwner = null; diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs index c9b2f40d..1db88995 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs @@ -2,11 +2,11 @@ using Ryujinx.HLE.HOS.Kernel.Common; namespace Ryujinx.HLE.HOS.Kernel.Threading { - class KWritableEvent + class KWritableEvent : KAutoObject { private KEvent _parent; - public KWritableEvent(KEvent parent) + public KWritableEvent(Horizon system, KEvent parent) : base(system) { _parent = parent; } |
