Support waiting for KThread, remove some test code, other tweaks
This commit is contained in:
parent
44e847c1c1
commit
2d119966b3
17 changed files with 167 additions and 173 deletions
|
@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
private bool OwnsCondVarValue;
|
private bool OwnsCondVarValue;
|
||||||
|
|
||||||
private List<HThread> WaitingThreads;
|
private List<KThread> WaitingThreads;
|
||||||
|
|
||||||
public CondVar(Process Process, long CondVarAddress, long Timeout)
|
public CondVar(Process Process, long CondVarAddress, long Timeout)
|
||||||
{
|
{
|
||||||
|
@ -21,10 +21,10 @@ namespace Ryujinx.Core.OsHle
|
||||||
this.CondVarAddress = CondVarAddress;
|
this.CondVarAddress = CondVarAddress;
|
||||||
this.Timeout = Timeout;
|
this.Timeout = Timeout;
|
||||||
|
|
||||||
WaitingThreads = new List<HThread>();
|
WaitingThreads = new List<KThread>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WaitForSignal(HThread Thread)
|
public bool WaitForSignal(KThread Thread)
|
||||||
{
|
{
|
||||||
int Count = Process.Memory.ReadInt32(CondVarAddress);
|
int Count = Process.Memory.ReadInt32(CondVarAddress);
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSignal(HThread Thread, int Count)
|
public void SetSignal(KThread Thread, int Count)
|
||||||
{
|
{
|
||||||
lock (WaitingThreads)
|
lock (WaitingThreads)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle
|
namespace Ryujinx.Core.OsHle
|
||||||
{
|
{
|
||||||
|
@ -38,14 +39,24 @@ namespace Ryujinx.Core.OsHle
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Delete(Process Process, int Id)
|
public object Delete(Process Process, int Id)
|
||||||
{
|
{
|
||||||
if (DictByProcess.TryGetValue(Process, out IdDictionary Dict))
|
if (DictByProcess.TryGetValue(Process, out IdDictionary Dict))
|
||||||
{
|
{
|
||||||
return Dict.Delete(Id);
|
return Dict.Delete(Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<object> DeleteProcess(Process Process)
|
||||||
|
{
|
||||||
|
if (DictByProcess.TryRemove(Process, out IdDictionary Dict))
|
||||||
|
{
|
||||||
|
return Dict.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
class KProcessHandleTable : IDisposable
|
class KProcessHandleTable
|
||||||
{
|
{
|
||||||
private IdDictionary Handles;
|
private IdDictionary Handles;
|
||||||
|
|
||||||
|
@ -13,14 +13,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public int OpenHandle(object Obj)
|
public int OpenHandle(object Obj)
|
||||||
{
|
{
|
||||||
int h = Handles.Add(Obj);
|
return Handles.Add(Obj);
|
||||||
|
|
||||||
/*if (h == 0x1d)
|
|
||||||
{
|
|
||||||
throw new System.Exception("bad handle");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetData<T>(int Handle)
|
public T GetData<T>(int Handle)
|
||||||
|
@ -28,38 +21,14 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
return Handles.GetData<T>(Handle);
|
return Handles.GetData<T>(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CloseHandle(int Handle)
|
public object CloseHandle(int Handle)
|
||||||
{
|
{
|
||||||
object Data = Handles.GetData(Handle);
|
|
||||||
|
|
||||||
if (Data is HTransferMem TMem)
|
|
||||||
{
|
|
||||||
TMem.Memory.Manager.Reprotect(
|
|
||||||
TMem.Position,
|
|
||||||
TMem.Size,
|
|
||||||
TMem.Perm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Handles.Delete(Handle);
|
return Handles.Delete(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public ICollection<object> Clear()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
return Handles.Clear();
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool Disposing)
|
|
||||||
{
|
|
||||||
if (Disposing)
|
|
||||||
{
|
|
||||||
foreach (object Obj in Handles)
|
|
||||||
{
|
|
||||||
if (Obj is IDisposable DisposableObj)
|
|
||||||
{
|
|
||||||
DisposableObj.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,15 +5,15 @@ using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
public class KProcessScheduler : IDisposable
|
class KProcessScheduler : IDisposable
|
||||||
{
|
{
|
||||||
private class SchedulerThread : IDisposable
|
private class SchedulerThread : IDisposable
|
||||||
{
|
{
|
||||||
public HThread Thread { get; private set; }
|
public KThread Thread { get; private set; }
|
||||||
|
|
||||||
public AutoResetEvent WaitEvent { get; private set; }
|
public AutoResetEvent WaitEvent { get; private set; }
|
||||||
|
|
||||||
public SchedulerThread(HThread Thread)
|
public SchedulerThread(KThread Thread)
|
||||||
{
|
{
|
||||||
this.Thread = Thread;
|
this.Thread = Thread;
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConcurrentDictionary<HThread, SchedulerThread> AllThreads;
|
private ConcurrentDictionary<KThread, SchedulerThread> AllThreads;
|
||||||
|
|
||||||
private ThreadQueue[] WaitingToRun;
|
private ThreadQueue[] WaitingToRun;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public KProcessScheduler()
|
public KProcessScheduler()
|
||||||
{
|
{
|
||||||
AllThreads = new ConcurrentDictionary<HThread, SchedulerThread>();
|
AllThreads = new ConcurrentDictionary<KThread, SchedulerThread>();
|
||||||
|
|
||||||
WaitingToRun = new ThreadQueue[4];
|
WaitingToRun = new ThreadQueue[4];
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
SchedLock = new object();
|
SchedLock = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartThread(HThread Thread)
|
public void StartThread(KThread Thread)
|
||||||
{
|
{
|
||||||
lock (SchedLock)
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
|
@ -164,7 +164,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume(HThread CurrThread)
|
public void Resume(KThread CurrThread)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
SchedulerThread SchedThread;
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
TryResumingExecution(SchedThread);
|
TryResumingExecution(SchedThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WaitForSignal(HThread Thread, int Timeout = -1)
|
public bool WaitForSignal(KThread Thread, int Timeout = -1)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
SchedulerThread SchedThread;
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
private void TryResumingExecution(SchedulerThread SchedThread)
|
private void TryResumingExecution(SchedulerThread SchedThread)
|
||||||
{
|
{
|
||||||
HThread Thread = SchedThread.Thread;
|
KThread Thread = SchedThread.Thread;
|
||||||
|
|
||||||
lock (SchedLock)
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
|
@ -249,7 +249,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
Logging.Debug($"{GetDbgThreadInfo(Thread)} resuming execution...");
|
Logging.Debug($"{GetDbgThreadInfo(Thread)} resuming execution...");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Yield(HThread Thread)
|
public void Yield(KThread Thread)
|
||||||
{
|
{
|
||||||
SchedulerThread SchedThread;
|
SchedulerThread SchedThread;
|
||||||
|
|
||||||
|
@ -295,11 +295,11 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Signal(params HThread[] Threads)
|
public void Signal(params KThread[] Threads)
|
||||||
{
|
{
|
||||||
lock (SchedLock)
|
lock (SchedLock)
|
||||||
{
|
{
|
||||||
foreach (HThread Thread in Threads)
|
foreach (KThread Thread in Threads)
|
||||||
{
|
{
|
||||||
if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
||||||
{
|
{
|
||||||
|
@ -314,7 +314,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetDbgThreadInfo(HThread Thread)
|
private string GetDbgThreadInfo(KThread Thread)
|
||||||
{
|
{
|
||||||
return $"Thread {Thread.ThreadId} (core {Thread.ProcessorId}) prio {Thread.Priority}";
|
return $"Thread {Thread.ThreadId} (core {Thread.ProcessorId}) prio {Thread.Priority}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ using ChocolArm64;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.Handles
|
namespace Ryujinx.Core.OsHle.Handles
|
||||||
{
|
{
|
||||||
public class HThread
|
class KThread : KSynchronizationObject
|
||||||
{
|
{
|
||||||
public AThread Thread { get; private set; }
|
public AThread Thread { get; private set; }
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
|
|
||||||
public int ThreadId => Thread.ThreadId;
|
public int ThreadId => Thread.ThreadId;
|
||||||
|
|
||||||
public HThread(AThread Thread, int ProcessorId, int Priority)
|
public KThread(AThread Thread, int ProcessorId, int Priority)
|
||||||
{
|
{
|
||||||
this.Thread = Thread;
|
this.Thread = Thread;
|
||||||
this.ProcessorId = ProcessorId;
|
this.ProcessorId = ProcessorId;
|
|
@ -1,12 +1,10 @@
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle
|
namespace Ryujinx.Core.OsHle
|
||||||
{
|
{
|
||||||
class IdDictionary : IEnumerable<object>
|
class IdDictionary
|
||||||
{
|
{
|
||||||
private ConcurrentDictionary<int, object> Objs;
|
private ConcurrentDictionary<int, object> Objs;
|
||||||
|
|
||||||
|
@ -60,31 +58,25 @@ namespace Ryujinx.Core.OsHle
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Delete(int Id)
|
public object Delete(int Id)
|
||||||
{
|
{
|
||||||
if (Objs.TryRemove(Id, out object Obj))
|
if (Objs.TryRemove(Id, out object Obj))
|
||||||
{
|
{
|
||||||
if (Obj is IDisposable DisposableObj && !(Obj is KEvent))
|
|
||||||
{
|
|
||||||
DisposableObj.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeIdHint = Id;
|
FreeIdHint = Id;
|
||||||
|
|
||||||
return true;
|
return Obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator<object> IEnumerable<object>.GetEnumerator()
|
public ICollection<object> Clear()
|
||||||
{
|
{
|
||||||
return Objs.Values.GetEnumerator();
|
ICollection<object> Values = Objs.Values;
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
Objs.Clear();
|
||||||
{
|
|
||||||
return Objs.Values.GetEnumerator();
|
return Values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,8 +13,7 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
AMemory Memory,
|
AMemory Memory,
|
||||||
KSession Session,
|
KSession Session,
|
||||||
IpcMessage Request,
|
IpcMessage Request,
|
||||||
long CmdPtr,
|
long CmdPtr)
|
||||||
int HndId)
|
|
||||||
{
|
{
|
||||||
IpcMessage Response = new IpcMessage();
|
IpcMessage Response = new IpcMessage();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
private object EnterWaitLock;
|
private object EnterWaitLock;
|
||||||
|
|
||||||
private ConcurrentQueue<HThread> WaitingThreads;
|
private ConcurrentQueue<KThread> WaitingThreads;
|
||||||
|
|
||||||
public Mutex(Process Process, long MutexAddress, int OwnerThreadHandle)
|
public Mutex(Process Process, long MutexAddress, int OwnerThreadHandle)
|
||||||
{
|
{
|
||||||
|
@ -27,10 +27,10 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
EnterWaitLock = new object();
|
EnterWaitLock = new object();
|
||||||
|
|
||||||
WaitingThreads = new ConcurrentQueue<HThread>();
|
WaitingThreads = new ConcurrentQueue<KThread>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WaitForLock(HThread RequestingThread, int RequestingThreadHandle)
|
public void WaitForLock(KThread RequestingThread, int RequestingThreadHandle)
|
||||||
{
|
{
|
||||||
AcquireMutexValue();
|
AcquireMutexValue();
|
||||||
|
|
||||||
|
@ -83,11 +83,11 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
ReleaseMutexValue();
|
ReleaseMutexValue();
|
||||||
|
|
||||||
HThread[] UnlockedThreads = new HThread[WaitingThreads.Count];
|
KThread[] UnlockedThreads = new KThread[WaitingThreads.Count];
|
||||||
|
|
||||||
int Index = 0;
|
int Index = 0;
|
||||||
|
|
||||||
while (WaitingThreads.TryDequeue(out HThread Thread))
|
while (WaitingThreads.TryDequeue(out KThread Thread))
|
||||||
{
|
{
|
||||||
UnlockedThreads[Index++] = Thread;
|
UnlockedThreads[Index++] = Thread;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Ryujinx.Core.Loaders;
|
||||||
using Ryujinx.Core.Loaders.Executables;
|
using Ryujinx.Core.Loaders.Executables;
|
||||||
using Ryujinx.Core.OsHle.Exceptions;
|
using Ryujinx.Core.OsHle.Exceptions;
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
|
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
||||||
using Ryujinx.Core.OsHle.Svc;
|
using Ryujinx.Core.OsHle.Svc;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
@ -41,11 +42,11 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
private ConcurrentDictionary<int, AThread> TlsSlots;
|
private ConcurrentDictionary<int, AThread> TlsSlots;
|
||||||
|
|
||||||
private ConcurrentDictionary<long, HThread> ThreadsByTpidr;
|
private ConcurrentDictionary<long, KThread> ThreadsByTpidr;
|
||||||
|
|
||||||
private List<Executable> Executables;
|
private List<Executable> Executables;
|
||||||
|
|
||||||
private HThread MainThread;
|
private KThread MainThread;
|
||||||
|
|
||||||
private long ImageBase;
|
private long ImageBase;
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
TlsSlots = new ConcurrentDictionary<int, AThread>();
|
TlsSlots = new ConcurrentDictionary<int, AThread>();
|
||||||
|
|
||||||
ThreadsByTpidr = new ConcurrentDictionary<long, HThread>();
|
ThreadsByTpidr = new ConcurrentDictionary<long, KThread>();
|
||||||
|
|
||||||
Executables = new List<Executable>();
|
Executables = new List<Executable>();
|
||||||
|
|
||||||
|
@ -132,7 +133,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainThread = HandleTable.GetData<HThread>(Handle);
|
MainThread = HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (NeedsHbAbi)
|
if (NeedsHbAbi)
|
||||||
{
|
{
|
||||||
|
@ -186,7 +187,7 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
AThread Thread = new AThread(GetTranslator(), Memory, EntryPoint);
|
AThread Thread = new AThread(GetTranslator(), Memory, EntryPoint);
|
||||||
|
|
||||||
HThread ThreadHnd = new HThread(Thread, ProcessorId, Priority);
|
KThread ThreadHnd = new KThread(Thread, ProcessorId, Priority);
|
||||||
|
|
||||||
int Handle = HandleTable.OpenHandle(ThreadHnd);
|
int Handle = HandleTable.OpenHandle(ThreadHnd);
|
||||||
|
|
||||||
|
@ -311,9 +312,9 @@ namespace Ryujinx.Core.OsHle
|
||||||
return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
|
return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HThread GetThread(long Tpidr)
|
public KThread GetThread(long Tpidr)
|
||||||
{
|
{
|
||||||
if (!ThreadsByTpidr.TryGetValue(Tpidr, out HThread Thread))
|
if (!ThreadsByTpidr.TryGetValue(Tpidr, out KThread Thread))
|
||||||
{
|
{
|
||||||
Logging.Error($"Thread with TPIDR 0x{Tpidr:x16} not found!");
|
Logging.Error($"Thread with TPIDR 0x{Tpidr:x16} not found!");
|
||||||
}
|
}
|
||||||
|
@ -345,7 +346,19 @@ namespace Ryujinx.Core.OsHle
|
||||||
|
|
||||||
Disposed = true;
|
Disposed = true;
|
||||||
|
|
||||||
HandleTable.Dispose();
|
foreach (object Obj in HandleTable.Clear())
|
||||||
|
{
|
||||||
|
if (Obj is KSession Session)
|
||||||
|
{
|
||||||
|
Session.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceNvDrv.Fds.DeleteProcess(this);
|
||||||
|
|
||||||
|
ServiceNvDrv.NvMaps.DeleteProcess(this);
|
||||||
|
|
||||||
|
ServiceNvDrv.NvMapsById.DeleteProcess(this);
|
||||||
|
|
||||||
Scheduler.Dispose();
|
Scheduler.Dispose();
|
||||||
|
|
||||||
|
|
|
@ -40,21 +40,6 @@ namespace Ryujinx.Core.OsHle.IpcServices
|
||||||
IsDomain = false;
|
IsDomain = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int Add(IIpcService Obj)
|
|
||||||
{
|
|
||||||
return DomainObjects.Add(Obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Delete(int Id)
|
|
||||||
{
|
|
||||||
return DomainObjects.Delete(Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IIpcService GetObject(int Id)
|
|
||||||
{
|
|
||||||
return DomainObjects.GetData<IIpcService>(Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CallMethod(ServiceCtx Context)
|
public void CallMethod(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
IIpcService Service = this;
|
IIpcService Service = this;
|
||||||
|
@ -140,5 +125,27 @@ namespace Ryujinx.Core.OsHle.IpcServices
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int Add(IIpcService Obj)
|
||||||
|
{
|
||||||
|
return DomainObjects.Add(Obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Delete(int Id)
|
||||||
|
{
|
||||||
|
object Obj = DomainObjects.Delete(Id);
|
||||||
|
|
||||||
|
if (Obj is IDisposable DisposableObj)
|
||||||
|
{
|
||||||
|
DisposableObj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Obj != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IIpcService GetObject(int Id)
|
||||||
|
{
|
||||||
|
return DomainObjects.GetData<IIpcService>(Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
||||||
|
|
||||||
private Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds;
|
private Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds;
|
||||||
|
|
||||||
private static GlobalStateTable Fds;
|
public static GlobalStateTable Fds { get; private set; }
|
||||||
|
|
||||||
public static GlobalStateTable NvMaps { get; private set; }
|
public static GlobalStateTable NvMaps { get; private set; }
|
||||||
public static GlobalStateTable NvMapsById { get; private set; }
|
public static GlobalStateTable NvMapsById { get; private set; }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.Android;
|
using Ryujinx.Core.OsHle.IpcServices.Android;
|
||||||
using Ryujinx.Graphics.Gal;
|
using Ryujinx.Graphics.Gal;
|
||||||
|
@ -13,6 +14,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
|
|
||||||
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
|
private KEvent ReleaseEvent;
|
||||||
|
|
||||||
private NvFlinger Flinger;
|
private NvFlinger Flinger;
|
||||||
|
|
||||||
public IHOSBinderDriver(IGalRenderer Renderer)
|
public IHOSBinderDriver(IGalRenderer Renderer)
|
||||||
|
@ -24,7 +27,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{ 2, GetNativeHandle }
|
{ 2, GetNativeHandle }
|
||||||
};
|
};
|
||||||
|
|
||||||
Flinger = new NvFlinger(Renderer);
|
ReleaseEvent = new KEvent();
|
||||||
|
|
||||||
|
Flinger = new NvFlinger(Renderer, ReleaseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long TransactParcel(ServiceCtx Context)
|
public long TransactParcel(ServiceCtx Context)
|
||||||
|
@ -56,7 +61,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
int Id = Context.RequestData.ReadInt32();
|
int Id = Context.RequestData.ReadInt32();
|
||||||
uint Unk = Context.RequestData.ReadUInt32();
|
uint Unk = Context.RequestData.ReadUInt32();
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe);
|
int Handle = Context.Process.HandleTable.OpenHandle(ReleaseEvent);
|
||||||
|
|
||||||
|
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +77,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi
|
||||||
{
|
{
|
||||||
if (Disposing)
|
if (Disposing)
|
||||||
{
|
{
|
||||||
|
ReleaseEvent.Dispose();
|
||||||
|
|
||||||
Flinger.Dispose();
|
Flinger.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
||||||
using Ryujinx.Graphics.Gal;
|
using Ryujinx.Graphics.Gal;
|
||||||
using System;
|
using System;
|
||||||
|
@ -17,6 +18,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
private Dictionary<(string, int), ServiceProcessParcel> Commands;
|
private Dictionary<(string, int), ServiceProcessParcel> Commands;
|
||||||
|
|
||||||
|
private KEvent ReleaseEvent;
|
||||||
|
|
||||||
|
private IGalRenderer Renderer;
|
||||||
|
|
||||||
private const int BufferQueueCount = 0x40;
|
private const int BufferQueueCount = 0x40;
|
||||||
private const int BufferQueueMask = BufferQueueCount - 1;
|
private const int BufferQueueMask = BufferQueueCount - 1;
|
||||||
|
|
||||||
|
@ -55,8 +60,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
public GbpBuffer Data;
|
public GbpBuffer Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IGalRenderer Renderer;
|
|
||||||
|
|
||||||
private BufferEntry[] BufferQueue;
|
private BufferEntry[] BufferQueue;
|
||||||
|
|
||||||
private ManualResetEvent WaitBufferFree;
|
private ManualResetEvent WaitBufferFree;
|
||||||
|
@ -69,7 +72,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
private bool KeepRunning;
|
private bool KeepRunning;
|
||||||
|
|
||||||
public NvFlinger(IGalRenderer Renderer)
|
public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent)
|
||||||
{
|
{
|
||||||
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
|
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
|
||||||
{
|
{
|
||||||
|
@ -84,7 +87,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
|
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Renderer = Renderer;
|
this.Renderer = Renderer;
|
||||||
|
this.ReleaseEvent = ReleaseEvent;
|
||||||
|
|
||||||
BufferQueue = new BufferEntry[0x40];
|
BufferQueue = new BufferEntry[0x40];
|
||||||
|
|
||||||
|
@ -293,6 +297,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
BufferQueue[Slot].State = BufferState.Free;
|
BufferQueue[Slot].State = BufferState.Free;
|
||||||
|
|
||||||
|
ReleaseEvent.Handle.Set();
|
||||||
|
|
||||||
WaitBufferFree.Set();
|
WaitBufferFree.Set();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -377,6 +383,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
||||||
|
|
||||||
Interlocked.Decrement(ref RenderQueueCount);
|
Interlocked.Decrement(ref RenderQueueCount);
|
||||||
|
|
||||||
|
ReleaseEvent.Handle.Set();
|
||||||
|
|
||||||
lock (WaitBufferFree)
|
lock (WaitBufferFree)
|
||||||
{
|
{
|
||||||
WaitBufferFree.Set();
|
WaitBufferFree.Set();
|
||||||
|
|
|
@ -35,7 +35,28 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
Process.HandleTable.CloseHandle(Handle);
|
object Obj = Process.HandleTable.CloseHandle(Handle);
|
||||||
|
|
||||||
|
if (Obj == null)
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to CloseHandle on invalid handle 0x{Handle:x8}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Obj is KSession Session)
|
||||||
|
{
|
||||||
|
Session.Dispose();
|
||||||
|
}
|
||||||
|
else if (Obj is HTransferMem TMem)
|
||||||
|
{
|
||||||
|
TMem.Memory.Manager.Reprotect(
|
||||||
|
TMem.Position,
|
||||||
|
TMem.Size,
|
||||||
|
TMem.Perm);
|
||||||
|
}
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +87,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
int HandlesCount = (int)ThreadState.X2;
|
int HandlesCount = (int)ThreadState.X2;
|
||||||
long Timeout = (long)ThreadState.X3;
|
long Timeout = (long)ThreadState.X3;
|
||||||
|
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
WaitHandle[] Handles = new WaitHandle[HandlesCount];
|
WaitHandle[] Handles = new WaitHandle[HandlesCount];
|
||||||
|
|
||||||
|
@ -142,32 +163,21 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcSendSyncRequest(AThreadState ThreadState)
|
private void SvcSendSyncRequest(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
SendSyncRequest(ThreadState, false);
|
SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
|
private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
SendSyncRequest(ThreadState, true);
|
SendSyncRequest(
|
||||||
|
ThreadState,
|
||||||
|
(long)ThreadState.X0,
|
||||||
|
(long)ThreadState.X1,
|
||||||
|
(int)ThreadState.X2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendSyncRequest(AThreadState ThreadState, bool UserBuffer)
|
private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle)
|
||||||
{
|
{
|
||||||
long CmdPtr = ThreadState.Tpidr;
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
long Size = 0x100;
|
|
||||||
int Handle = 0;
|
|
||||||
|
|
||||||
if (UserBuffer)
|
|
||||||
{
|
|
||||||
CmdPtr = (long)ThreadState.X0;
|
|
||||||
Size = (long)ThreadState.X1;
|
|
||||||
Handle = (int)ThreadState.X2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Handle = (int)ThreadState.X0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
|
||||||
|
|
||||||
byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
|
byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size);
|
||||||
|
|
||||||
|
@ -179,14 +189,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
|
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
|
||||||
|
|
||||||
IpcHandler.IpcCall(
|
IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
|
||||||
Ns,
|
|
||||||
Process,
|
|
||||||
Memory,
|
|
||||||
Session,
|
|
||||||
Cmd,
|
|
||||||
CmdPtr,
|
|
||||||
Handle);
|
|
||||||
|
|
||||||
Thread.Yield();
|
Thread.Yield();
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -53,16 +53,18 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcExitThread(AThreadState ThreadState)
|
private void SvcExitThread(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
CurrThread.Thread.StopExecution();
|
CurrThread.Thread.StopExecution();
|
||||||
|
|
||||||
|
CurrThread.Handle.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcSleepThread(AThreadState ThreadState)
|
private void SvcSleepThread(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
ulong NanoSecs = ThreadState.X0;
|
ulong NanoSecs = ThreadState.X0;
|
||||||
|
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
if (NanoSecs == 0)
|
if (NanoSecs == 0)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +80,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X1;
|
int Handle = (int)ThreadState.X1;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -91,10 +93,10 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcSetThreadPriority(AThreadState ThreadState)
|
private void SvcSetThreadPriority(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
|
int Prio = (int)ThreadState.X0;
|
||||||
int Handle = (int)ThreadState.X1;
|
int Handle = (int)ThreadState.X1;
|
||||||
int Prio = (int)ThreadState.X0;
|
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +119,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(Handle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long MutexAddress = (long)ThreadState.X1;
|
long MutexAddress = (long)ThreadState.X1;
|
||||||
int RequestingThreadHandle = (int)ThreadState.X2;
|
int RequestingThreadHandle = (int)ThreadState.X2;
|
||||||
|
|
||||||
HThread RequestingThread = Process.HandleTable.GetData<HThread>(RequestingThreadHandle);
|
KThread RequestingThread = Process.HandleTable.GetData<KThread>(RequestingThreadHandle);
|
||||||
|
|
||||||
Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);
|
Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
int ThreadHandle = (int)ThreadState.X2;
|
int ThreadHandle = (int)ThreadState.X2;
|
||||||
long Timeout = (long)ThreadState.X3;
|
long Timeout = (long)ThreadState.X3;
|
||||||
|
|
||||||
HThread Thread = Process.HandleTable.GetData<HThread>(ThreadHandle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
|
||||||
|
|
||||||
Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);
|
Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long CondVarAddress = (long)ThreadState.X0;
|
long CondVarAddress = (long)ThreadState.X0;
|
||||||
int Count = (int)ThreadState.X1;
|
int Count = (int)ThreadState.X1;
|
||||||
|
|
||||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
|
if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
using Ryujinx.Graphics.Gal;
|
using Ryujinx.Graphics.Gal;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu
|
namespace Ryujinx.Graphics.Gpu
|
||||||
{
|
{
|
||||||
|
@ -46,24 +45,6 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (NsGpuRegister)0x114:
|
|
||||||
uint BindId = GetRegister((NsGpuRegister)0x11c);
|
|
||||||
|
|
||||||
if (BindId == 0xd)
|
|
||||||
{
|
|
||||||
using (FileStream FS = new FileStream("D:\\macro.bin", FileMode.Create))
|
|
||||||
{
|
|
||||||
BinaryWriter Writer = new BinaryWriter(FS);
|
|
||||||
|
|
||||||
foreach (int arg in Entry.Arguments)
|
|
||||||
{
|
|
||||||
Writer.Write(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//System.Console.WriteLine("macro bind " + Entry.Arguments[0].ToString("x8"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NsGpuRegister._3dVertexArray0Fetch:
|
case NsGpuRegister._3dVertexArray0Fetch:
|
||||||
SendVertexBuffers(Memory);
|
SendVertexBuffers(Memory);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue