aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/Threading
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-01-18 20:26:39 -0200
committerGitHub <noreply@github.com>2019-01-18 20:26:39 -0200
commit22bacc618815170c0d186a82e1ea4558e36b7063 (patch)
tree79b97959481fea1ac301da6d4e9dea9b991ece6f /Ryujinx.HLE/HOS/Kernel/Threading
parent3731d0ce8412c3c48286c242842bcb4940b4ca6d (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.cs2
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs20
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs2
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs62
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs4
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;
}