mirror of
https://git.743378673.xyz/MeloNX/MeloNX.git
synced 2025-08-02 18:47:10 +02:00
Split main project into core,graphics and chocolarm4 subproject (#29)
This commit is contained in:
parent
cb665bb715
commit
62b827f474
257 changed files with 415 additions and 285 deletions
80
Ryujinx.Core/OsHle/Svc/SvcHandler.cs
Normal file
80
Ryujinx.Core/OsHle/Svc/SvcHandler.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private delegate void SvcFunc(AThreadState ThreadState);
|
||||
|
||||
private Dictionary<int, SvcFunc> SvcFuncs;
|
||||
|
||||
private Switch Ns;
|
||||
private Process Process;
|
||||
private AMemory Memory;
|
||||
|
||||
private static Random Rng;
|
||||
|
||||
public SvcHandler(Switch Ns, Process Process)
|
||||
{
|
||||
SvcFuncs = new Dictionary<int, SvcFunc>()
|
||||
{
|
||||
{ 0x01, SvcSetHeapSize },
|
||||
{ 0x03, SvcSetMemoryAttribute },
|
||||
{ 0x04, SvcMapMemory },
|
||||
{ 0x06, SvcQueryMemory },
|
||||
{ 0x07, SvcExitProcess },
|
||||
{ 0x08, SvcCreateThread },
|
||||
{ 0x09, SvcStartThread },
|
||||
{ 0x0b, SvcSleepThread },
|
||||
{ 0x0c, SvcGetThreadPriority },
|
||||
{ 0x13, SvcMapSharedMemory },
|
||||
{ 0x14, SvcUnmapSharedMemory },
|
||||
{ 0x15, SvcCreateTransferMemory },
|
||||
{ 0x16, SvcCloseHandle },
|
||||
{ 0x17, SvcResetSignal },
|
||||
{ 0x18, SvcWaitSynchronization },
|
||||
{ 0x1a, SvcArbitrateLock },
|
||||
{ 0x1b, SvcArbitrateUnlock },
|
||||
{ 0x1c, SvcWaitProcessWideKeyAtomic },
|
||||
{ 0x1d, SvcSignalProcessWideKey },
|
||||
{ 0x1e, SvcGetSystemTick },
|
||||
{ 0x1f, SvcConnectToNamedPort },
|
||||
{ 0x21, SvcSendSyncRequest },
|
||||
{ 0x22, SvcSendSyncRequestWithUserBuffer },
|
||||
{ 0x26, SvcBreak },
|
||||
{ 0x27, SvcOutputDebugString },
|
||||
{ 0x29, SvcGetInfo }
|
||||
};
|
||||
|
||||
this.Ns = Ns;
|
||||
this.Process = Process;
|
||||
this.Memory = Process.Memory;
|
||||
}
|
||||
|
||||
static SvcHandler()
|
||||
{
|
||||
Rng = new Random();
|
||||
}
|
||||
|
||||
public void SvcCall(object sender, AInstExceptEventArgs e)
|
||||
{
|
||||
AThreadState ThreadState = (AThreadState)sender;
|
||||
|
||||
if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func))
|
||||
{
|
||||
Logging.Trace($"(Thread {ThreadState.ThreadId}) {Func.Method.Name} called.");
|
||||
|
||||
Func(ThreadState);
|
||||
|
||||
Logging.Trace($"(Thread {ThreadState.ThreadId}) {Func.Method.Name} ended.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(e.Id.ToString("x4"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
121
Ryujinx.Core/OsHle/Svc/SvcMemory.cs
Normal file
121
Ryujinx.Core/OsHle/Svc/SvcMemory.cs
Normal file
|
@ -0,0 +1,121 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private void SvcSetHeapSize(AThreadState ThreadState)
|
||||
{
|
||||
uint Size = (uint)ThreadState.X1;
|
||||
|
||||
Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
ThreadState.X1 = (ulong)Memory.Manager.HeapAddr;
|
||||
}
|
||||
|
||||
private void SvcSetMemoryAttribute(AThreadState ThreadState)
|
||||
{
|
||||
long Position = (long)ThreadState.X0;
|
||||
long Size = (long)ThreadState.X1;
|
||||
int State0 = (int)ThreadState.X2;
|
||||
int State1 = (int)ThreadState.X3;
|
||||
|
||||
//TODO
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcMapMemory(AThreadState ThreadState)
|
||||
{
|
||||
long Dst = (long)ThreadState.X0;
|
||||
long Src = (long)ThreadState.X1;
|
||||
long Size = (long)ThreadState.X2;
|
||||
|
||||
Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcQueryMemory(AThreadState ThreadState)
|
||||
{
|
||||
long InfoPtr = (long)ThreadState.X0;
|
||||
long Position = (long)ThreadState.X2;
|
||||
|
||||
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
|
||||
|
||||
MemoryInfo Info = new MemoryInfo(MapInfo);
|
||||
|
||||
Memory.WriteInt64(InfoPtr + 0x00, Info.BaseAddress);
|
||||
Memory.WriteInt64(InfoPtr + 0x08, Info.Size);
|
||||
Memory.WriteInt32(InfoPtr + 0x10, Info.MemType);
|
||||
Memory.WriteInt32(InfoPtr + 0x14, Info.MemAttr);
|
||||
Memory.WriteInt32(InfoPtr + 0x18, Info.MemPerm);
|
||||
Memory.WriteInt32(InfoPtr + 0x1c, Info.IpcRefCount);
|
||||
Memory.WriteInt32(InfoPtr + 0x20, Info.DeviceRefCount);
|
||||
Memory.WriteInt32(InfoPtr + 0x24, Info.Padding);
|
||||
|
||||
//TODO: X1.
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
ThreadState.X1 = 0;
|
||||
}
|
||||
|
||||
private void SvcMapSharedMemory(AThreadState ThreadState)
|
||||
{
|
||||
int Handle = (int)ThreadState.X0;
|
||||
long Src = (long)ThreadState.X1;
|
||||
long Size = (long)ThreadState.X2;
|
||||
int Perm = (int)ThreadState.X3;
|
||||
|
||||
HSharedMem SharedMem = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
||||
|
||||
if (SharedMem != null)
|
||||
{
|
||||
SharedMem.AddVirtualPosition(Src);
|
||||
|
||||
Memory.Manager.MapPhys(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private void SvcUnmapSharedMemory(AThreadState ThreadState)
|
||||
{
|
||||
int Handle = (int)ThreadState.X0;
|
||||
long Position = (long)ThreadState.X1;
|
||||
long Size = (long)ThreadState.X2;
|
||||
|
||||
HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
||||
|
||||
if (HndData != null)
|
||||
{
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private void SvcCreateTransferMemory(AThreadState ThreadState)
|
||||
{
|
||||
long Position = (long)ThreadState.X1;
|
||||
long Size = (long)ThreadState.X2;
|
||||
int Perm = (int)ThreadState.X3;
|
||||
|
||||
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
|
||||
|
||||
Memory.Manager.Reprotect(Position, Size, (AMemoryPerm)Perm);
|
||||
|
||||
HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Position, Size);
|
||||
|
||||
int Handle = Ns.Os.Handles.GenerateId(HndData);
|
||||
|
||||
ThreadState.X1 = (ulong)Handle;
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
11
Ryujinx.Core/OsHle/Svc/SvcResult.cs
Normal file
11
Ryujinx.Core/OsHle/Svc/SvcResult.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Ryujinx.Core.OsHle.Svc
|
||||
{
|
||||
enum SvcResult
|
||||
{
|
||||
Success = 0,
|
||||
ErrBadHandle = 0xe401,
|
||||
ErrTimeout = 0xea01,
|
||||
ErrBadInfo = 0xf001,
|
||||
ErrBadIpcReq = 0xf601
|
||||
}
|
||||
}
|
227
Ryujinx.Core/OsHle/Svc/SvcSystem.cs
Normal file
227
Ryujinx.Core/OsHle/Svc/SvcSystem.cs
Normal file
|
@ -0,0 +1,227 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using Ryujinx.Core.OsHle.Exceptions;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
using Ryujinx.Core.OsHle.Ipc;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private void SvcExitProcess(AThreadState ThreadState) => Ns.Os.ExitProcess(ThreadState.ProcessId);
|
||||
|
||||
private void SvcCloseHandle(AThreadState ThreadState)
|
||||
{
|
||||
int Handle = (int)ThreadState.X0;
|
||||
|
||||
Ns.Os.CloseHandle(Handle);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcResetSignal(AThreadState ThreadState)
|
||||
{
|
||||
int Handle = (int)ThreadState.X0;
|
||||
|
||||
//TODO: Implement events.
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcWaitSynchronization(AThreadState ThreadState)
|
||||
{
|
||||
long HandlesPtr = (long)ThreadState.X0;
|
||||
int HandlesCount = (int)ThreadState.X2;
|
||||
long Timeout = (long)ThreadState.X3;
|
||||
|
||||
//TODO: Implement events.
|
||||
|
||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||
|
||||
Process.Scheduler.Suspend(CurrThread.ProcessorId);
|
||||
Process.Scheduler.Resume(CurrThread);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcGetSystemTick(AThreadState ThreadState)
|
||||
{
|
||||
ThreadState.X0 = (ulong)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.
|
||||
|
||||
HSession Session = new HSession(Name);
|
||||
|
||||
ThreadState.X1 = (ulong)Ns.Os.Handles.GenerateId(Session);
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcSendSyncRequest(AThreadState ThreadState)
|
||||
{
|
||||
SendSyncRequest(ThreadState, false);
|
||||
}
|
||||
|
||||
private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
|
||||
{
|
||||
SendSyncRequest(ThreadState, true);
|
||||
}
|
||||
|
||||
private void SendSyncRequest(AThreadState ThreadState, bool UserBuffer)
|
||||
{
|
||||
long CmdPtr = 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);
|
||||
|
||||
Process.Scheduler.Suspend(CurrThread.ProcessorId);
|
||||
|
||||
byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
|
||||
|
||||
HSession Session = Ns.Os.Handles.GetData<HSession>(Handle);
|
||||
|
||||
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain);
|
||||
|
||||
if (Session != null)
|
||||
{
|
||||
IpcHandler.IpcCall(Ns, Memory, Session, Cmd, CmdPtr, Handle);
|
||||
|
||||
byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
ThreadState.X0 = (int)SvcResult.ErrBadIpcReq;
|
||||
}
|
||||
|
||||
Thread.Yield();
|
||||
|
||||
Process.Scheduler.Resume(CurrThread);
|
||||
}
|
||||
|
||||
private void SvcBreak(AThreadState ThreadState)
|
||||
{
|
||||
long Reason = (long)ThreadState.X0;
|
||||
long Unknown = (long)ThreadState.X1;
|
||||
long Info = (long)ThreadState.X2;
|
||||
|
||||
throw new GuestBrokeExecutionException();
|
||||
}
|
||||
|
||||
private void SvcOutputDebugString(AThreadState ThreadState)
|
||||
{
|
||||
long Position = (long)ThreadState.X0;
|
||||
long Size = (long)ThreadState.X1;
|
||||
|
||||
string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
|
||||
|
||||
Logging.Info($"SvcOutputDebugString: {Str}");
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ThreadState.X0 = (int)SvcResult.ErrBadInfo;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (InfoType)
|
||||
{
|
||||
case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
||||
case 3: ThreadState.X1 = GetMapRegionSize(); break;
|
||||
case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break;
|
||||
case 5: ThreadState.X1 = GetHeapRegionSize(); break;
|
||||
case 6: ThreadState.X1 = GetTotalMem(); break;
|
||||
case 7: ThreadState.X1 = GetUsedMem(); break;
|
||||
case 11: ThreadState.X1 = GetRnd64(); break;
|
||||
case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break;
|
||||
case 13: ThreadState.X1 = GetAddrSpaceSize(); break;
|
||||
case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
||||
case 15: ThreadState.X1 = GetMapRegionSize(); break;
|
||||
|
||||
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
||||
}
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private ulong GetTotalMem()
|
||||
{
|
||||
return (ulong)Memory.Manager.GetTotalMemorySize();
|
||||
}
|
||||
|
||||
private ulong GetUsedMem()
|
||||
{
|
||||
return (ulong)Memory.Manager.GetUsedMemorySize();
|
||||
}
|
||||
|
||||
private ulong GetRnd64()
|
||||
{
|
||||
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
||||
}
|
||||
|
||||
private ulong GetAddrSpaceBaseAddr()
|
||||
{
|
||||
return 0x08000000;
|
||||
}
|
||||
|
||||
private ulong GetAddrSpaceSize()
|
||||
{
|
||||
return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
|
||||
}
|
||||
|
||||
private ulong GetMapRegionBaseAddr()
|
||||
{
|
||||
return 0x80000000;
|
||||
}
|
||||
|
||||
private ulong GetMapRegionSize()
|
||||
{
|
||||
return 0x40000000;
|
||||
}
|
||||
|
||||
private ulong GetHeapRegionBaseAddr()
|
||||
{
|
||||
return GetMapRegionBaseAddr() + GetMapRegionSize();
|
||||
}
|
||||
|
||||
private ulong GetHeapRegionSize()
|
||||
{
|
||||
return 0x40000000;
|
||||
}
|
||||
}
|
||||
}
|
85
Ryujinx.Core/OsHle/Svc/SvcThread.cs
Normal file
85
Ryujinx.Core/OsHle/Svc/SvcThread.cs
Normal file
|
@ -0,0 +1,85 @@
|
|||
using ChocolArm64.State;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Svc
|
||||
{
|
||||
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 (Ns.Os.TryGetProcess(ThreadState.ProcessId, out Process Process))
|
||||
{
|
||||
if (ProcessorId == -2)
|
||||
{
|
||||
//TODO: Get this value from the NPDM file.
|
||||
ProcessorId = 0;
|
||||
}
|
||||
|
||||
int Handle = Process.MakeThread(
|
||||
EntryPoint,
|
||||
StackTop,
|
||||
ArgsPtr,
|
||||
Priority,
|
||||
ProcessorId);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
ThreadState.X1 = (ulong)Handle;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private void SvcStartThread(AThreadState ThreadState)
|
||||
{
|
||||
int Handle = (int)ThreadState.X0;
|
||||
|
||||
HThread Thread = Ns.Os.Handles.GetData<HThread>(Handle);
|
||||
|
||||
if (Thread != null)
|
||||
{
|
||||
Process.Scheduler.StartThread(Thread);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private void SvcSleepThread(AThreadState ThreadState)
|
||||
{
|
||||
ulong NanoSecs = ThreadState.X0;
|
||||
|
||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||
|
||||
if (NanoSecs == 0)
|
||||
{
|
||||
Process.Scheduler.Yield(CurrThread);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process.Scheduler.WaitForSignal(CurrThread, (int)(NanoSecs / 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
private void SvcGetThreadPriority(AThreadState ThreadState)
|
||||
{
|
||||
int Handle = (int)ThreadState.X1;
|
||||
|
||||
HThread Thread = Ns.Os.Handles.GetData<HThread>(Handle);
|
||||
|
||||
if (Thread != null)
|
||||
{
|
||||
ThreadState.X1 = (ulong)Thread.Priority;
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
}
|
||||
}
|
78
Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
Normal file
78
Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using ChocolArm64.State;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private void SvcArbitrateLock(AThreadState ThreadState)
|
||||
{
|
||||
int OwnerThreadHandle = (int)ThreadState.X0;
|
||||
long MutexAddress = (long)ThreadState.X1;
|
||||
int RequestingThreadHandle = (int)ThreadState.X2;
|
||||
|
||||
HThread RequestingThread = Ns.Os.Handles.GetData<HThread>(RequestingThreadHandle);
|
||||
|
||||
Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);
|
||||
|
||||
M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);
|
||||
|
||||
M.WaitForLock(RequestingThread, RequestingThreadHandle);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcArbitrateUnlock(AThreadState ThreadState)
|
||||
{
|
||||
long MutexAddress = (long)ThreadState.X0;
|
||||
|
||||
if (Ns.Os.Mutexes.TryGetValue(MutexAddress, out Mutex M))
|
||||
{
|
||||
M.Unlock();
|
||||
}
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
|
||||
{
|
||||
long MutexAddress = (long)ThreadState.X0;
|
||||
long CondVarAddress = (long)ThreadState.X1;
|
||||
int ThreadHandle = (int)ThreadState.X2;
|
||||
long Timeout = (long)ThreadState.X3;
|
||||
|
||||
HThread Thread = Ns.Os.Handles.GetData<HThread>(ThreadHandle);
|
||||
|
||||
Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);
|
||||
|
||||
M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);
|
||||
|
||||
M.GiveUpLock(ThreadHandle);
|
||||
|
||||
CondVar Cv = new CondVar(Process, CondVarAddress, Timeout);
|
||||
|
||||
Cv = Ns.Os.CondVars.GetOrAdd(CondVarAddress, Cv);
|
||||
|
||||
Cv.WaitForSignal(Thread);
|
||||
|
||||
M.WaitForLock(Thread, ThreadHandle);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcSignalProcessWideKey(AThreadState ThreadState)
|
||||
{
|
||||
long CondVarAddress = (long)ThreadState.X0;
|
||||
int Count = (int)ThreadState.X1;
|
||||
|
||||
HThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||
|
||||
if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
|
||||
{
|
||||
Cv.SetSignal(CurrThread, Count);
|
||||
}
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue