Adjust naming conventions and general refactoring in HLE Project (#490)

* Rename enum fields

* Naming conventions

* Remove unneeded ".this"

* Remove unneeded semicolons

* Remove unused Usings

* Don't use var

* Remove unneeded enum underlying types

* Explicitly label class visibility

* Remove unneeded @ prefixes

* Remove unneeded commas

* Remove unneeded if expressions

* Method doesn't use unsafe code

* Remove unneeded casts

* Initialized objects don't need an empty constructor

* Remove settings from DotSettings

* Revert "Explicitly label class visibility"

This reverts commit ad5eb5787c.

* Small changes

* Revert external enum renaming

* Changes from feedback

* Remove unneeded property setters
This commit is contained in:
Alex Barney
2018-12-04 14:23:37 -06:00
committed by gdkchan
parent c86aacde76
commit 85dbb9559a
299 changed files with 12268 additions and 12276 deletions

View File

@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private class PausableThread
{
public ManualResetEvent Event { get; private set; }
public ManualResetEvent Event { get; }
public bool IsExiting { get; set; }
@ -17,49 +17,49 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
private ConcurrentDictionary<Thread, PausableThread> Threads;
private ConcurrentDictionary<Thread, PausableThread> _threads;
public HleCoreManager()
{
Threads = new ConcurrentDictionary<Thread, PausableThread>();
_threads = new ConcurrentDictionary<Thread, PausableThread>();
}
public void Set(Thread Thread)
public void Set(Thread thread)
{
GetThread(Thread).Event.Set();
GetThread(thread).Event.Set();
}
public void Reset(Thread Thread)
public void Reset(Thread thread)
{
GetThread(Thread).Event.Reset();
GetThread(thread).Event.Reset();
}
public void Wait(Thread Thread)
public void Wait(Thread thread)
{
PausableThread PausableThread = GetThread(Thread);
PausableThread pausableThread = GetThread(thread);
if (!PausableThread.IsExiting)
if (!pausableThread.IsExiting)
{
PausableThread.Event.WaitOne();
pausableThread.Event.WaitOne();
}
}
public void Exit(Thread Thread)
public void Exit(Thread thread)
{
GetThread(Thread).IsExiting = true;
GetThread(thread).IsExiting = true;
}
private PausableThread GetThread(Thread Thread)
private PausableThread GetThread(Thread thread)
{
return Threads.GetOrAdd(Thread, (Key) => new PausableThread());
return _threads.GetOrAdd(thread, (key) => new PausableThread());
}
public void RemoveThread(Thread Thread)
public void RemoveThread(Thread thread)
{
if (Threads.TryRemove(Thread, out PausableThread PausableThread))
if (_threads.TryRemove(thread, out PausableThread pausableThread))
{
PausableThread.Event.Set();
PausableThread.Event.Dispose();
pausableThread.Event.Set();
pausableThread.Event.Dispose();
}
}
}

View File

@ -14,138 +14,138 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private const int Mod0 = 'M' << 0 | 'O' << 8 | 'D' << 16 | '0' << 24;
private KProcess Owner;
private KProcess _owner;
private class Image
{
public long BaseAddress { get; private set; }
public long BaseAddress { get; }
public ElfSymbol[] Symbols { get; private set; }
public ElfSymbol[] Symbols { get; }
public Image(long BaseAddress, ElfSymbol[] Symbols)
public Image(long baseAddress, ElfSymbol[] symbols)
{
this.BaseAddress = BaseAddress;
this.Symbols = Symbols;
BaseAddress = baseAddress;
Symbols = symbols;
}
}
private List<Image> Images;
private List<Image> _images;
private int Loaded;
private int _loaded;
public HleProcessDebugger(KProcess Owner)
public HleProcessDebugger(KProcess owner)
{
this.Owner = Owner;
_owner = owner;
Images = new List<Image>();
_images = new List<Image>();
}
public void PrintGuestStackTrace(CpuThreadState ThreadState)
public void PrintGuestStackTrace(CpuThreadState threadState)
{
EnsureLoaded();
StringBuilder Trace = new StringBuilder();
StringBuilder trace = new StringBuilder();
Trace.AppendLine("Guest stack trace:");
trace.AppendLine("Guest stack trace:");
void AppendTrace(long Address)
void AppendTrace(long address)
{
Image Image = GetImage(Address, out int ImageIndex);
Image image = GetImage(address, out int imageIndex);
if (Image == null || !TryGetSubName(Image, Address, out string SubName))
if (image == null || !TryGetSubName(image, address, out string subName))
{
SubName = $"Sub{Address:x16}";
subName = $"Sub{address:x16}";
}
else if (SubName.StartsWith("_Z"))
else if (subName.StartsWith("_Z"))
{
SubName = Demangler.Parse(SubName);
subName = Demangler.Parse(subName);
}
if (Image != null)
if (image != null)
{
long Offset = Address - Image.BaseAddress;
long offset = address - image.BaseAddress;
string ImageName = GetGuessedNsoNameFromIndex(ImageIndex);
string imageName = GetGuessedNsoNameFromIndex(imageIndex);
string ImageNameAndOffset = $"[{Owner.Name}] {ImageName}:0x{Offset:x8}";
string imageNameAndOffset = $"[{_owner.Name}] {imageName}:0x{offset:x8}";
Trace.AppendLine($" {ImageNameAndOffset} {SubName}");
trace.AppendLine($" {imageNameAndOffset} {subName}");
}
else
{
Trace.AppendLine($" [{Owner.Name}] ??? {SubName}");
trace.AppendLine($" [{_owner.Name}] ??? {subName}");
}
}
long FramePointer = (long)ThreadState.X29;
long framePointer = (long)threadState.X29;
while (FramePointer != 0)
while (framePointer != 0)
{
if ((FramePointer & 7) != 0 ||
!Owner.CpuMemory.IsMapped(FramePointer) ||
!Owner.CpuMemory.IsMapped(FramePointer + 8))
if ((framePointer & 7) != 0 ||
!_owner.CpuMemory.IsMapped(framePointer) ||
!_owner.CpuMemory.IsMapped(framePointer + 8))
{
break;
}
//Note: This is the return address, we need to subtract one instruction
//worth of bytes to get the branch instruction address.
AppendTrace(Owner.CpuMemory.ReadInt64(FramePointer + 8) - 4);
AppendTrace(_owner.CpuMemory.ReadInt64(framePointer + 8) - 4);
FramePointer = Owner.CpuMemory.ReadInt64(FramePointer);
framePointer = _owner.CpuMemory.ReadInt64(framePointer);
}
Logger.PrintInfo(LogClass.Cpu, Trace.ToString());
Logger.PrintInfo(LogClass.Cpu, trace.ToString());
}
private bool TryGetSubName(Image Image, long Address, out string Name)
private bool TryGetSubName(Image image, long address, out string name)
{
Address -= Image.BaseAddress;
address -= image.BaseAddress;
int Left = 0;
int Right = Image.Symbols.Length - 1;
int left = 0;
int right = image.Symbols.Length - 1;
while (Left <= Right)
while (left <= right)
{
int Size = Right - Left;
int size = right - left;
int Middle = Left + (Size >> 1);
int middle = left + (size >> 1);
ElfSymbol Symbol = Image.Symbols[Middle];
ElfSymbol symbol = image.Symbols[middle];
long EndAddr = Symbol.Value + Symbol.Size;
long endAddr = symbol.Value + symbol.Size;
if ((ulong)Address >= (ulong)Symbol.Value && (ulong)Address < (ulong)EndAddr)
if ((ulong)address >= (ulong)symbol.Value && (ulong)address < (ulong)endAddr)
{
Name = Symbol.Name;
name = symbol.Name;
return true;
}
if ((ulong)Address < (ulong)Symbol.Value)
if ((ulong)address < (ulong)symbol.Value)
{
Right = Middle - 1;
right = middle - 1;
}
else
{
Left = Middle + 1;
left = middle + 1;
}
}
Name = null;
name = null;
return false;
}
private Image GetImage(long Address, out int Index)
private Image GetImage(long address, out int index)
{
lock (Images)
lock (_images)
{
for (Index = Images.Count - 1; Index >= 0; Index--)
for (index = _images.Count - 1; index >= 0; index--)
{
if ((ulong)Address >= (ulong)Images[Index].BaseAddress)
if ((ulong)address >= (ulong)_images[index].BaseAddress)
{
return Images[Index];
return _images[index];
}
}
}
@ -153,42 +153,42 @@ namespace Ryujinx.HLE.HOS.Kernel
return null;
}
private string GetGuessedNsoNameFromIndex(int Index)
private string GetGuessedNsoNameFromIndex(int index)
{
if ((uint)Index > 11)
if ((uint)index > 11)
{
return "???";
}
if (Index == 0)
if (index == 0)
{
return "rtld";
}
else if (Index == 1)
else if (index == 1)
{
return "main";
}
else if (Index == GetImagesCount() - 1)
else if (index == GetImagesCount() - 1)
{
return "sdk";
}
else
{
return "subsdk" + (Index - 2);
return "subsdk" + (index - 2);
}
}
private int GetImagesCount()
{
lock (Images)
lock (_images)
{
return Images.Count;
return _images.Count;
}
}
private void EnsureLoaded()
{
if (Interlocked.CompareExchange(ref Loaded, 1, 0) == 0)
if (Interlocked.CompareExchange(ref _loaded, 1, 0) == 0)
{
ScanMemoryForTextSegments();
}
@ -196,115 +196,115 @@ namespace Ryujinx.HLE.HOS.Kernel
private void ScanMemoryForTextSegments()
{
ulong OldAddress = 0;
ulong Address = 0;
ulong oldAddress = 0;
ulong address = 0;
while (Address >= OldAddress)
while (address >= oldAddress)
{
KMemoryInfo Info = Owner.MemoryManager.QueryMemory(Address);
KMemoryInfo info = _owner.MemoryManager.QueryMemory(address);
if (Info.State == MemoryState.Reserved)
if (info.State == MemoryState.Reserved)
{
break;
}
if (Info.State == MemoryState.CodeStatic && Info.Permission == MemoryPermission.ReadAndExecute)
if (info.State == MemoryState.CodeStatic && info.Permission == MemoryPermission.ReadAndExecute)
{
LoadMod0Symbols(Owner.CpuMemory, (long)Info.Address);
LoadMod0Symbols(_owner.CpuMemory, (long)info.Address);
}
OldAddress = Address;
oldAddress = address;
Address = Info.Address + Info.Size;
address = info.Address + info.Size;
}
}
private void LoadMod0Symbols(MemoryManager Memory, long TextOffset)
private void LoadMod0Symbols(MemoryManager memory, long textOffset)
{
long Mod0Offset = TextOffset + Memory.ReadUInt32(TextOffset + 4);
long mod0Offset = textOffset + memory.ReadUInt32(textOffset + 4);
if (Mod0Offset < TextOffset || !Memory.IsMapped(Mod0Offset) || (Mod0Offset & 3) != 0)
if (mod0Offset < textOffset || !memory.IsMapped(mod0Offset) || (mod0Offset & 3) != 0)
{
return;
}
Dictionary<ElfDynamicTag, long> Dynamic = new Dictionary<ElfDynamicTag, long>();
Dictionary<ElfDynamicTag, long> dynamic = new Dictionary<ElfDynamicTag, long>();
int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0);
int mod0Magic = memory.ReadInt32(mod0Offset + 0x0);
if (Mod0Magic != Mod0)
if (mod0Magic != Mod0)
{
return;
}
long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset;
long BssStartOffset = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset;
long BssEndOffset = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset;
long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset;
long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset;
long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset;
long dynamicOffset = memory.ReadInt32(mod0Offset + 0x4) + mod0Offset;
long bssStartOffset = memory.ReadInt32(mod0Offset + 0x8) + mod0Offset;
long bssEndOffset = memory.ReadInt32(mod0Offset + 0xc) + mod0Offset;
long ehHdrStartOffset = memory.ReadInt32(mod0Offset + 0x10) + mod0Offset;
long ehHdrEndOffset = memory.ReadInt32(mod0Offset + 0x14) + mod0Offset;
long modObjOffset = memory.ReadInt32(mod0Offset + 0x18) + mod0Offset;
while (true)
{
long TagVal = Memory.ReadInt64(DynamicOffset + 0);
long Value = Memory.ReadInt64(DynamicOffset + 8);
long tagVal = memory.ReadInt64(dynamicOffset + 0);
long value = memory.ReadInt64(dynamicOffset + 8);
DynamicOffset += 0x10;
dynamicOffset += 0x10;
ElfDynamicTag Tag = (ElfDynamicTag)TagVal;
ElfDynamicTag tag = (ElfDynamicTag)tagVal;
if (Tag == ElfDynamicTag.DT_NULL)
if (tag == ElfDynamicTag.DT_NULL)
{
break;
}
Dynamic[Tag] = Value;
dynamic[tag] = value;
}
if (!Dynamic.TryGetValue(ElfDynamicTag.DT_STRTAB, out long StrTab) ||
!Dynamic.TryGetValue(ElfDynamicTag.DT_SYMTAB, out long SymTab) ||
!Dynamic.TryGetValue(ElfDynamicTag.DT_SYMENT, out long SymEntSize))
if (!dynamic.TryGetValue(ElfDynamicTag.DT_STRTAB, out long strTab) ||
!dynamic.TryGetValue(ElfDynamicTag.DT_SYMTAB, out long symTab) ||
!dynamic.TryGetValue(ElfDynamicTag.DT_SYMENT, out long symEntSize))
{
return;
}
long StrTblAddr = TextOffset + StrTab;
long SymTblAddr = TextOffset + SymTab;
long strTblAddr = textOffset + strTab;
long symTblAddr = textOffset + symTab;
List<ElfSymbol> Symbols = new List<ElfSymbol>();
List<ElfSymbol> symbols = new List<ElfSymbol>();
while ((ulong)SymTblAddr < (ulong)StrTblAddr)
while ((ulong)symTblAddr < (ulong)strTblAddr)
{
ElfSymbol Sym = GetSymbol(Memory, SymTblAddr, StrTblAddr);
ElfSymbol sym = GetSymbol(memory, symTblAddr, strTblAddr);
Symbols.Add(Sym);
symbols.Add(sym);
SymTblAddr += SymEntSize;
symTblAddr += symEntSize;
}
lock (Images)
lock (_images)
{
Images.Add(new Image(TextOffset, Symbols.OrderBy(x => x.Value).ToArray()));
_images.Add(new Image(textOffset, symbols.OrderBy(x => x.Value).ToArray()));
}
}
private ElfSymbol GetSymbol(MemoryManager Memory, long Address, long StrTblAddr)
private ElfSymbol GetSymbol(MemoryManager memory, long address, long strTblAddr)
{
int NameIndex = Memory.ReadInt32(Address + 0);
int Info = Memory.ReadByte (Address + 4);
int Other = Memory.ReadByte (Address + 5);
int SHIdx = Memory.ReadInt16(Address + 6);
long Value = Memory.ReadInt64(Address + 8);
long Size = Memory.ReadInt64(Address + 16);
int nameIndex = memory.ReadInt32(address + 0);
int info = memory.ReadByte (address + 4);
int other = memory.ReadByte (address + 5);
int shIdx = memory.ReadInt16(address + 6);
long value = memory.ReadInt64(address + 8);
long size = memory.ReadInt64(address + 16);
string Name = string.Empty;
string name = string.Empty;
for (int Chr; (Chr = Memory.ReadByte(StrTblAddr + NameIndex++)) != 0;)
for (int chr; (chr = memory.ReadByte(strTblAddr + nameIndex++)) != 0;)
{
Name += (char)Chr;
name += (char)chr;
}
return new ElfSymbol(Name, Info, Other, SHIdx, Value, Size);
return new ElfSymbol(name, info, other, shIdx, value, size);
}
}
}

View File

@ -7,21 +7,21 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private const int RoundRobinTimeQuantumMs = 10;
private int CurrentCore;
private int _currentCore;
public bool MultiCoreScheduling { get; set; }
public HleCoreManager CoreManager { get; private set; }
public HleCoreManager CoreManager { get; }
private bool KeepPreempting;
private bool _keepPreempting;
public void StartAutoPreemptionThread()
{
Thread PreemptionThread = new Thread(PreemptCurrentThread);
Thread preemptionThread = new Thread(PreemptCurrentThread);
KeepPreempting = true;
_keepPreempting = true;
PreemptionThread.Start();
preemptionThread.Start();
}
public void ContextSwitch()
@ -30,28 +30,28 @@ namespace Ryujinx.HLE.HOS.Kernel
{
if (MultiCoreScheduling)
{
int SelectedCount = 0;
int selectedCount = 0;
for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
for (int core = 0; core < CpuCoresCount; core++)
{
KCoreContext CoreContext = CoreContexts[Core];
KCoreContext coreContext = CoreContexts[core];
if (CoreContext.ContextSwitchNeeded && (CoreContext.CurrentThread?.Context.IsCurrentThread() ?? false))
if (coreContext.ContextSwitchNeeded && (coreContext.CurrentThread?.Context.IsCurrentThread() ?? false))
{
CoreContext.ContextSwitch();
coreContext.ContextSwitch();
}
if (CoreContext.CurrentThread?.Context.IsCurrentThread() ?? false)
if (coreContext.CurrentThread?.Context.IsCurrentThread() ?? false)
{
SelectedCount++;
selectedCount++;
}
}
if (SelectedCount == 0)
if (selectedCount == 0)
{
CoreManager.Reset(Thread.CurrentThread);
}
else if (SelectedCount == 1)
else if (selectedCount == 1)
{
CoreManager.Set(Thread.CurrentThread);
}
@ -62,41 +62,41 @@ namespace Ryujinx.HLE.HOS.Kernel
}
else
{
KThread CurrentThread = CoreContexts[CurrentCore].CurrentThread;
KThread currentThread = CoreContexts[_currentCore].CurrentThread;
bool HasThreadExecuting = CurrentThread != null;
bool hasThreadExecuting = currentThread != null;
if (HasThreadExecuting)
if (hasThreadExecuting)
{
//If this is not the thread that is currently executing, we need
//to request an interrupt to allow safely starting another thread.
if (!CurrentThread.Context.IsCurrentThread())
if (!currentThread.Context.IsCurrentThread())
{
CurrentThread.Context.RequestInterrupt();
currentThread.Context.RequestInterrupt();
return;
}
CoreManager.Reset(CurrentThread.Context.Work);
CoreManager.Reset(currentThread.Context.Work);
}
//Advance current core and try picking a thread,
//keep advancing if it is null.
for (int Core = 0; Core < 4; Core++)
for (int core = 0; core < 4; core++)
{
CurrentCore = (CurrentCore + 1) % CpuCoresCount;
_currentCore = (_currentCore + 1) % CpuCoresCount;
KCoreContext CoreContext = CoreContexts[CurrentCore];
KCoreContext coreContext = CoreContexts[_currentCore];
CoreContext.UpdateCurrentThread();
coreContext.UpdateCurrentThread();
if (CoreContext.CurrentThread != null)
if (coreContext.CurrentThread != null)
{
CoreContext.CurrentThread.ClearExclusive();
coreContext.CurrentThread.ClearExclusive();
CoreManager.Set(CoreContext.CurrentThread.Context.Work);
CoreManager.Set(coreContext.CurrentThread.Context.Work);
CoreContext.CurrentThread.Context.Execute();
coreContext.CurrentThread.Context.Execute();
break;
}
@ -104,7 +104,7 @@ namespace Ryujinx.HLE.HOS.Kernel
//If nothing was running before, then we are on a "external"
//HLE thread, we don't need to wait.
if (!HasThreadExecuting)
if (!hasThreadExecuting)
{
return;
}
@ -119,13 +119,13 @@ namespace Ryujinx.HLE.HOS.Kernel
//Preempts current thread every 10 milliseconds on a round-robin fashion,
//when multi core scheduling is disabled, to try ensuring that all threads
//gets a chance to run.
while (KeepPreempting)
while (_keepPreempting)
{
lock (CoreContexts)
{
KThread CurrentThread = CoreContexts[CurrentCore].CurrentThread;
KThread currentThread = CoreContexts[_currentCore].CurrentThread;
CurrentThread?.Context.RequestInterrupt();
currentThread?.Context.RequestInterrupt();
}
PreemptThreads();
@ -134,16 +134,16 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
public void ExitThread(KThread Thread)
public void ExitThread(KThread thread)
{
Thread.Context.StopExecution();
thread.Context.StopExecution();
CoreManager.Exit(Thread.Context.Work);
CoreManager.Exit(thread.Context.Work);
}
public void RemoveThread(KThread Thread)
public void RemoveThread(KThread thread)
{
CoreManager.RemoveThread(Thread.Context.Work);
CoreManager.RemoveThread(thread.Context.Work);
}
}
}

View File

@ -9,641 +9,641 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private const int HasListenersMask = 0x40000000;
private Horizon System;
private Horizon _system;
public List<KThread> CondVarThreads;
public List<KThread> ArbiterThreads;
public KAddressArbiter(Horizon System)
public KAddressArbiter(Horizon system)
{
this.System = System;
_system = system;
CondVarThreads = new List<KThread>();
ArbiterThreads = new List<KThread>();
}
public long ArbitrateLock(int OwnerHandle, long MutexAddress, int RequesterHandle)
public long ArbitrateLock(int ownerHandle, long mutexAddress, int requesterHandle)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
CurrentThread.SignaledObj = null;
CurrentThread.ObjSyncResult = 0;
currentThread.SignaledObj = null;
currentThread.ObjSyncResult = 0;
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if (!KernelTransfer.UserToKernelInt32(System, MutexAddress, out int MutexValue))
if (!KernelTransfer.UserToKernelInt32(_system, mutexAddress, out int mutexValue))
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);;
return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
}
if (MutexValue != (OwnerHandle | HasListenersMask))
if (mutexValue != (ownerHandle | HasListenersMask))
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return 0;
}
KThread MutexOwner = CurrentProcess.HandleTable.GetObject<KThread>(OwnerHandle);
KThread mutexOwner = currentProcess.HandleTable.GetObject<KThread>(ownerHandle);
if (MutexOwner == null)
if (mutexOwner == null)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
}
CurrentThread.MutexAddress = MutexAddress;
CurrentThread.ThreadHandleForUserMutex = RequesterHandle;
currentThread.MutexAddress = mutexAddress;
currentThread.ThreadHandleForUserMutex = requesterHandle;
MutexOwner.AddMutexWaiter(CurrentThread);
mutexOwner.AddMutexWaiter(currentThread);
CurrentThread.Reschedule(ThreadSchedState.Paused);
currentThread.Reschedule(ThreadSchedState.Paused);
System.CriticalSection.Leave();
System.CriticalSection.Enter();
_system.CriticalSection.Leave();
_system.CriticalSection.Enter();
if (CurrentThread.MutexOwner != null)
if (currentThread.MutexOwner != null)
{
CurrentThread.MutexOwner.RemoveMutexWaiter(CurrentThread);
currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return (uint)CurrentThread.ObjSyncResult;
return (uint)currentThread.ObjSyncResult;
}
public long ArbitrateUnlock(long MutexAddress)
public long ArbitrateUnlock(long mutexAddress)
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
(long Result, KThread NewOwnerThread) = MutexUnlock(CurrentThread, MutexAddress);
(long result, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress);
if (Result != 0 && NewOwnerThread != null)
if (result != 0 && newOwnerThread != null)
{
NewOwnerThread.SignaledObj = null;
NewOwnerThread.ObjSyncResult = (int)Result;
newOwnerThread.SignaledObj = null;
newOwnerThread.ObjSyncResult = (int)result;
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return Result;
return result;
}
public long WaitProcessWideKeyAtomic(
long MutexAddress,
long CondVarAddress,
int ThreadHandle,
long Timeout)
long mutexAddress,
long condVarAddress,
int threadHandle,
long timeout)
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
CurrentThread.SignaledObj = null;
CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);
currentThread.SignaledObj = null;
currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);
if (CurrentThread.ShallBeTerminated ||
CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
if (currentThread.ShallBeTerminated ||
currentThread.SchedFlags == ThreadSchedState.TerminationPending)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
}
(long Result, _) = MutexUnlock(CurrentThread, MutexAddress);
(long result, _) = MutexUnlock(currentThread, mutexAddress);
if (Result != 0)
if (result != 0)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return Result;
return result;
}
CurrentThread.MutexAddress = MutexAddress;
CurrentThread.ThreadHandleForUserMutex = ThreadHandle;
CurrentThread.CondVarAddress = CondVarAddress;
currentThread.MutexAddress = mutexAddress;
currentThread.ThreadHandleForUserMutex = threadHandle;
currentThread.CondVarAddress = condVarAddress;
CondVarThreads.Add(CurrentThread);
CondVarThreads.Add(currentThread);
if (Timeout != 0)
if (timeout != 0)
{
CurrentThread.Reschedule(ThreadSchedState.Paused);
currentThread.Reschedule(ThreadSchedState.Paused);
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
_system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
}
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.UnscheduleFutureInvocation(CurrentThread);
_system.TimeManager.UnscheduleFutureInvocation(currentThread);
}
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
if (CurrentThread.MutexOwner != null)
if (currentThread.MutexOwner != null)
{
CurrentThread.MutexOwner.RemoveMutexWaiter(CurrentThread);
currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
}
CondVarThreads.Remove(CurrentThread);
CondVarThreads.Remove(currentThread);
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return (uint)CurrentThread.ObjSyncResult;
return (uint)currentThread.ObjSyncResult;
}
private (long, KThread) MutexUnlock(KThread CurrentThread, long MutexAddress)
private (long, KThread) MutexUnlock(KThread currentThread, long mutexAddress)
{
KThread NewOwnerThread = CurrentThread.RelinquishMutex(MutexAddress, out int Count);
KThread newOwnerThread = currentThread.RelinquishMutex(mutexAddress, out int count);
int MutexValue = 0;
int mutexValue = 0;
if (NewOwnerThread != null)
if (newOwnerThread != null)
{
MutexValue = NewOwnerThread.ThreadHandleForUserMutex;
mutexValue = newOwnerThread.ThreadHandleForUserMutex;
if (Count >= 2)
if (count >= 2)
{
MutexValue |= HasListenersMask;
mutexValue |= HasListenersMask;
}
NewOwnerThread.SignaledObj = null;
NewOwnerThread.ObjSyncResult = 0;
newOwnerThread.SignaledObj = null;
newOwnerThread.ObjSyncResult = 0;
NewOwnerThread.ReleaseAndResume();
newOwnerThread.ReleaseAndResume();
}
long Result = 0;
long result = 0;
if (!KernelTransfer.KernelToUserInt32(System, MutexAddress, MutexValue))
if (!KernelTransfer.KernelToUserInt32(_system, mutexAddress, mutexValue))
{
Result = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
result = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
}
return (Result, NewOwnerThread);
return (result, newOwnerThread);
}
public void SignalProcessWideKey(long Address, int Count)
public void SignalProcessWideKey(long address, int count)
{
Queue<KThread> SignaledThreads = new Queue<KThread>();
Queue<KThread> signaledThreads = new Queue<KThread>();
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
IOrderedEnumerable<KThread> SortedThreads = CondVarThreads.OrderBy(x => x.DynamicPriority);
IOrderedEnumerable<KThread> sortedThreads = CondVarThreads.OrderBy(x => x.DynamicPriority);
foreach (KThread Thread in SortedThreads.Where(x => x.CondVarAddress == Address))
foreach (KThread thread in sortedThreads.Where(x => x.CondVarAddress == address))
{
TryAcquireMutex(Thread);
TryAcquireMutex(thread);
SignaledThreads.Enqueue(Thread);
signaledThreads.Enqueue(thread);
//If the count is <= 0, we should signal all threads waiting.
if (Count >= 1 && --Count == 0)
if (count >= 1 && --count == 0)
{
break;
}
}
while (SignaledThreads.TryDequeue(out KThread Thread))
while (signaledThreads.TryDequeue(out KThread thread))
{
CondVarThreads.Remove(Thread);
CondVarThreads.Remove(thread);
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
}
private KThread TryAcquireMutex(KThread Requester)
private KThread TryAcquireMutex(KThread requester)
{
long Address = Requester.MutexAddress;
long address = requester.MutexAddress;
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
if (!KernelTransfer.UserToKernelInt32(System, Address, out int MutexValue))
if (!KernelTransfer.UserToKernelInt32(_system, address, out int mutexValue))
{
//Invalid address.
CurrentProcess.CpuMemory.ClearExclusive(0);
currentProcess.CpuMemory.ClearExclusive(0);
Requester.SignaledObj = null;
Requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
requester.SignaledObj = null;
requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return null;
}
while (true)
{
if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
if (currentProcess.CpuMemory.TestExclusive(0, address))
{
if (MutexValue != 0)
if (mutexValue != 0)
{
//Update value to indicate there is a mutex waiter now.
CurrentProcess.CpuMemory.WriteInt32(Address, MutexValue | HasListenersMask);
currentProcess.CpuMemory.WriteInt32(address, mutexValue | HasListenersMask);
}
else
{
//No thread owning the mutex, assign to requesting thread.
CurrentProcess.CpuMemory.WriteInt32(Address, Requester.ThreadHandleForUserMutex);
currentProcess.CpuMemory.WriteInt32(address, requester.ThreadHandleForUserMutex);
}
CurrentProcess.CpuMemory.ClearExclusiveForStore(0);
currentProcess.CpuMemory.ClearExclusiveForStore(0);
break;
}
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
MutexValue = CurrentProcess.CpuMemory.ReadInt32(Address);
mutexValue = currentProcess.CpuMemory.ReadInt32(address);
}
if (MutexValue == 0)
if (mutexValue == 0)
{
//We now own the mutex.
Requester.SignaledObj = null;
Requester.ObjSyncResult = 0;
requester.SignaledObj = null;
requester.ObjSyncResult = 0;
Requester.ReleaseAndResume();
requester.ReleaseAndResume();
return null;
}
MutexValue &= ~HasListenersMask;
mutexValue &= ~HasListenersMask;
KThread MutexOwner = CurrentProcess.HandleTable.GetObject<KThread>(MutexValue);
KThread mutexOwner = currentProcess.HandleTable.GetObject<KThread>(mutexValue);
if (MutexOwner != null)
if (mutexOwner != null)
{
//Mutex already belongs to another thread, wait for it.
MutexOwner.AddMutexWaiter(Requester);
mutexOwner.AddMutexWaiter(requester);
}
else
{
//Invalid mutex owner.
Requester.SignaledObj = null;
Requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
requester.SignaledObj = null;
requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
Requester.ReleaseAndResume();
requester.ReleaseAndResume();
}
return MutexOwner;
return mutexOwner;
}
public long WaitForAddressIfEqual(long Address, int Value, long Timeout)
public long WaitForAddressIfEqual(long address, int value, long timeout)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
if (CurrentThread.ShallBeTerminated ||
CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
if (currentThread.ShallBeTerminated ||
currentThread.SchedFlags == ThreadSchedState.TerminationPending)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
}
CurrentThread.SignaledObj = null;
CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);
currentThread.SignaledObj = null;
currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);
if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
}
if (CurrentValue == Value)
if (currentValue == value)
{
if (Timeout == 0)
if (timeout == 0)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.Timeout);
}
CurrentThread.MutexAddress = Address;
CurrentThread.WaitingInArbitration = true;
currentThread.MutexAddress = address;
currentThread.WaitingInArbitration = true;
InsertSortedByPriority(ArbiterThreads, CurrentThread);
InsertSortedByPriority(ArbiterThreads, currentThread);
CurrentThread.Reschedule(ThreadSchedState.Paused);
currentThread.Reschedule(ThreadSchedState.Paused);
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
_system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.UnscheduleFutureInvocation(CurrentThread);
_system.TimeManager.UnscheduleFutureInvocation(currentThread);
}
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
if (CurrentThread.WaitingInArbitration)
if (currentThread.WaitingInArbitration)
{
ArbiterThreads.Remove(CurrentThread);
ArbiterThreads.Remove(currentThread);
CurrentThread.WaitingInArbitration = false;
currentThread.WaitingInArbitration = false;
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return CurrentThread.ObjSyncResult;
return currentThread.ObjSyncResult;
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
}
public long WaitForAddressIfLessThan(long Address, int Value, bool ShouldDecrement, long Timeout)
public long WaitForAddressIfLessThan(long address, int value, bool shouldDecrement, long timeout)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
if (CurrentThread.ShallBeTerminated ||
CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
if (currentThread.ShallBeTerminated ||
currentThread.SchedFlags == ThreadSchedState.TerminationPending)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
}
CurrentThread.SignaledObj = null;
CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);
currentThread.SignaledObj = null;
currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
//If ShouldDecrement is true, do atomic decrement of the value at Address.
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
}
if (ShouldDecrement)
if (shouldDecrement)
{
while (CurrentValue < Value)
while (currentValue < value)
{
if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
if (currentProcess.CpuMemory.TestExclusive(0, address))
{
CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue - 1);
currentProcess.CpuMemory.WriteInt32(address, currentValue - 1);
CurrentProcess.CpuMemory.ClearExclusiveForStore(0);
currentProcess.CpuMemory.ClearExclusiveForStore(0);
break;
}
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
currentValue = currentProcess.CpuMemory.ReadInt32(address);
}
}
CurrentProcess.CpuMemory.ClearExclusive(0);
currentProcess.CpuMemory.ClearExclusive(0);
if (CurrentValue < Value)
if (currentValue < value)
{
if (Timeout == 0)
if (timeout == 0)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.Timeout);
}
CurrentThread.MutexAddress = Address;
CurrentThread.WaitingInArbitration = true;
currentThread.MutexAddress = address;
currentThread.WaitingInArbitration = true;
InsertSortedByPriority(ArbiterThreads, CurrentThread);
InsertSortedByPriority(ArbiterThreads, currentThread);
CurrentThread.Reschedule(ThreadSchedState.Paused);
currentThread.Reschedule(ThreadSchedState.Paused);
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
_system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.UnscheduleFutureInvocation(CurrentThread);
_system.TimeManager.UnscheduleFutureInvocation(currentThread);
}
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
if (CurrentThread.WaitingInArbitration)
if (currentThread.WaitingInArbitration)
{
ArbiterThreads.Remove(CurrentThread);
ArbiterThreads.Remove(currentThread);
CurrentThread.WaitingInArbitration = false;
currentThread.WaitingInArbitration = false;
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return CurrentThread.ObjSyncResult;
return currentThread.ObjSyncResult;
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
}
private void InsertSortedByPriority(List<KThread> Threads, KThread Thread)
private void InsertSortedByPriority(List<KThread> threads, KThread thread)
{
int NextIndex = -1;
int nextIndex = -1;
for (int Index = 0; Index < Threads.Count; Index++)
for (int index = 0; index < threads.Count; index++)
{
if (Threads[Index].DynamicPriority > Thread.DynamicPriority)
if (threads[index].DynamicPriority > thread.DynamicPriority)
{
NextIndex = Index;
nextIndex = index;
break;
}
}
if (NextIndex != -1)
if (nextIndex != -1)
{
Threads.Insert(NextIndex, Thread);
threads.Insert(nextIndex, thread);
}
else
{
Threads.Add(Thread);
threads.Add(thread);
}
}
public long Signal(long Address, int Count)
public long Signal(long address, int count)
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
WakeArbiterThreads(Address, Count);
WakeArbiterThreads(address, count);
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return 0;
}
public long SignalAndIncrementIfEqual(long Address, int Value, int Count)
public long SignalAndIncrementIfEqual(long address, int value, int count)
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
}
while (CurrentValue == Value)
while (currentValue == value)
{
if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
if (currentProcess.CpuMemory.TestExclusive(0, address))
{
CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue + 1);
currentProcess.CpuMemory.WriteInt32(address, currentValue + 1);
CurrentProcess.CpuMemory.ClearExclusiveForStore(0);
currentProcess.CpuMemory.ClearExclusiveForStore(0);
break;
}
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
currentValue = currentProcess.CpuMemory.ReadInt32(address);
}
CurrentProcess.CpuMemory.ClearExclusive(0);
currentProcess.CpuMemory.ClearExclusive(0);
if (CurrentValue != Value)
if (currentValue != value)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
}
WakeArbiterThreads(Address, Count);
WakeArbiterThreads(address, count);
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return 0;
}
public long SignalAndModifyIfEqual(long Address, int Value, int Count)
public long SignalAndModifyIfEqual(long address, int value, int count)
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
int Offset;
int offset;
//The value is decremented if the number of threads waiting is less
//or equal to the Count of threads to be signaled, or Count is zero
//or negative. It is incremented if there are no threads waiting.
int WaitingCount = 0;
int waitingCount = 0;
foreach (KThread Thread in ArbiterThreads.Where(x => x.MutexAddress == Address))
foreach (KThread thread in ArbiterThreads.Where(x => x.MutexAddress == address))
{
if (++WaitingCount > Count)
if (++waitingCount > count)
{
break;
}
}
if (WaitingCount > 0)
if (waitingCount > 0)
{
Offset = WaitingCount <= Count || Count <= 0 ? -1 : 0;
offset = waitingCount <= count || count <= 0 ? -1 : 0;
}
else
{
Offset = 1;
offset = 1;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue))
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
}
while (CurrentValue == Value)
while (currentValue == value)
{
if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
if (currentProcess.CpuMemory.TestExclusive(0, address))
{
CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue + Offset);
currentProcess.CpuMemory.WriteInt32(address, currentValue + offset);
CurrentProcess.CpuMemory.ClearExclusiveForStore(0);
currentProcess.CpuMemory.ClearExclusiveForStore(0);
break;
}
CurrentProcess.CpuMemory.SetExclusive(0, Address);
currentProcess.CpuMemory.SetExclusive(0, address);
CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
currentValue = currentProcess.CpuMemory.ReadInt32(address);
}
CurrentProcess.CpuMemory.ClearExclusive(0);
currentProcess.CpuMemory.ClearExclusive(0);
if (CurrentValue != Value)
if (currentValue != value)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
}
WakeArbiterThreads(Address, Count);
WakeArbiterThreads(address, count);
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return 0;
}
private void WakeArbiterThreads(long Address, int Count)
private void WakeArbiterThreads(long address, int count)
{
Queue<KThread> SignaledThreads = new Queue<KThread>();
Queue<KThread> signaledThreads = new Queue<KThread>();
foreach (KThread Thread in ArbiterThreads.Where(x => x.MutexAddress == Address))
foreach (KThread thread in ArbiterThreads.Where(x => x.MutexAddress == address))
{
SignaledThreads.Enqueue(Thread);
signaledThreads.Enqueue(thread);
//If the count is <= 0, we should signal all threads waiting.
if (Count >= 1 && --Count == 0)
if (count >= 1 && --count == 0)
{
break;
}
}
while (SignaledThreads.TryDequeue(out KThread Thread))
while (signaledThreads.TryDequeue(out KThread thread))
{
Thread.SignaledObj = null;
Thread.ObjSyncResult = 0;
thread.SignaledObj = null;
thread.ObjSyncResult = 0;
Thread.ReleaseAndResume();
thread.ReleaseAndResume();
Thread.WaitingInArbitration = false;
thread.WaitingInArbitration = false;
ArbiterThreads.Remove(Thread);
ArbiterThreads.Remove(thread);
}
}
}

View File

@ -4,14 +4,14 @@ namespace Ryujinx.HLE.HOS.Kernel
{
protected Horizon System;
public KAutoObject(Horizon System)
public KAutoObject(Horizon system)
{
this.System = System;
System = system;
}
public virtual KernelResult SetName(string Name)
public virtual KernelResult SetName(string name)
{
if (!System.AutoObjectNames.TryAdd(Name, this))
if (!System.AutoObjectNames.TryAdd(name, this))
{
return KernelResult.InvalidState;
}
@ -19,9 +19,9 @@ namespace Ryujinx.HLE.HOS.Kernel
return KernelResult.Success;
}
public static KernelResult RemoveName(Horizon System, string Name)
public static KernelResult RemoveName(Horizon system, string name)
{
if (!System.AutoObjectNames.TryRemove(Name, out _))
if (!system.AutoObjectNames.TryRemove(name, out _))
{
return KernelResult.NotFound;
}
@ -29,11 +29,11 @@ namespace Ryujinx.HLE.HOS.Kernel
return KernelResult.Success;
}
public static KAutoObject FindNamedObject(Horizon System, string Name)
public static KAutoObject FindNamedObject(Horizon system, string name)
{
if (System.AutoObjectNames.TryGetValue(Name, out KAutoObject Obj))
if (system.AutoObjectNames.TryGetValue(name, out KAutoObject obj))
{
return Obj;
return obj;
}
return null;

View File

@ -2,30 +2,30 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KClientPort : KSynchronizationObject
{
private int SessionsCount;
private int CurrentCapacity;
private int MaxSessions;
private int _sessionsCount;
private int _currentCapacity;
private int _maxSessions;
private KPort Parent;
private KPort _parent;
public KClientPort(Horizon System) : base(System) { }
public KClientPort(Horizon system) : base(system) { }
public void Initialize(KPort Parent, int MaxSessions)
public void Initialize(KPort parent, int maxSessions)
{
this.MaxSessions = MaxSessions;
this.Parent = Parent;
_maxSessions = maxSessions;
_parent = parent;
}
public new static KernelResult RemoveName(Horizon System, string Name)
public new static KernelResult RemoveName(Horizon system, string name)
{
KAutoObject FoundObj = KAutoObject.FindNamedObject(System, Name);
KAutoObject foundObj = FindNamedObject(system, name);
if (!(FoundObj is KClientPort))
if (!(foundObj is KClientPort))
{
return KernelResult.NotFound;
}
return KAutoObject.RemoveName(System, Name);
return KAutoObject.RemoveName(system, name);
}
}
}

View File

@ -5,67 +5,67 @@ namespace Ryujinx.HLE.HOS.Kernel
{
static class KConditionVariable
{
public static void Wait(Horizon System, LinkedList<KThread> ThreadList, object Mutex, long Timeout)
public static void Wait(Horizon system, LinkedList<KThread> threadList, object mutex, long timeout)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = system.Scheduler.GetCurrentThread();
System.CriticalSection.Enter();
system.CriticalSection.Enter();
Monitor.Exit(Mutex);
Monitor.Exit(mutex);
CurrentThread.Withholder = ThreadList;
currentThread.Withholder = threadList;
CurrentThread.Reschedule(ThreadSchedState.Paused);
currentThread.Reschedule(ThreadSchedState.Paused);
CurrentThread.WithholderNode = ThreadList.AddLast(CurrentThread);
currentThread.WithholderNode = threadList.AddLast(currentThread);
if (CurrentThread.ShallBeTerminated ||
CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
if (currentThread.ShallBeTerminated ||
currentThread.SchedFlags == ThreadSchedState.TerminationPending)
{
ThreadList.Remove(CurrentThread.WithholderNode);
threadList.Remove(currentThread.WithholderNode);
CurrentThread.Reschedule(ThreadSchedState.Running);
currentThread.Reschedule(ThreadSchedState.Running);
CurrentThread.Withholder = null;
currentThread.Withholder = null;
System.CriticalSection.Leave();
system.CriticalSection.Leave();
}
else
{
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
}
System.CriticalSection.Leave();
system.CriticalSection.Leave();
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.UnscheduleFutureInvocation(CurrentThread);
system.TimeManager.UnscheduleFutureInvocation(currentThread);
}
}
Monitor.Enter(Mutex);
Monitor.Enter(mutex);
}
public static void NotifyAll(Horizon System, LinkedList<KThread> ThreadList)
public static void NotifyAll(Horizon system, LinkedList<KThread> threadList)
{
System.CriticalSection.Enter();
system.CriticalSection.Enter();
LinkedListNode<KThread> Node = ThreadList.First;
LinkedListNode<KThread> node = threadList.First;
for (; Node != null; Node = ThreadList.First)
for (; node != null; node = threadList.First)
{
KThread Thread = Node.Value;
KThread thread = node.Value;
ThreadList.Remove(Thread.WithholderNode);
threadList.Remove(thread.WithholderNode);
Thread.Withholder = null;
thread.Withholder = null;
Thread.Reschedule(ThreadSchedState.Running);
thread.Reschedule(ThreadSchedState.Running);
}
System.CriticalSection.Leave();
system.CriticalSection.Leave();
}
}
}

View File

@ -7,77 +7,77 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private const int IdMasksCount = 8;
private int[] IdMasks;
private int[] _idMasks;
private int NextFreeBitHint;
private int _nextFreeBitHint;
public KContextIdManager()
{
IdMasks = new int[IdMasksCount];
_idMasks = new int[IdMasksCount];
}
public int GetId()
{
lock (IdMasks)
lock (_idMasks)
{
int Id = 0;
int id = 0;
if (!TestBit(NextFreeBitHint))
if (!TestBit(_nextFreeBitHint))
{
Id = NextFreeBitHint;
id = _nextFreeBitHint;
}
else
{
for (int Index = 0; Index < IdMasksCount; Index++)
for (int index = 0; index < IdMasksCount; index++)
{
int Mask = IdMasks[Index];
int mask = _idMasks[index];
int FirstFreeBit = BitUtils.CountLeadingZeros32((Mask + 1) & ~Mask);
int firstFreeBit = BitUtils.CountLeadingZeros32((mask + 1) & ~mask);
if (FirstFreeBit < 32)
if (firstFreeBit < 32)
{
int BaseBit = Index * 32 + 31;
int baseBit = index * 32 + 31;
Id = BaseBit - FirstFreeBit;
id = baseBit - firstFreeBit;
break;
}
else if (Index == IdMasksCount - 1)
else if (index == IdMasksCount - 1)
{
throw new InvalidOperationException("Maximum number of Ids reached!");
}
}
}
NextFreeBitHint = Id + 1;
_nextFreeBitHint = id + 1;
SetBit(Id);
SetBit(id);
return Id;
return id;
}
}
public void PutId(int Id)
public void PutId(int id)
{
lock (IdMasks)
lock (_idMasks)
{
ClearBit(Id);
ClearBit(id);
}
}
private bool TestBit(int Bit)
private bool TestBit(int bit)
{
return (IdMasks[NextFreeBitHint / 32] & (1 << (NextFreeBitHint & 31))) != 0;
return (_idMasks[_nextFreeBitHint / 32] & (1 << (_nextFreeBitHint & 31))) != 0;
}
private void SetBit(int Bit)
private void SetBit(int bit)
{
IdMasks[NextFreeBitHint / 32] |= (1 << (NextFreeBitHint & 31));
_idMasks[_nextFreeBitHint / 32] |= (1 << (_nextFreeBitHint & 31));
}
private void ClearBit(int Bit)
private void ClearBit(int bit)
{
IdMasks[NextFreeBitHint / 32] &= ~(1 << (NextFreeBitHint & 31));
_idMasks[_nextFreeBitHint / 32] &= ~(1 << (_nextFreeBitHint & 31));
}
}
}

View File

@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KCoreContext
{
private KScheduler Scheduler;
private KScheduler _scheduler;
private HleCoreManager CoreManager;
private HleCoreManager _coreManager;
public bool ContextSwitchNeeded { get; private set; }
@ -17,15 +17,15 @@ namespace Ryujinx.HLE.HOS.Kernel
public KThread CurrentThread { get; private set; }
public KThread SelectedThread { get; private set; }
public KCoreContext(KScheduler Scheduler, HleCoreManager CoreManager)
public KCoreContext(KScheduler scheduler, HleCoreManager coreManager)
{
this.Scheduler = Scheduler;
this.CoreManager = CoreManager;
_scheduler = scheduler;
_coreManager = coreManager;
}
public void SelectThread(KThread Thread)
public void SelectThread(KThread thread)
{
SelectedThread = Thread;
SelectedThread = thread;
if (SelectedThread != CurrentThread)
{
@ -43,10 +43,10 @@ namespace Ryujinx.HLE.HOS.Kernel
if (CurrentThread != null)
{
long CurrentTime = PerformanceCounter.ElapsedMilliseconds;
long currentTime = PerformanceCounter.ElapsedMilliseconds;
CurrentThread.TotalTimeRunning += CurrentTime - CurrentThread.LastScheduledTime;
CurrentThread.LastScheduledTime = CurrentTime;
CurrentThread.TotalTimeRunning += currentTime - CurrentThread.LastScheduledTime;
CurrentThread.LastScheduledTime = currentTime;
}
}
@ -58,21 +58,21 @@ namespace Ryujinx.HLE.HOS.Kernel
if (CurrentThread != null)
{
CoreManager.Reset(CurrentThread.Context.Work);
_coreManager.Reset(CurrentThread.Context.Work);
}
CurrentThread = SelectedThread;
if (CurrentThread != null)
{
long CurrentTime = PerformanceCounter.ElapsedMilliseconds;
long currentTime = PerformanceCounter.ElapsedMilliseconds;
CurrentThread.TotalTimeRunning += CurrentTime - CurrentThread.LastScheduledTime;
CurrentThread.LastScheduledTime = CurrentTime;
CurrentThread.TotalTimeRunning += currentTime - CurrentThread.LastScheduledTime;
CurrentThread.LastScheduledTime = currentTime;
CurrentThread.ClearExclusive();
CoreManager.Set(CurrentThread.Context.Work);
_coreManager.Set(CurrentThread.Context.Work);
CurrentThread.Context.Execute();
}

View File

@ -5,15 +5,15 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KCriticalSection
{
private Horizon System;
private Horizon _system;
public object LockObj { get; private set; }
public object LockObj { get; }
private int RecursionCount;
private int _recursionCount;
public KCriticalSection(Horizon System)
public KCriticalSection(Horizon system)
{
this.System = System;
_system = system;
LockObj = new object();
}
@ -22,53 +22,53 @@ namespace Ryujinx.HLE.HOS.Kernel
{
Monitor.Enter(LockObj);
RecursionCount++;
_recursionCount++;
}
public void Leave()
{
if (RecursionCount == 0)
if (_recursionCount == 0)
{
return;
}
bool DoContextSwitch = false;
bool doContextSwitch = false;
if (--RecursionCount == 0)
if (--_recursionCount == 0)
{
if (System.Scheduler.ThreadReselectionRequested)
if (_system.Scheduler.ThreadReselectionRequested)
{
System.Scheduler.SelectThreads();
_system.Scheduler.SelectThreads();
}
Monitor.Exit(LockObj);
if (System.Scheduler.MultiCoreScheduling)
if (_system.Scheduler.MultiCoreScheduling)
{
lock (System.Scheduler.CoreContexts)
lock (_system.Scheduler.CoreContexts)
{
for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
for (int core = 0; core < KScheduler.CpuCoresCount; core++)
{
KCoreContext CoreContext = System.Scheduler.CoreContexts[Core];
KCoreContext coreContext = _system.Scheduler.CoreContexts[core];
if (CoreContext.ContextSwitchNeeded)
if (coreContext.ContextSwitchNeeded)
{
CpuThread CurrentHleThread = CoreContext.CurrentThread?.Context;
CpuThread currentHleThread = coreContext.CurrentThread?.Context;
if (CurrentHleThread == null)
if (currentHleThread == null)
{
//Nothing is running, we can perform the context switch immediately.
CoreContext.ContextSwitch();
coreContext.ContextSwitch();
}
else if (CurrentHleThread.IsCurrentThread())
else if (currentHleThread.IsCurrentThread())
{
//Thread running on the current core, context switch will block.
DoContextSwitch = true;
doContextSwitch = true;
}
else
{
//Thread running on another core, request a interrupt.
CurrentHleThread.RequestInterrupt();
currentHleThread.RequestInterrupt();
}
}
}
@ -76,7 +76,7 @@ namespace Ryujinx.HLE.HOS.Kernel
}
else
{
DoContextSwitch = true;
doContextSwitch = true;
}
}
else
@ -84,9 +84,9 @@ namespace Ryujinx.HLE.HOS.Kernel
Monitor.Exit(LockObj);
}
if (DoContextSwitch)
if (doContextSwitch)
{
System.Scheduler.ContextSwitch();
_system.Scheduler.ContextSwitch();
}
}
}

View File

@ -2,12 +2,12 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KEvent
{
public KReadableEvent ReadableEvent { get; private set; }
public KWritableEvent WritableEvent { get; private set; }
public KReadableEvent ReadableEvent { get; }
public KWritableEvent WritableEvent { get; }
public KEvent(Horizon System)
public KEvent(Horizon system)
{
ReadableEvent = new KReadableEvent(System, this);
ReadableEvent = new KReadableEvent(system, this);
WritableEvent = new KWritableEvent(this);
}
}

View File

@ -4,14 +4,14 @@ namespace Ryujinx.HLE.HOS.Kernel
{
public KHandleEntry Next { get; set; }
public int Index { get; private set; }
public int Index { get; }
public ushort HandleId { get; set; }
public object Obj { get; set; }
public KHandleEntry(int Index)
public KHandleEntry(int index)
{
this.Index = Index;
Index = index;
}
}
}

View File

@ -7,148 +7,148 @@ namespace Ryujinx.HLE.HOS.Kernel
private const int SelfThreadHandle = (0x1ffff << 15) | 0;
private const int SelfProcessHandle = (0x1ffff << 15) | 1;
private Horizon System;
private Horizon _system;
private KHandleEntry[] Table;
private KHandleEntry[] _table;
private KHandleEntry TableHead;
private KHandleEntry NextFreeEntry;
private KHandleEntry _tableHead;
private KHandleEntry _nextFreeEntry;
private int ActiveSlotsCount;
private int _activeSlotsCount;
private int Size;
private int _size;
private ushort IdCounter;
private ushort _idCounter;
public KHandleTable(Horizon System)
public KHandleTable(Horizon system)
{
this.System = System;
_system = system;
}
public KernelResult Initialize(int Size)
public KernelResult Initialize(int size)
{
if ((uint)Size > 1024)
if ((uint)size > 1024)
{
return KernelResult.OutOfMemory;
}
if (Size < 1)
if (size < 1)
{
Size = 1024;
size = 1024;
}
this.Size = Size;
_size = size;
IdCounter = 1;
_idCounter = 1;
Table = new KHandleEntry[Size];
_table = new KHandleEntry[size];
TableHead = new KHandleEntry(0);
_tableHead = new KHandleEntry(0);
KHandleEntry Entry = TableHead;
KHandleEntry entry = _tableHead;
for (int Index = 0; Index < Size; Index++)
for (int index = 0; index < size; index++)
{
Table[Index] = Entry;
_table[index] = entry;
Entry.Next = new KHandleEntry(Index + 1);
entry.Next = new KHandleEntry(index + 1);
Entry = Entry.Next;
entry = entry.Next;
}
Table[Size - 1].Next = null;
_table[size - 1].Next = null;
NextFreeEntry = TableHead;
_nextFreeEntry = _tableHead;
return KernelResult.Success;
}
public KernelResult GenerateHandle(object Obj, out int Handle)
public KernelResult GenerateHandle(object obj, out int handle)
{
Handle = 0;
handle = 0;
lock (Table)
lock (_table)
{
if (ActiveSlotsCount >= Size)
if (_activeSlotsCount >= _size)
{
return KernelResult.HandleTableFull;
}
KHandleEntry Entry = NextFreeEntry;
KHandleEntry entry = _nextFreeEntry;
NextFreeEntry = Entry.Next;
_nextFreeEntry = entry.Next;
Entry.Obj = Obj;
Entry.HandleId = IdCounter;
entry.Obj = obj;
entry.HandleId = _idCounter;
ActiveSlotsCount++;
_activeSlotsCount++;
Handle = (int)((IdCounter << 15) & (uint)0xffff8000) | Entry.Index;
handle = (int)((_idCounter << 15) & 0xffff8000) | entry.Index;
if ((short)(IdCounter + 1) >= 0)
if ((short)(_idCounter + 1) >= 0)
{
IdCounter++;
_idCounter++;
}
else
{
IdCounter = 1;
_idCounter = 1;
}
}
return KernelResult.Success;
}
public bool CloseHandle(int Handle)
public bool CloseHandle(int handle)
{
if ((Handle >> 30) != 0 ||
Handle == SelfThreadHandle ||
Handle == SelfProcessHandle)
if ((handle >> 30) != 0 ||
handle == SelfThreadHandle ||
handle == SelfProcessHandle)
{
return false;
}
int Index = (Handle >> 0) & 0x7fff;
int HandleId = (Handle >> 15);
int index = (handle >> 0) & 0x7fff;
int handleId = (handle >> 15);
bool Result = false;
bool result = false;
lock (Table)
lock (_table)
{
if (HandleId != 0 && Index < Size)
if (handleId != 0 && index < _size)
{
KHandleEntry Entry = Table[Index];
KHandleEntry entry = _table[index];
if (Entry.Obj != null && Entry.HandleId == HandleId)
if (entry.Obj != null && entry.HandleId == handleId)
{
Entry.Obj = null;
Entry.Next = NextFreeEntry;
entry.Obj = null;
entry.Next = _nextFreeEntry;
NextFreeEntry = Entry;
_nextFreeEntry = entry;
ActiveSlotsCount--;
_activeSlotsCount--;
Result = true;
result = true;
}
}
}
return Result;
return result;
}
public T GetObject<T>(int Handle)
public T GetObject<T>(int handle)
{
int Index = (Handle >> 0) & 0x7fff;
int HandleId = (Handle >> 15);
int index = (handle >> 0) & 0x7fff;
int handleId = (handle >> 15);
lock (Table)
lock (_table)
{
if ((Handle >> 30) == 0 && HandleId != 0)
if ((handle >> 30) == 0 && handleId != 0)
{
KHandleEntry Entry = Table[Index];
KHandleEntry entry = _table[index];
if (Entry.HandleId == HandleId && Entry.Obj is T Obj)
if (entry.HandleId == handleId && entry.Obj is T obj)
{
return Obj;
return obj;
}
}
}
@ -156,49 +156,49 @@ namespace Ryujinx.HLE.HOS.Kernel
return default(T);
}
public KThread GetKThread(int Handle)
public KThread GetKThread(int handle)
{
if (Handle == SelfThreadHandle)
if (handle == SelfThreadHandle)
{
return System.Scheduler.GetCurrentThread();
return _system.Scheduler.GetCurrentThread();
}
else
{
return GetObject<KThread>(Handle);
return GetObject<KThread>(handle);
}
}
public KProcess GetKProcess(int Handle)
public KProcess GetKProcess(int handle)
{
if (Handle == SelfProcessHandle)
if (handle == SelfProcessHandle)
{
return System.Scheduler.GetCurrentProcess();
return _system.Scheduler.GetCurrentProcess();
}
else
{
return GetObject<KProcess>(Handle);
return GetObject<KProcess>(handle);
}
}
public void Destroy()
{
lock (Table)
lock (_table)
{
for (int Index = 0; Index < Size; Index++)
for (int index = 0; index < _size; index++)
{
KHandleEntry Entry = Table[Index];
KHandleEntry entry = _table[index];
if (Entry.Obj != null)
if (entry.Obj != null)
{
if (Entry.Obj is IDisposable DisposableObj)
if (entry.Obj is IDisposable disposableObj)
{
DisposableObj.Dispose();
disposableObj.Dispose();
}
Entry.Obj = null;
Entry.Next = NextFreeEntry;
entry.Obj = null;
entry.Next = _nextFreeEntry;
NextFreeEntry = Entry;
_nextFreeEntry = entry;
}
}
}

View File

@ -2,21 +2,21 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KMemoryArrange
{
public KMemoryArrangeRegion Service { get; private set; }
public KMemoryArrangeRegion NvServices { get; private set; }
public KMemoryArrangeRegion Applet { get; private set; }
public KMemoryArrangeRegion Application { get; private set; }
public KMemoryArrangeRegion Service { get; }
public KMemoryArrangeRegion NvServices { get; }
public KMemoryArrangeRegion Applet { get; }
public KMemoryArrangeRegion Application { get; }
public KMemoryArrange(
KMemoryArrangeRegion Service,
KMemoryArrangeRegion NvServices,
KMemoryArrangeRegion Applet,
KMemoryArrangeRegion Application)
KMemoryArrangeRegion service,
KMemoryArrangeRegion nvServices,
KMemoryArrangeRegion applet,
KMemoryArrangeRegion application)
{
this.Service = Service;
this.NvServices = NvServices;
this.Applet = Applet;
this.Application = Application;
Service = service;
NvServices = nvServices;
Applet = applet;
Application = application;
}
}
}

View File

@ -2,15 +2,15 @@ namespace Ryujinx.HLE.HOS.Kernel
{
struct KMemoryArrangeRegion
{
public ulong Address { get; private set; }
public ulong Size { get; private set; }
public ulong Address { get; }
public ulong Size { get; }
public ulong EndAddr => Address + Size;
public KMemoryArrangeRegion(ulong Address, ulong Size)
public KMemoryArrangeRegion(ulong address, ulong size)
{
this.Address = Address;
this.Size = Size;
Address = address;
Size = size;
}
}
}

View File

@ -13,26 +13,26 @@ namespace Ryujinx.HLE.HOS.Kernel
public int DeviceRefCount { get; set; }
public KMemoryBlock(
ulong BaseAddress,
ulong PagesCount,
MemoryState State,
MemoryPermission Permission,
MemoryAttribute Attribute)
ulong baseAddress,
ulong pagesCount,
MemoryState state,
MemoryPermission permission,
MemoryAttribute attribute)
{
this.BaseAddress = BaseAddress;
this.PagesCount = PagesCount;
this.State = State;
this.Attribute = Attribute;
this.Permission = Permission;
BaseAddress = baseAddress;
PagesCount = pagesCount;
State = state;
Attribute = attribute;
Permission = permission;
}
public KMemoryInfo GetInfo()
{
ulong Size = PagesCount * KMemoryManager.PageSize;
ulong size = PagesCount * KMemoryManager.PageSize;
return new KMemoryInfo(
BaseAddress,
Size,
size,
State,
Permission,
Attribute,

View File

@ -2,18 +2,18 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KMemoryBlockAllocator
{
private ulong CapacityElements;
private ulong _capacityElements;
public int Count { get; set; }
public KMemoryBlockAllocator(ulong CapacityElements)
public KMemoryBlockAllocator(ulong capacityElements)
{
this.CapacityElements = CapacityElements;
_capacityElements = capacityElements;
}
public bool CanAllocate(int Count)
public bool CanAllocate(int count)
{
return (ulong)(this.Count + Count) <= CapacityElements;
return (ulong)(Count + count) <= _capacityElements;
}
}
}

View File

@ -2,32 +2,32 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KMemoryInfo
{
public ulong Address { get; private set; }
public ulong Size { get; private set; }
public ulong Address { get; }
public ulong Size { get; }
public MemoryState State { get; private set; }
public MemoryPermission Permission { get; private set; }
public MemoryAttribute Attribute { get; private set; }
public MemoryState State { get; }
public MemoryPermission Permission { get; }
public MemoryAttribute Attribute { get; }
public int IpcRefCount { get; private set; }
public int DeviceRefCount { get; private set; }
public int IpcRefCount { get; }
public int DeviceRefCount { get; }
public KMemoryInfo(
ulong Address,
ulong Size,
MemoryState State,
MemoryPermission Permission,
MemoryAttribute Attribute,
int IpcRefCount,
int DeviceRefCount)
ulong address,
ulong size,
MemoryState state,
MemoryPermission permission,
MemoryAttribute attribute,
int ipcRefCount,
int deviceRefCount)
{
this.Address = Address;
this.Size = Size;
this.State = State;
this.Attribute = Attribute;
this.Permission = Permission;
this.IpcRefCount = IpcRefCount;
this.DeviceRefCount = DeviceRefCount;
Address = address;
Size = size;
State = state;
Attribute = attribute;
Permission = permission;
IpcRefCount = ipcRefCount;
DeviceRefCount = deviceRefCount;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -12,30 +12,30 @@ namespace Ryujinx.HLE.HOS.Kernel
public int Order;
public int NextOrder;
public bool TryCoalesce(int Index, int Size)
public bool TryCoalesce(int index, int size)
{
long Mask = ((1L << Size) - 1) << (Index & 63);
long mask = ((1L << size) - 1) << (index & 63);
Index /= 64;
index /= 64;
if ((Mask & ~Masks[MaxLevel - 1][Index]) != 0)
if ((mask & ~Masks[MaxLevel - 1][index]) != 0)
{
return false;
}
Masks[MaxLevel - 1][Index] &= ~Mask;
Masks[MaxLevel - 1][index] &= ~mask;
for (int Level = MaxLevel - 2; Level >= 0; Level--, Index /= 64)
for (int level = MaxLevel - 2; level >= 0; level--, index /= 64)
{
Masks[Level][Index / 64] &= ~(1L << (Index & 63));
Masks[level][index / 64] &= ~(1L << (index & 63));
if (Masks[Level][Index / 64] != 0)
if (Masks[level][index / 64] != 0)
{
break;
}
}
FreeCount -= (ulong)Size;
FreeCount -= (ulong)size;
return true;
}

View File

@ -6,404 +6,404 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private static readonly int[] BlockOrders = new int[] { 12, 16, 21, 22, 25, 29, 30 };
public ulong Address { get; private set; }
public ulong EndAddr { get; private set; }
public ulong Size { get; private set; }
public ulong Address { get; }
public ulong EndAddr { get; }
public ulong Size { get; }
private int BlockOrdersCount;
private int _blockOrdersCount;
private KMemoryRegionBlock[] Blocks;
private KMemoryRegionBlock[] _blocks;
public KMemoryRegionManager(ulong Address, ulong Size, ulong EndAddr)
public KMemoryRegionManager(ulong address, ulong size, ulong endAddr)
{
Blocks = new KMemoryRegionBlock[BlockOrders.Length];
_blocks = new KMemoryRegionBlock[BlockOrders.Length];
this.Address = Address;
this.Size = Size;
this.EndAddr = EndAddr;
Address = address;
Size = size;
EndAddr = endAddr;
BlockOrdersCount = BlockOrders.Length;
_blockOrdersCount = BlockOrders.Length;
for (int BlockIndex = 0; BlockIndex < BlockOrdersCount; BlockIndex++)
for (int blockIndex = 0; blockIndex < _blockOrdersCount; blockIndex++)
{
Blocks[BlockIndex] = new KMemoryRegionBlock();
_blocks[blockIndex] = new KMemoryRegionBlock();
Blocks[BlockIndex].Order = BlockOrders[BlockIndex];
_blocks[blockIndex].Order = BlockOrders[blockIndex];
int NextOrder = BlockIndex == BlockOrdersCount - 1 ? 0 : BlockOrders[BlockIndex + 1];
int nextOrder = blockIndex == _blockOrdersCount - 1 ? 0 : BlockOrders[blockIndex + 1];
Blocks[BlockIndex].NextOrder = NextOrder;
_blocks[blockIndex].NextOrder = nextOrder;
int CurrBlockSize = 1 << BlockOrders[BlockIndex];
int NextBlockSize = CurrBlockSize;
int currBlockSize = 1 << BlockOrders[blockIndex];
int nextBlockSize = currBlockSize;
if (NextOrder != 0)
if (nextOrder != 0)
{
NextBlockSize = 1 << NextOrder;
nextBlockSize = 1 << nextOrder;
}
ulong StartAligned = BitUtils.AlignDown(Address, NextBlockSize);
ulong EndAddrAligned = BitUtils.AlignDown(EndAddr, CurrBlockSize);
ulong startAligned = BitUtils.AlignDown(address, nextBlockSize);
ulong endAddrAligned = BitUtils.AlignDown(endAddr, currBlockSize);
ulong SizeInBlocksTruncated = (EndAddrAligned - StartAligned) >> BlockOrders[BlockIndex];
ulong sizeInBlocksTruncated = (endAddrAligned - startAligned) >> BlockOrders[blockIndex];
ulong EndAddrRounded = BitUtils.AlignUp(Address + Size, NextBlockSize);
ulong endAddrRounded = BitUtils.AlignUp(address + size, nextBlockSize);
ulong SizeInBlocksRounded = (EndAddrRounded - StartAligned) >> BlockOrders[BlockIndex];
ulong sizeInBlocksRounded = (endAddrRounded - startAligned) >> BlockOrders[blockIndex];
Blocks[BlockIndex].StartAligned = StartAligned;
Blocks[BlockIndex].SizeInBlocksTruncated = SizeInBlocksTruncated;
Blocks[BlockIndex].SizeInBlocksRounded = SizeInBlocksRounded;
_blocks[blockIndex].StartAligned = startAligned;
_blocks[blockIndex].SizeInBlocksTruncated = sizeInBlocksTruncated;
_blocks[blockIndex].SizeInBlocksRounded = sizeInBlocksRounded;
ulong CurrSizeInBlocks = SizeInBlocksRounded;
ulong currSizeInBlocks = sizeInBlocksRounded;
int MaxLevel = 0;
int maxLevel = 0;
do
{
MaxLevel++;
maxLevel++;
}
while ((CurrSizeInBlocks /= 64) != 0);
while ((currSizeInBlocks /= 64) != 0);
Blocks[BlockIndex].MaxLevel = MaxLevel;
_blocks[blockIndex].MaxLevel = maxLevel;
Blocks[BlockIndex].Masks = new long[MaxLevel][];
_blocks[blockIndex].Masks = new long[maxLevel][];
CurrSizeInBlocks = SizeInBlocksRounded;
currSizeInBlocks = sizeInBlocksRounded;
for (int Level = MaxLevel - 1; Level >= 0; Level--)
for (int level = maxLevel - 1; level >= 0; level--)
{
CurrSizeInBlocks = (CurrSizeInBlocks + 63) / 64;
currSizeInBlocks = (currSizeInBlocks + 63) / 64;
Blocks[BlockIndex].Masks[Level] = new long[CurrSizeInBlocks];
_blocks[blockIndex].Masks[level] = new long[currSizeInBlocks];
}
}
if (Size != 0)
if (size != 0)
{
FreePages(Address, Size / KMemoryManager.PageSize);
FreePages(address, size / KMemoryManager.PageSize);
}
}
public KernelResult AllocatePages(ulong PagesCount, bool Backwards, out KPageList PageList)
public KernelResult AllocatePages(ulong pagesCount, bool backwards, out KPageList pageList)
{
lock (Blocks)
lock (_blocks)
{
return AllocatePagesImpl(PagesCount, Backwards, out PageList);
return AllocatePagesImpl(pagesCount, backwards, out pageList);
}
}
private KernelResult AllocatePagesImpl(ulong PagesCount, bool Backwards, out KPageList PageList)
private KernelResult AllocatePagesImpl(ulong pagesCount, bool backwards, out KPageList pageList)
{
PageList = new KPageList();
pageList = new KPageList();
if (BlockOrdersCount > 0)
if (_blockOrdersCount > 0)
{
if (GetFreePagesImpl() < PagesCount)
if (GetFreePagesImpl() < pagesCount)
{
return KernelResult.OutOfMemory;
}
}
else if (PagesCount != 0)
else if (pagesCount != 0)
{
return KernelResult.OutOfMemory;
}
for (int BlockIndex = BlockOrdersCount - 1; BlockIndex >= 0; BlockIndex--)
for (int blockIndex = _blockOrdersCount - 1; blockIndex >= 0; blockIndex--)
{
KMemoryRegionBlock Block = Blocks[BlockIndex];
KMemoryRegionBlock block = _blocks[blockIndex];
ulong BestFitBlockSize = 1UL << Block.Order;
ulong bestFitBlockSize = 1UL << block.Order;
ulong BlockPagesCount = BestFitBlockSize / KMemoryManager.PageSize;
ulong blockPagesCount = bestFitBlockSize / KMemoryManager.PageSize;
//Check if this is the best fit for this page size.
//If so, try allocating as much requested pages as possible.
while (BlockPagesCount <= PagesCount)
while (blockPagesCount <= pagesCount)
{
ulong Address = 0;
ulong address = 0;
for (int CurrBlockIndex = BlockIndex;
CurrBlockIndex < BlockOrdersCount && Address == 0;
CurrBlockIndex++)
for (int currBlockIndex = blockIndex;
currBlockIndex < _blockOrdersCount && address == 0;
currBlockIndex++)
{
Block = Blocks[CurrBlockIndex];
block = _blocks[currBlockIndex];
int Index = 0;
int index = 0;
bool ZeroMask = false;
bool zeroMask = false;
for (int Level = 0; Level < Block.MaxLevel; Level++)
for (int level = 0; level < block.MaxLevel; level++)
{
long Mask = Block.Masks[Level][Index];
long mask = block.Masks[level][index];
if (Mask == 0)
if (mask == 0)
{
ZeroMask = true;
zeroMask = true;
break;
}
if (Backwards)
if (backwards)
{
Index = (Index * 64 + 63) - BitUtils.CountLeadingZeros64(Mask);
index = (index * 64 + 63) - BitUtils.CountLeadingZeros64(mask);
}
else
{
Index = Index * 64 + BitUtils.CountLeadingZeros64(BitUtils.ReverseBits64(Mask));
index = index * 64 + BitUtils.CountLeadingZeros64(BitUtils.ReverseBits64(mask));
}
}
if (Block.SizeInBlocksTruncated <= (ulong)Index || ZeroMask)
if (block.SizeInBlocksTruncated <= (ulong)index || zeroMask)
{
continue;
}
Block.FreeCount--;
block.FreeCount--;
int TempIdx = Index;
int tempIdx = index;
for (int Level = Block.MaxLevel - 1; Level >= 0; Level--, TempIdx /= 64)
for (int level = block.MaxLevel - 1; level >= 0; level--, tempIdx /= 64)
{
Block.Masks[Level][TempIdx / 64] &= ~(1L << (TempIdx & 63));
block.Masks[level][tempIdx / 64] &= ~(1L << (tempIdx & 63));
if (Block.Masks[Level][TempIdx / 64] != 0)
if (block.Masks[level][tempIdx / 64] != 0)
{
break;
}
}
Address = Block.StartAligned + ((ulong)Index << Block.Order);
address = block.StartAligned + ((ulong)index << block.Order);
}
for (int CurrBlockIndex = BlockIndex;
CurrBlockIndex < BlockOrdersCount && Address == 0;
CurrBlockIndex++)
for (int currBlockIndex = blockIndex;
currBlockIndex < _blockOrdersCount && address == 0;
currBlockIndex++)
{
Block = Blocks[CurrBlockIndex];
block = _blocks[currBlockIndex];
int Index = 0;
int index = 0;
bool ZeroMask = false;
bool zeroMask = false;
for (int Level = 0; Level < Block.MaxLevel; Level++)
for (int level = 0; level < block.MaxLevel; level++)
{
long Mask = Block.Masks[Level][Index];
long mask = block.Masks[level][index];
if (Mask == 0)
if (mask == 0)
{
ZeroMask = true;
zeroMask = true;
break;
}
if (Backwards)
if (backwards)
{
Index = Index * 64 + BitUtils.CountLeadingZeros64(BitUtils.ReverseBits64(Mask));
index = index * 64 + BitUtils.CountLeadingZeros64(BitUtils.ReverseBits64(mask));
}
else
{
Index = (Index * 64 + 63) - BitUtils.CountLeadingZeros64(Mask);
index = (index * 64 + 63) - BitUtils.CountLeadingZeros64(mask);
}
}
if (Block.SizeInBlocksTruncated <= (ulong)Index || ZeroMask)
if (block.SizeInBlocksTruncated <= (ulong)index || zeroMask)
{
continue;
}
Block.FreeCount--;
block.FreeCount--;
int TempIdx = Index;
int tempIdx = index;
for (int Level = Block.MaxLevel - 1; Level >= 0; Level--, TempIdx /= 64)
for (int level = block.MaxLevel - 1; level >= 0; level--, tempIdx /= 64)
{
Block.Masks[Level][TempIdx / 64] &= ~(1L << (TempIdx & 63));
block.Masks[level][tempIdx / 64] &= ~(1L << (tempIdx & 63));
if (Block.Masks[Level][TempIdx / 64] != 0)
if (block.Masks[level][tempIdx / 64] != 0)
{
break;
}
}
Address = Block.StartAligned + ((ulong)Index << Block.Order);
address = block.StartAligned + ((ulong)index << block.Order);
}
//The address being zero means that no free space was found on that order,
//just give up and try with the next one.
if (Address == 0)
if (address == 0)
{
break;
}
//If we are using a larger order than best fit, then we should
//split it into smaller blocks.
ulong FirstFreeBlockSize = 1UL << Block.Order;
ulong firstFreeBlockSize = 1UL << block.Order;
if (FirstFreeBlockSize > BestFitBlockSize)
if (firstFreeBlockSize > bestFitBlockSize)
{
FreePages(Address + BestFitBlockSize, (FirstFreeBlockSize - BestFitBlockSize) / KMemoryManager.PageSize);
FreePages(address + bestFitBlockSize, (firstFreeBlockSize - bestFitBlockSize) / KMemoryManager.PageSize);
}
//Add new allocated page(s) to the pages list.
//If an error occurs, then free all allocated pages and fail.
KernelResult Result = PageList.AddRange(Address, BlockPagesCount);
KernelResult result = pageList.AddRange(address, blockPagesCount);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
FreePages(Address, BlockPagesCount);
FreePages(address, blockPagesCount);
foreach (KPageNode PageNode in PageList)
foreach (KPageNode pageNode in pageList)
{
FreePages(PageNode.Address, PageNode.PagesCount);
FreePages(pageNode.Address, pageNode.PagesCount);
}
return Result;
return result;
}
PagesCount -= BlockPagesCount;
pagesCount -= blockPagesCount;
}
}
//Success case, all requested pages were allocated successfully.
if (PagesCount == 0)
if (pagesCount == 0)
{
return KernelResult.Success;
}
//Error case, free allocated pages and return out of memory.
foreach (KPageNode PageNode in PageList)
foreach (KPageNode pageNode in pageList)
{
FreePages(PageNode.Address, PageNode.PagesCount);
FreePages(pageNode.Address, pageNode.PagesCount);
}
PageList = null;
pageList = null;
return KernelResult.OutOfMemory;
}
public void FreePages(KPageList PageList)
public void FreePages(KPageList pageList)
{
lock (Blocks)
lock (_blocks)
{
foreach (KPageNode PageNode in PageList)
foreach (KPageNode pageNode in pageList)
{
FreePages(PageNode.Address, PageNode.PagesCount);
FreePages(pageNode.Address, pageNode.PagesCount);
}
}
}
private void FreePages(ulong Address, ulong PagesCount)
private void FreePages(ulong address, ulong pagesCount)
{
ulong EndAddr = Address + PagesCount * KMemoryManager.PageSize;
ulong endAddr = address + pagesCount * KMemoryManager.PageSize;
int BlockIndex = BlockOrdersCount - 1;
int blockIndex = _blockOrdersCount - 1;
ulong AddressRounded = 0;
ulong EndAddrTruncated = 0;
ulong addressRounded = 0;
ulong endAddrTruncated = 0;
for (; BlockIndex >= 0; BlockIndex--)
for (; blockIndex >= 0; blockIndex--)
{
KMemoryRegionBlock AllocInfo = Blocks[BlockIndex];
KMemoryRegionBlock allocInfo = _blocks[blockIndex];
int BlockSize = 1 << AllocInfo.Order;
int blockSize = 1 << allocInfo.Order;
AddressRounded = BitUtils.AlignUp (Address, BlockSize);
EndAddrTruncated = BitUtils.AlignDown(EndAddr, BlockSize);
addressRounded = BitUtils.AlignUp (address, blockSize);
endAddrTruncated = BitUtils.AlignDown(endAddr, blockSize);
if (AddressRounded < EndAddrTruncated)
if (addressRounded < endAddrTruncated)
{
break;
}
}
void FreeRegion(ulong CurrAddress)
void FreeRegion(ulong currAddress)
{
for (int CurrBlockIndex = BlockIndex;
CurrBlockIndex < BlockOrdersCount && CurrAddress != 0;
CurrBlockIndex++)
for (int currBlockIndex = blockIndex;
currBlockIndex < _blockOrdersCount && currAddress != 0;
currBlockIndex++)
{
KMemoryRegionBlock Block = Blocks[CurrBlockIndex];
KMemoryRegionBlock block = _blocks[currBlockIndex];
Block.FreeCount++;
block.FreeCount++;
ulong FreedBlocks = (CurrAddress - Block.StartAligned) >> Block.Order;
ulong freedBlocks = (currAddress - block.StartAligned) >> block.Order;
int Index = (int)FreedBlocks;
int index = (int)freedBlocks;
for (int Level = Block.MaxLevel - 1; Level >= 0; Level--, Index /= 64)
for (int level = block.MaxLevel - 1; level >= 0; level--, index /= 64)
{
long Mask = Block.Masks[Level][Index / 64];
long mask = block.Masks[level][index / 64];
Block.Masks[Level][Index / 64] = Mask | (1L << (Index & 63));
block.Masks[level][index / 64] = mask | (1L << (index & 63));
if (Mask != 0)
if (mask != 0)
{
break;
}
}
int BlockSizeDelta = 1 << (Block.NextOrder - Block.Order);
int blockSizeDelta = 1 << (block.NextOrder - block.Order);
int FreedBlocksTruncated = BitUtils.AlignDown((int)FreedBlocks, BlockSizeDelta);
int freedBlocksTruncated = BitUtils.AlignDown((int)freedBlocks, blockSizeDelta);
if (!Block.TryCoalesce(FreedBlocksTruncated, BlockSizeDelta))
if (!block.TryCoalesce(freedBlocksTruncated, blockSizeDelta))
{
break;
}
CurrAddress = Block.StartAligned + ((ulong)FreedBlocksTruncated << Block.Order);
currAddress = block.StartAligned + ((ulong)freedBlocksTruncated << block.Order);
}
}
//Free inside aligned region.
ulong BaseAddress = AddressRounded;
ulong baseAddress = addressRounded;
while (BaseAddress < EndAddrTruncated)
while (baseAddress < endAddrTruncated)
{
ulong BlockSize = 1UL << Blocks[BlockIndex].Order;
ulong blockSize = 1UL << _blocks[blockIndex].Order;
FreeRegion(BaseAddress);
FreeRegion(baseAddress);
BaseAddress += BlockSize;
baseAddress += blockSize;
}
int NextBlockIndex = BlockIndex - 1;
int nextBlockIndex = blockIndex - 1;
//Free region between Address and aligned region start.
BaseAddress = AddressRounded;
baseAddress = addressRounded;
for (BlockIndex = NextBlockIndex; BlockIndex >= 0; BlockIndex--)
for (blockIndex = nextBlockIndex; blockIndex >= 0; blockIndex--)
{
ulong BlockSize = 1UL << Blocks[BlockIndex].Order;
ulong blockSize = 1UL << _blocks[blockIndex].Order;
while (BaseAddress - BlockSize >= Address)
while (baseAddress - blockSize >= address)
{
BaseAddress -= BlockSize;
baseAddress -= blockSize;
FreeRegion(BaseAddress);
FreeRegion(baseAddress);
}
}
//Free region between aligned region end and End Address.
BaseAddress = EndAddrTruncated;
baseAddress = endAddrTruncated;
for (BlockIndex = NextBlockIndex; BlockIndex >= 0; BlockIndex--)
for (blockIndex = nextBlockIndex; blockIndex >= 0; blockIndex--)
{
ulong BlockSize = 1UL << Blocks[BlockIndex].Order;
ulong blockSize = 1UL << _blocks[blockIndex].Order;
while (BaseAddress + BlockSize <= EndAddr)
while (baseAddress + blockSize <= endAddr)
{
FreeRegion(BaseAddress);
FreeRegion(baseAddress);
BaseAddress += BlockSize;
baseAddress += blockSize;
}
}
}
public ulong GetFreePages()
{
lock (Blocks)
lock (_blocks)
{
return GetFreePagesImpl();
}
@ -411,18 +411,18 @@ namespace Ryujinx.HLE.HOS.Kernel
private ulong GetFreePagesImpl()
{
ulong AvailablePages = 0;
ulong availablePages = 0;
for (int BlockIndex = 0; BlockIndex < BlockOrdersCount; BlockIndex++)
for (int blockIndex = 0; blockIndex < _blockOrdersCount; blockIndex++)
{
KMemoryRegionBlock Block = Blocks[BlockIndex];
KMemoryRegionBlock block = _blocks[blockIndex];
ulong BlockPagesCount = (1UL << Block.Order) / KMemoryManager.PageSize;
ulong blockPagesCount = (1UL << block.Order) / KMemoryManager.PageSize;
AvailablePages += BlockPagesCount * Block.FreeCount;
availablePages += blockPagesCount * block.FreeCount;
}
return AvailablePages;
return availablePages;
}
}
}

View File

@ -5,31 +5,31 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KPageList : IEnumerable<KPageNode>
{
public LinkedList<KPageNode> Nodes { get; private set; }
public LinkedList<KPageNode> Nodes { get; }
public KPageList()
{
Nodes = new LinkedList<KPageNode>();
}
public KernelResult AddRange(ulong Address, ulong PagesCount)
public KernelResult AddRange(ulong address, ulong pagesCount)
{
if (PagesCount != 0)
if (pagesCount != 0)
{
if (Nodes.Last != null)
{
KPageNode LastNode = Nodes.Last.Value;
KPageNode lastNode = Nodes.Last.Value;
if (LastNode.Address + LastNode.PagesCount * KMemoryManager.PageSize == Address)
if (lastNode.Address + lastNode.PagesCount * KMemoryManager.PageSize == address)
{
Address = LastNode.Address;
PagesCount += LastNode.PagesCount;
address = lastNode.Address;
pagesCount += lastNode.PagesCount;
Nodes.RemoveLast();
}
}
Nodes.AddLast(new KPageNode(Address, PagesCount));
Nodes.AddLast(new KPageNode(address, pagesCount));
}
return KernelResult.Success;
@ -37,34 +37,34 @@ namespace Ryujinx.HLE.HOS.Kernel
public ulong GetPagesCount()
{
ulong Sum = 0;
ulong sum = 0;
foreach (KPageNode Node in Nodes)
foreach (KPageNode node in Nodes)
{
Sum += Node.PagesCount;
sum += node.PagesCount;
}
return Sum;
return sum;
}
public bool IsEqual(KPageList Other)
public bool IsEqual(KPageList other)
{
LinkedListNode<KPageNode> ThisNode = Nodes.First;
LinkedListNode<KPageNode> OtherNode = Other.Nodes.First;
LinkedListNode<KPageNode> thisNode = Nodes.First;
LinkedListNode<KPageNode> otherNode = other.Nodes.First;
while (ThisNode != null && OtherNode != null)
while (thisNode != null && otherNode != null)
{
if (ThisNode.Value.Address != OtherNode.Value.Address ||
ThisNode.Value.PagesCount != OtherNode.Value.PagesCount)
if (thisNode.Value.Address != otherNode.Value.Address ||
thisNode.Value.PagesCount != otherNode.Value.PagesCount)
{
return false;
}
ThisNode = ThisNode.Next;
OtherNode = OtherNode.Next;
thisNode = thisNode.Next;
otherNode = otherNode.Next;
}
return ThisNode == null && OtherNode == null;
return thisNode == null && otherNode == null;
}
public IEnumerator<KPageNode> GetEnumerator()

View File

@ -5,10 +5,10 @@ namespace Ryujinx.HLE.HOS.Kernel
public ulong Address;
public ulong PagesCount;
public KPageNode(ulong Address, ulong PagesCount)
public KPageNode(ulong address, ulong pagesCount)
{
this.Address = Address;
this.PagesCount = PagesCount;
Address = address;
PagesCount = pagesCount;
}
}
}

View File

@ -2,25 +2,25 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KPort : KAutoObject
{
public KServerPort ServerPort { get; private set; }
public KClientPort ClientPort { get; private set; }
public KServerPort ServerPort { get; }
public KClientPort ClientPort { get; }
private long NameAddress;
private bool IsLight;
private long _nameAddress;
private bool _isLight;
public KPort(Horizon System) : base(System)
public KPort(Horizon system) : base(system)
{
ServerPort = new KServerPort(System);
ClientPort = new KClientPort(System);
ServerPort = new KServerPort(system);
ClientPort = new KClientPort(system);
}
public void Initialize(int MaxSessions, bool IsLight, long NameAddress)
public void Initialize(int maxSessions, bool isLight, long nameAddress)
{
ServerPort.Initialize(this);
ClientPort.Initialize(this, MaxSessions);
ClientPort.Initialize(this, maxSessions);
this.IsLight = IsLight;
this.NameAddress = NameAddress;
_isLight = isLight;
_nameAddress = nameAddress;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,8 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KProcessCapabilities
{
public byte[] SvcAccessMask { get; private set; }
public byte[] IrqAccessMask { get; private set; }
public byte[] SvcAccessMask { get; }
public byte[] IrqAccessMask { get; }
public long AllowedCpuCoresMask { get; private set; }
public long AllowedThreadPriosMask { get; private set; }
@ -21,91 +21,91 @@ namespace Ryujinx.HLE.HOS.Kernel
IrqAccessMask = new byte[0x80];
}
public KernelResult InitializeForKernel(int[] Caps, KMemoryManager MemoryManager)
public KernelResult InitializeForKernel(int[] caps, KMemoryManager memoryManager)
{
AllowedCpuCoresMask = 0xf;
AllowedThreadPriosMask = -1;
DebuggingFlags &= ~3;
KernelReleaseVersion = KProcess.KernelVersionPacked;
return Parse(Caps, MemoryManager);
return Parse(caps, memoryManager);
}
public KernelResult InitializeForUser(int[] Caps, KMemoryManager MemoryManager)
public KernelResult InitializeForUser(int[] caps, KMemoryManager memoryManager)
{
return Parse(Caps, MemoryManager);
return Parse(caps, memoryManager);
}
private KernelResult Parse(int[] Caps, KMemoryManager MemoryManager)
private KernelResult Parse(int[] caps, KMemoryManager memoryManager)
{
int Mask0 = 0;
int Mask1 = 0;
int mask0 = 0;
int mask1 = 0;
for (int Index = 0; Index < Caps.Length; Index++)
for (int index = 0; index < caps.Length; index++)
{
int Cap = Caps[Index];
int cap = caps[index];
if (((Cap + 1) & ~Cap) != 0x40)
if (((cap + 1) & ~cap) != 0x40)
{
KernelResult Result = ParseCapability(Cap, ref Mask0, ref Mask1, MemoryManager);
KernelResult result = ParseCapability(cap, ref mask0, ref mask1, memoryManager);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
return Result;
return result;
}
}
else
{
if ((uint)Index + 1 >= Caps.Length)
if ((uint)index + 1 >= caps.Length)
{
return KernelResult.InvalidCombination;
}
int PrevCap = Cap;
int prevCap = cap;
Cap = Caps[++Index];
cap = caps[++index];
if (((Cap + 1) & ~Cap) != 0x40)
if (((cap + 1) & ~cap) != 0x40)
{
return KernelResult.InvalidCombination;
}
if ((Cap & 0x78000000) != 0)
if ((cap & 0x78000000) != 0)
{
return KernelResult.MaximumExceeded;
}
if ((Cap & 0x7ffff80) == 0)
if ((cap & 0x7ffff80) == 0)
{
return KernelResult.InvalidSize;
}
long Address = ((long)(uint)PrevCap << 5) & 0xffffff000;
long Size = ((long)(uint)Cap << 5) & 0xfffff000;
long address = ((long)(uint)prevCap << 5) & 0xffffff000;
long size = ((long)(uint)cap << 5) & 0xfffff000;
if (((ulong)(Address + Size - 1) >> 36) != 0)
if (((ulong)(address + size - 1) >> 36) != 0)
{
return KernelResult.InvalidAddress;
}
MemoryPermission Perm = (PrevCap >> 31) != 0
MemoryPermission perm = (prevCap >> 31) != 0
? MemoryPermission.Read
: MemoryPermission.ReadAndWrite;
KernelResult Result;
KernelResult result;
if ((Cap >> 31) != 0)
if ((cap >> 31) != 0)
{
Result = MemoryManager.MapNormalMemory(Address, Size, Perm);
result = memoryManager.MapNormalMemory(address, size, perm);
}
else
{
Result = MemoryManager.MapIoMemory(Address, Size, Perm);
result = memoryManager.MapIoMemory(address, size, perm);
}
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
return Result;
return result;
}
}
}
@ -113,30 +113,30 @@ namespace Ryujinx.HLE.HOS.Kernel
return KernelResult.Success;
}
private KernelResult ParseCapability(int Cap, ref int Mask0, ref int Mask1, KMemoryManager MemoryManager)
private KernelResult ParseCapability(int cap, ref int mask0, ref int mask1, KMemoryManager memoryManager)
{
int Code = (Cap + 1) & ~Cap;
int code = (cap + 1) & ~cap;
if (Code == 1)
if (code == 1)
{
return KernelResult.InvalidCapability;
}
else if (Code == 0)
else if (code == 0)
{
return KernelResult.Success;
}
int CodeMask = 1 << (32 - BitUtils.CountLeadingZeros32(Code + 1));
int codeMask = 1 << (32 - BitUtils.CountLeadingZeros32(code + 1));
//Check if the property was already set.
if (((Mask0 & CodeMask) & 0x1e008) != 0)
if (((mask0 & codeMask) & 0x1e008) != 0)
{
return KernelResult.InvalidCombination;
}
Mask0 |= CodeMask;
mask0 |= codeMask;
switch (Code)
switch (code)
{
case 8:
{
@ -145,65 +145,65 @@ namespace Ryujinx.HLE.HOS.Kernel
return KernelResult.InvalidCapability;
}
int LowestCpuCore = (Cap >> 16) & 0xff;
int HighestCpuCore = (Cap >> 24) & 0xff;
int lowestCpuCore = (cap >> 16) & 0xff;
int highestCpuCore = (cap >> 24) & 0xff;
if (LowestCpuCore > HighestCpuCore)
if (lowestCpuCore > highestCpuCore)
{
return KernelResult.InvalidCombination;
}
int HighestThreadPrio = (Cap >> 4) & 0x3f;
int LowestThreadPrio = (Cap >> 10) & 0x3f;
int highestThreadPrio = (cap >> 4) & 0x3f;
int lowestThreadPrio = (cap >> 10) & 0x3f;
if (LowestThreadPrio > HighestThreadPrio)
if (lowestThreadPrio > highestThreadPrio)
{
return KernelResult.InvalidCombination;
}
if (HighestCpuCore >= KScheduler.CpuCoresCount)
if (highestCpuCore >= KScheduler.CpuCoresCount)
{
return KernelResult.InvalidCpuCore;
}
AllowedCpuCoresMask = GetMaskFromMinMax(LowestCpuCore, HighestCpuCore);
AllowedThreadPriosMask = GetMaskFromMinMax(LowestThreadPrio, HighestThreadPrio);
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
break;
}
case 0x10:
{
int Slot = (Cap >> 29) & 7;
int slot = (cap >> 29) & 7;
int SvcSlotMask = 1 << Slot;
int svcSlotMask = 1 << slot;
if ((Mask1 & SvcSlotMask) != 0)
if ((mask1 & svcSlotMask) != 0)
{
return KernelResult.InvalidCombination;
}
Mask1 |= SvcSlotMask;
mask1 |= svcSlotMask;
int SvcMask = (Cap >> 5) & 0xffffff;
int svcMask = (cap >> 5) & 0xffffff;
int BaseSvc = Slot * 24;
int baseSvc = slot * 24;
for (int Index = 0; Index < 24; Index++)
for (int index = 0; index < 24; index++)
{
if (((SvcMask >> Index) & 1) == 0)
if (((svcMask >> index) & 1) == 0)
{
continue;
}
int SvcId = BaseSvc + Index;
int svcId = baseSvc + index;
if (SvcId > 0x7f)
if (svcId > 0x7f)
{
return KernelResult.MaximumExceeded;
}
SvcAccessMask[SvcId / 8] |= (byte)(1 << (SvcId & 7));
SvcAccessMask[svcId / 8] |= (byte)(1 << (svcId & 7));
}
break;
@ -211,9 +211,9 @@ namespace Ryujinx.HLE.HOS.Kernel
case 0x80:
{
long Address = ((long)(uint)Cap << 4) & 0xffffff000;
long address = ((long)(uint)cap << 4) & 0xffffff000;
MemoryManager.MapIoMemory(Address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite);
memoryManager.MapIoMemory(address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite);
break;
}
@ -221,17 +221,17 @@ namespace Ryujinx.HLE.HOS.Kernel
case 0x800:
{
//TODO: GIC distributor check.
int Irq0 = (Cap >> 12) & 0x3ff;
int Irq1 = (Cap >> 22) & 0x3ff;
int irq0 = (cap >> 12) & 0x3ff;
int irq1 = (cap >> 22) & 0x3ff;
if (Irq0 != 0x3ff)
if (irq0 != 0x3ff)
{
IrqAccessMask[Irq0 / 8] |= (byte)(1 << (Irq0 & 7));
IrqAccessMask[irq0 / 8] |= (byte)(1 << (irq0 & 7));
}
if (Irq1 != 0x3ff)
if (irq1 != 0x3ff)
{
IrqAccessMask[Irq1 / 8] |= (byte)(1 << (Irq1 & 7));
IrqAccessMask[irq1 / 8] |= (byte)(1 << (irq1 & 7));
}
break;
@ -239,14 +239,14 @@ namespace Ryujinx.HLE.HOS.Kernel
case 0x2000:
{
int ApplicationType = Cap >> 14;
int applicationType = cap >> 14;
if ((uint)ApplicationType > 7)
if ((uint)applicationType > 7)
{
return KernelResult.ReservedValue;
}
this.ApplicationType = ApplicationType;
ApplicationType = applicationType;
break;
}
@ -254,41 +254,41 @@ namespace Ryujinx.HLE.HOS.Kernel
case 0x4000:
{
//Note: This check is bugged on kernel too, we are just replicating the bug here.
if ((KernelReleaseVersion >> 17) != 0 || Cap < 0x80000)
if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000)
{
return KernelResult.ReservedValue;
}
KernelReleaseVersion = Cap;
KernelReleaseVersion = cap;
break;
}
case 0x8000:
{
int HandleTableSize = Cap >> 26;
int handleTableSize = cap >> 26;
if ((uint)HandleTableSize > 0x3ff)
if ((uint)handleTableSize > 0x3ff)
{
return KernelResult.ReservedValue;
}
this.HandleTableSize = HandleTableSize;
HandleTableSize = handleTableSize;
break;
}
case 0x10000:
{
int DebuggingFlags = Cap >> 19;
int debuggingFlags = cap >> 19;
if ((uint)DebuggingFlags > 3)
if ((uint)debuggingFlags > 3)
{
return KernelResult.ReservedValue;
}
this.DebuggingFlags &= ~3;
this.DebuggingFlags |= DebuggingFlags;
DebuggingFlags &= ~3;
DebuggingFlags |= debuggingFlags;
break;
}
@ -299,13 +299,13 @@ namespace Ryujinx.HLE.HOS.Kernel
return KernelResult.Success;
}
private static long GetMaskFromMinMax(int Min, int Max)
private static long GetMaskFromMinMax(int min, int max)
{
int Range = Max - Min + 1;
int range = max - min + 1;
long Mask = (1L << Range) - 1;
long mask = (1L << range) - 1;
return Mask << Min;
return mask << min;
}
}
}

View File

@ -2,22 +2,22 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KReadableEvent : KSynchronizationObject
{
private KEvent Parent;
private KEvent _parent;
private bool Signaled;
private bool _signaled;
public KReadableEvent(Horizon System, KEvent Parent) : base(System)
public KReadableEvent(Horizon system, KEvent parent) : base(system)
{
this.Parent = Parent;
_parent = parent;
}
public override void Signal()
{
System.CriticalSection.Enter();
if (!Signaled)
if (!_signaled)
{
Signaled = true;
_signaled = true;
base.Signal();
}
@ -27,36 +27,36 @@ namespace Ryujinx.HLE.HOS.Kernel
public KernelResult Clear()
{
Signaled = false;
_signaled = false;
return KernelResult.Success;
}
public KernelResult ClearIfSignaled()
{
KernelResult Result;
KernelResult result;
System.CriticalSection.Enter();
if (Signaled)
if (_signaled)
{
Signaled = false;
_signaled = false;
Result = KernelResult.Success;
result = KernelResult.Success;
}
else
{
Result = KernelResult.InvalidState;
result = KernelResult.InvalidState;
}
System.CriticalSection.Leave();
return Result;
return result;
}
public override bool IsSignaled()
{
return Signaled;
return _signaled;
}
}
}

View File

@ -7,127 +7,127 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private const int Time10SecondsMs = 10000;
private long[] Current;
private long[] Limit;
private long[] Available;
private long[] _current;
private long[] _limit;
private long[] _available;
private object LockObj;
private object _lockObj;
private LinkedList<KThread> WaitingThreads;
private LinkedList<KThread> _waitingThreads;
private int WaitingThreadsCount;
private int _waitingThreadsCount;
private Horizon System;
private Horizon _system;
public KResourceLimit(Horizon System)
public KResourceLimit(Horizon system)
{
Current = new long[(int)LimitableResource.Count];
Limit = new long[(int)LimitableResource.Count];
Available = new long[(int)LimitableResource.Count];
_current = new long[(int)LimitableResource.Count];
_limit = new long[(int)LimitableResource.Count];
_available = new long[(int)LimitableResource.Count];
LockObj = new object();
_lockObj = new object();
WaitingThreads = new LinkedList<KThread>();
_waitingThreads = new LinkedList<KThread>();
this.System = System;
_system = system;
}
public bool Reserve(LimitableResource Resource, ulong Amount)
public bool Reserve(LimitableResource resource, ulong amount)
{
return Reserve(Resource, (long)Amount);
return Reserve(resource, (long)amount);
}
public bool Reserve(LimitableResource Resource, long Amount)
public bool Reserve(LimitableResource resource, long amount)
{
return Reserve(Resource, Amount, KTimeManager.ConvertMillisecondsToNanoseconds(Time10SecondsMs));
return Reserve(resource, amount, KTimeManager.ConvertMillisecondsToNanoseconds(Time10SecondsMs));
}
public bool Reserve(LimitableResource Resource, long Amount, long Timeout)
public bool Reserve(LimitableResource resource, long amount, long timeout)
{
long EndTimePoint = KTimeManager.ConvertNanosecondsToMilliseconds(Timeout);
long endTimePoint = KTimeManager.ConvertNanosecondsToMilliseconds(timeout);
EndTimePoint += PerformanceCounter.ElapsedMilliseconds;
endTimePoint += PerformanceCounter.ElapsedMilliseconds;
bool Success = false;
bool success = false;
int Index = GetIndex(Resource);
int index = GetIndex(resource);
lock (LockObj)
lock (_lockObj)
{
long NewCurrent = Current[Index] + Amount;
long newCurrent = _current[index] + amount;
while (NewCurrent > Limit[Index] && Available[Index] + Amount <= Limit[Index])
while (newCurrent > _limit[index] && _available[index] + amount <= _limit[index])
{
WaitingThreadsCount++;
_waitingThreadsCount++;
KConditionVariable.Wait(System, WaitingThreads, LockObj, Timeout);
KConditionVariable.Wait(_system, _waitingThreads, _lockObj, timeout);
WaitingThreadsCount--;
_waitingThreadsCount--;
NewCurrent = Current[Index] + Amount;
newCurrent = _current[index] + amount;
if (Timeout >= 0 && PerformanceCounter.ElapsedMilliseconds > EndTimePoint)
if (timeout >= 0 && PerformanceCounter.ElapsedMilliseconds > endTimePoint)
{
break;
}
}
if (NewCurrent <= Limit[Index])
if (newCurrent <= _limit[index])
{
Current[Index] = NewCurrent;
_current[index] = newCurrent;
Success = true;
success = true;
}
}
return Success;
return success;
}
public void Release(LimitableResource Resource, ulong Amount)
public void Release(LimitableResource resource, ulong amount)
{
Release(Resource, (long)Amount);
Release(resource, (long)amount);
}
public void Release(LimitableResource Resource, long Amount)
public void Release(LimitableResource resource, long amount)
{
Release(Resource, Amount, Amount);
Release(resource, amount, amount);
}
private void Release(LimitableResource Resource, long UsedAmount, long AvailableAmount)
private void Release(LimitableResource resource, long usedAmount, long availableAmount)
{
int Index = GetIndex(Resource);
int index = GetIndex(resource);
lock (LockObj)
lock (_lockObj)
{
Current [Index] -= UsedAmount;
Available[Index] -= AvailableAmount;
_current [index] -= usedAmount;
_available[index] -= availableAmount;
if (WaitingThreadsCount > 0)
if (_waitingThreadsCount > 0)
{
KConditionVariable.NotifyAll(System, WaitingThreads);
KConditionVariable.NotifyAll(_system, _waitingThreads);
}
}
}
public long GetRemainingValue(LimitableResource Resource)
public long GetRemainingValue(LimitableResource resource)
{
int Index = GetIndex(Resource);
int index = GetIndex(resource);
lock (LockObj)
lock (_lockObj)
{
return Limit[Index] - Current[Index];
return _limit[index] - _current[index];
}
}
public KernelResult SetLimitValue(LimitableResource Resource, long Limit)
public KernelResult SetLimitValue(LimitableResource resource, long limit)
{
int Index = GetIndex(Resource);
int index = GetIndex(resource);
lock (LockObj)
lock (_lockObj)
{
if (Current[Index] <= Limit)
if (_current[index] <= limit)
{
this.Limit[Index] = Limit;
_limit[index] = limit;
return KernelResult.Success;
}
@ -138,9 +138,9 @@ namespace Ryujinx.HLE.HOS.Kernel
}
}
private static int GetIndex(LimitableResource Resource)
private static int GetIndex(LimitableResource resource)
{
return (int)Resource;
return (int)resource;
}
}
}

View File

@ -12,17 +12,17 @@ namespace Ryujinx.HLE.HOS.Kernel
private const int PreemptionPriorityCores012 = 59;
private const int PreemptionPriorityCore3 = 63;
private Horizon System;
private Horizon _system;
public KSchedulingData SchedulingData { get; private set; }
public KSchedulingData SchedulingData { get; }
public KCoreContext[] CoreContexts { get; private set; }
public KCoreContext[] CoreContexts { get; }
public bool ThreadReselectionRequested { get; set; }
public KScheduler(Horizon System)
public KScheduler(Horizon system)
{
this.System = System;
_system = system;
SchedulingData = new KSchedulingData();
@ -30,87 +30,87 @@ namespace Ryujinx.HLE.HOS.Kernel
CoreContexts = new KCoreContext[CpuCoresCount];
for (int Core = 0; Core < CpuCoresCount; Core++)
for (int core = 0; core < CpuCoresCount; core++)
{
CoreContexts[Core] = new KCoreContext(this, CoreManager);
CoreContexts[core] = new KCoreContext(this, CoreManager);
}
}
private void PreemptThreads()
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
PreemptThread(PreemptionPriorityCores012, 0);
PreemptThread(PreemptionPriorityCores012, 1);
PreemptThread(PreemptionPriorityCores012, 2);
PreemptThread(PreemptionPriorityCore3, 3);
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
}
private void PreemptThread(int Prio, int Core)
private void PreemptThread(int prio, int core)
{
IEnumerable<KThread> ScheduledThreads = SchedulingData.ScheduledThreads(Core);
IEnumerable<KThread> scheduledThreads = SchedulingData.ScheduledThreads(core);
KThread SelectedThread = ScheduledThreads.FirstOrDefault(x => x.DynamicPriority == Prio);
KThread selectedThread = scheduledThreads.FirstOrDefault(x => x.DynamicPriority == prio);
//Yield priority queue.
if (SelectedThread != null)
if (selectedThread != null)
{
SchedulingData.Reschedule(Prio, Core, SelectedThread);
SchedulingData.Reschedule(prio, core, selectedThread);
}
IEnumerable<KThread> SuitableCandidates()
{
foreach (KThread Thread in SchedulingData.SuggestedThreads(Core))
foreach (KThread thread in SchedulingData.SuggestedThreads(core))
{
int SrcCore = Thread.CurrentCore;
int srcCore = thread.CurrentCore;
if (SrcCore >= 0)
if (srcCore >= 0)
{
KThread HighestPrioSrcCore = SchedulingData.ScheduledThreads(SrcCore).FirstOrDefault();
KThread highestPrioSrcCore = SchedulingData.ScheduledThreads(srcCore).FirstOrDefault();
if (HighestPrioSrcCore != null && HighestPrioSrcCore.DynamicPriority < 2)
if (highestPrioSrcCore != null && highestPrioSrcCore.DynamicPriority < 2)
{
break;
}
if (HighestPrioSrcCore == Thread)
if (highestPrioSrcCore == thread)
{
continue;
}
}
//If the candidate was scheduled after the current thread, then it's not worth it.
if (SelectedThread == null || SelectedThread.LastScheduledTime >= Thread.LastScheduledTime)
if (selectedThread == null || selectedThread.LastScheduledTime >= thread.LastScheduledTime)
{
yield return Thread;
yield return thread;
}
}
}
//Select candidate threads that could run on this core.
//Only take into account threads that are not yet selected.
KThread Dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority == Prio);
KThread dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority == prio);
if (Dst != null)
if (dst != null)
{
SchedulingData.TransferToCore(Prio, Core, Dst);
SchedulingData.TransferToCore(prio, core, dst);
SelectedThread = Dst;
selectedThread = dst;
}
//If the priority of the currently selected thread is lower than preemption priority,
//then allow threads with lower priorities to be selected aswell.
if (SelectedThread != null && SelectedThread.DynamicPriority > Prio)
if (selectedThread != null && selectedThread.DynamicPriority > prio)
{
Func<KThread, bool> Predicate = x => x.DynamicPriority >= SelectedThread.DynamicPriority;
Func<KThread, bool> predicate = x => x.DynamicPriority >= selectedThread.DynamicPriority;
Dst = SuitableCandidates().FirstOrDefault(Predicate);
dst = SuitableCandidates().FirstOrDefault(predicate);
if (Dst != null)
if (dst != null)
{
SchedulingData.TransferToCore(Dst.DynamicPriority, Core, Dst);
SchedulingData.TransferToCore(dst.DynamicPriority, core, dst);
}
}
@ -121,52 +121,52 @@ namespace Ryujinx.HLE.HOS.Kernel
{
ThreadReselectionRequested = false;
for (int Core = 0; Core < CpuCoresCount; Core++)
for (int core = 0; core < CpuCoresCount; core++)
{
KThread Thread = SchedulingData.ScheduledThreads(Core).FirstOrDefault();
KThread thread = SchedulingData.ScheduledThreads(core).FirstOrDefault();
CoreContexts[Core].SelectThread(Thread);
CoreContexts[core].SelectThread(thread);
}
for (int Core = 0; Core < CpuCoresCount; Core++)
for (int core = 0; core < CpuCoresCount; core++)
{
//If the core is not idle (there's already a thread running on it),
//then we don't need to attempt load balancing.
if (SchedulingData.ScheduledThreads(Core).Any())
if (SchedulingData.ScheduledThreads(core).Any())
{
continue;
}
int[] SrcCoresHighestPrioThreads = new int[CpuCoresCount];
int[] srcCoresHighestPrioThreads = new int[CpuCoresCount];
int SrcCoresHighestPrioThreadsCount = 0;
int srcCoresHighestPrioThreadsCount = 0;
KThread Dst = null;
KThread dst = null;
//Select candidate threads that could run on this core.
//Give preference to threads that are not yet selected.
foreach (KThread Thread in SchedulingData.SuggestedThreads(Core))
foreach (KThread thread in SchedulingData.SuggestedThreads(core))
{
if (Thread.CurrentCore < 0 || Thread != CoreContexts[Thread.CurrentCore].SelectedThread)
if (thread.CurrentCore < 0 || thread != CoreContexts[thread.CurrentCore].SelectedThread)
{
Dst = Thread;
dst = thread;
break;
}
SrcCoresHighestPrioThreads[SrcCoresHighestPrioThreadsCount++] = Thread.CurrentCore;
srcCoresHighestPrioThreads[srcCoresHighestPrioThreadsCount++] = thread.CurrentCore;
}
//Not yet selected candidate found.
if (Dst != null)
if (dst != null)
{
//Priorities < 2 are used for the kernel message dispatching
//threads, we should skip load balancing entirely.
if (Dst.DynamicPriority >= 2)
if (dst.DynamicPriority >= 2)
{
SchedulingData.TransferToCore(Dst.DynamicPriority, Core, Dst);
SchedulingData.TransferToCore(dst.DynamicPriority, core, dst);
CoreContexts[Core].SelectThread(Dst);
CoreContexts[core].SelectThread(dst);
}
continue;
@ -174,23 +174,23 @@ namespace Ryujinx.HLE.HOS.Kernel
//All candiates are already selected, choose the best one
//(the first one that doesn't make the source core idle if moved).
for (int Index = 0; Index < SrcCoresHighestPrioThreadsCount; Index++)
for (int index = 0; index < srcCoresHighestPrioThreadsCount; index++)
{
int SrcCore = SrcCoresHighestPrioThreads[Index];
int srcCore = srcCoresHighestPrioThreads[index];
KThread Src = SchedulingData.ScheduledThreads(SrcCore).ElementAtOrDefault(1);
KThread src = SchedulingData.ScheduledThreads(srcCore).ElementAtOrDefault(1);
if (Src != null)
if (src != null)
{
//Run the second thread on the queue on the source core,
//move the first one to the current core.
KThread OrigSelectedCoreSrc = CoreContexts[SrcCore].SelectedThread;
KThread origSelectedCoreSrc = CoreContexts[srcCore].SelectedThread;
CoreContexts[SrcCore].SelectThread(Src);
CoreContexts[srcCore].SelectThread(src);
SchedulingData.TransferToCore(OrigSelectedCoreSrc.DynamicPriority, Core, OrigSelectedCoreSrc);
SchedulingData.TransferToCore(origSelectedCoreSrc.DynamicPriority, core, origSelectedCoreSrc);
CoreContexts[Core].SelectThread(OrigSelectedCoreSrc);
CoreContexts[core].SelectThread(origSelectedCoreSrc);
}
}
}
@ -200,11 +200,11 @@ namespace Ryujinx.HLE.HOS.Kernel
{
lock (CoreContexts)
{
for (int Core = 0; Core < CpuCoresCount; Core++)
for (int core = 0; core < CpuCoresCount; core++)
{
if (CoreContexts[Core].CurrentThread?.Context.IsCurrentThread() ?? false)
if (CoreContexts[core].CurrentThread?.Context.IsCurrentThread() ?? false)
{
return CoreContexts[Core].CurrentThread;
return CoreContexts[core].CurrentThread;
}
}
}
@ -222,11 +222,11 @@ namespace Ryujinx.HLE.HOS.Kernel
Dispose(true);
}
protected virtual void Dispose(bool Disposing)
protected virtual void Dispose(bool disposing)
{
if (Disposing)
if (disposing)
{
KeepPreempting = false;
_keepPreempting = false;
}
}
}

View File

@ -4,204 +4,204 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KSchedulingData
{
private LinkedList<KThread>[][] ScheduledThreadsPerPrioPerCore;
private LinkedList<KThread>[][] SuggestedThreadsPerPrioPerCore;
private LinkedList<KThread>[][] _scheduledThreadsPerPrioPerCore;
private LinkedList<KThread>[][] _suggestedThreadsPerPrioPerCore;
private long[] ScheduledPrioritiesPerCore;
private long[] SuggestedPrioritiesPerCore;
private long[] _scheduledPrioritiesPerCore;
private long[] _suggestedPrioritiesPerCore;
public KSchedulingData()
{
SuggestedThreadsPerPrioPerCore = new LinkedList<KThread>[KScheduler.PrioritiesCount][];
ScheduledThreadsPerPrioPerCore = new LinkedList<KThread>[KScheduler.PrioritiesCount][];
_suggestedThreadsPerPrioPerCore = new LinkedList<KThread>[KScheduler.PrioritiesCount][];
_scheduledThreadsPerPrioPerCore = new LinkedList<KThread>[KScheduler.PrioritiesCount][];
for (int Prio = 0; Prio < KScheduler.PrioritiesCount; Prio++)
for (int prio = 0; prio < KScheduler.PrioritiesCount; prio++)
{
SuggestedThreadsPerPrioPerCore[Prio] = new LinkedList<KThread>[KScheduler.CpuCoresCount];
ScheduledThreadsPerPrioPerCore[Prio] = new LinkedList<KThread>[KScheduler.CpuCoresCount];
_suggestedThreadsPerPrioPerCore[prio] = new LinkedList<KThread>[KScheduler.CpuCoresCount];
_scheduledThreadsPerPrioPerCore[prio] = new LinkedList<KThread>[KScheduler.CpuCoresCount];
for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
for (int core = 0; core < KScheduler.CpuCoresCount; core++)
{
SuggestedThreadsPerPrioPerCore[Prio][Core] = new LinkedList<KThread>();
ScheduledThreadsPerPrioPerCore[Prio][Core] = new LinkedList<KThread>();
_suggestedThreadsPerPrioPerCore[prio][core] = new LinkedList<KThread>();
_scheduledThreadsPerPrioPerCore[prio][core] = new LinkedList<KThread>();
}
}
ScheduledPrioritiesPerCore = new long[KScheduler.CpuCoresCount];
SuggestedPrioritiesPerCore = new long[KScheduler.CpuCoresCount];
_scheduledPrioritiesPerCore = new long[KScheduler.CpuCoresCount];
_suggestedPrioritiesPerCore = new long[KScheduler.CpuCoresCount];
}
public IEnumerable<KThread> SuggestedThreads(int Core)
public IEnumerable<KThread> SuggestedThreads(int core)
{
return Iterate(SuggestedThreadsPerPrioPerCore, SuggestedPrioritiesPerCore, Core);
return Iterate(_suggestedThreadsPerPrioPerCore, _suggestedPrioritiesPerCore, core);
}
public IEnumerable<KThread> ScheduledThreads(int Core)
public IEnumerable<KThread> ScheduledThreads(int core)
{
return Iterate(ScheduledThreadsPerPrioPerCore, ScheduledPrioritiesPerCore, Core);
return Iterate(_scheduledThreadsPerPrioPerCore, _scheduledPrioritiesPerCore, core);
}
private IEnumerable<KThread> Iterate(LinkedList<KThread>[][] ListPerPrioPerCore, long[] Prios, int Core)
private IEnumerable<KThread> Iterate(LinkedList<KThread>[][] listPerPrioPerCore, long[] prios, int core)
{
long PrioMask = Prios[Core];
long prioMask = prios[core];
int Prio = CountTrailingZeros(PrioMask);
int prio = CountTrailingZeros(prioMask);
PrioMask &= ~(1L << Prio);
prioMask &= ~(1L << prio);
while (Prio < KScheduler.PrioritiesCount)
while (prio < KScheduler.PrioritiesCount)
{
LinkedList<KThread> List = ListPerPrioPerCore[Prio][Core];
LinkedList<KThread> list = listPerPrioPerCore[prio][core];
LinkedListNode<KThread> Node = List.First;
LinkedListNode<KThread> node = list.First;
while (Node != null)
while (node != null)
{
yield return Node.Value;
yield return node.Value;
Node = Node.Next;
node = node.Next;
}
Prio = CountTrailingZeros(PrioMask);
prio = CountTrailingZeros(prioMask);
PrioMask &= ~(1L << Prio);
prioMask &= ~(1L << prio);
}
}
private int CountTrailingZeros(long Value)
private int CountTrailingZeros(long value)
{
int Count = 0;
int count = 0;
while (((Value >> Count) & 0xf) == 0 && Count < 64)
while (((value >> count) & 0xf) == 0 && count < 64)
{
Count += 4;
count += 4;
}
while (((Value >> Count) & 1) == 0 && Count < 64)
while (((value >> count) & 1) == 0 && count < 64)
{
Count++;
count++;
}
return Count;
return count;
}
public void TransferToCore(int Prio, int DstCore, KThread Thread)
public void TransferToCore(int prio, int dstCore, KThread thread)
{
bool Schedulable = Thread.DynamicPriority < KScheduler.PrioritiesCount;
bool schedulable = thread.DynamicPriority < KScheduler.PrioritiesCount;
int SrcCore = Thread.CurrentCore;
int srcCore = thread.CurrentCore;
Thread.CurrentCore = DstCore;
thread.CurrentCore = dstCore;
if (SrcCore == DstCore || !Schedulable)
if (srcCore == dstCore || !schedulable)
{
return;
}
if (SrcCore >= 0)
if (srcCore >= 0)
{
Unschedule(Prio, SrcCore, Thread);
Unschedule(prio, srcCore, thread);
}
if (DstCore >= 0)
if (dstCore >= 0)
{
Unsuggest(Prio, DstCore, Thread);
Schedule(Prio, DstCore, Thread);
Unsuggest(prio, dstCore, thread);
Schedule(prio, dstCore, thread);
}
if (SrcCore >= 0)
if (srcCore >= 0)
{
Suggest(Prio, SrcCore, Thread);
Suggest(prio, srcCore, thread);
}
}
public void Suggest(int Prio, int Core, KThread Thread)
public void Suggest(int prio, int core, KThread thread)
{
if (Prio >= KScheduler.PrioritiesCount)
if (prio >= KScheduler.PrioritiesCount)
{
return;
}
Thread.SiblingsPerCore[Core] = SuggestedQueue(Prio, Core).AddFirst(Thread);
thread.SiblingsPerCore[core] = SuggestedQueue(prio, core).AddFirst(thread);
SuggestedPrioritiesPerCore[Core] |= 1L << Prio;
_suggestedPrioritiesPerCore[core] |= 1L << prio;
}
public void Unsuggest(int Prio, int Core, KThread Thread)
public void Unsuggest(int prio, int core, KThread thread)
{
if (Prio >= KScheduler.PrioritiesCount)
if (prio >= KScheduler.PrioritiesCount)
{
return;
}
LinkedList<KThread> Queue = SuggestedQueue(Prio, Core);
LinkedList<KThread> queue = SuggestedQueue(prio, core);
Queue.Remove(Thread.SiblingsPerCore[Core]);
queue.Remove(thread.SiblingsPerCore[core]);
if (Queue.First == null)
if (queue.First == null)
{
SuggestedPrioritiesPerCore[Core] &= ~(1L << Prio);
_suggestedPrioritiesPerCore[core] &= ~(1L << prio);
}
}
public void Schedule(int Prio, int Core, KThread Thread)
public void Schedule(int prio, int core, KThread thread)
{
if (Prio >= KScheduler.PrioritiesCount)
if (prio >= KScheduler.PrioritiesCount)
{
return;
}
Thread.SiblingsPerCore[Core] = ScheduledQueue(Prio, Core).AddLast(Thread);
thread.SiblingsPerCore[core] = ScheduledQueue(prio, core).AddLast(thread);
ScheduledPrioritiesPerCore[Core] |= 1L << Prio;
_scheduledPrioritiesPerCore[core] |= 1L << prio;
}
public void SchedulePrepend(int Prio, int Core, KThread Thread)
public void SchedulePrepend(int prio, int core, KThread thread)
{
if (Prio >= KScheduler.PrioritiesCount)
if (prio >= KScheduler.PrioritiesCount)
{
return;
}
Thread.SiblingsPerCore[Core] = ScheduledQueue(Prio, Core).AddFirst(Thread);
thread.SiblingsPerCore[core] = ScheduledQueue(prio, core).AddFirst(thread);
ScheduledPrioritiesPerCore[Core] |= 1L << Prio;
_scheduledPrioritiesPerCore[core] |= 1L << prio;
}
public void Reschedule(int Prio, int Core, KThread Thread)
public void Reschedule(int prio, int core, KThread thread)
{
LinkedList<KThread> Queue = ScheduledQueue(Prio, Core);
LinkedList<KThread> queue = ScheduledQueue(prio, core);
Queue.Remove(Thread.SiblingsPerCore[Core]);
queue.Remove(thread.SiblingsPerCore[core]);
Thread.SiblingsPerCore[Core] = Queue.AddLast(Thread);
thread.SiblingsPerCore[core] = queue.AddLast(thread);
}
public void Unschedule(int Prio, int Core, KThread Thread)
public void Unschedule(int prio, int core, KThread thread)
{
if (Prio >= KScheduler.PrioritiesCount)
if (prio >= KScheduler.PrioritiesCount)
{
return;
}
LinkedList<KThread> Queue = ScheduledQueue(Prio, Core);
LinkedList<KThread> queue = ScheduledQueue(prio, core);
Queue.Remove(Thread.SiblingsPerCore[Core]);
queue.Remove(thread.SiblingsPerCore[core]);
if (Queue.First == null)
if (queue.First == null)
{
ScheduledPrioritiesPerCore[Core] &= ~(1L << Prio);
_scheduledPrioritiesPerCore[core] &= ~(1L << prio);
}
}
private LinkedList<KThread> SuggestedQueue(int Prio, int Core)
private LinkedList<KThread> SuggestedQueue(int prio, int core)
{
return SuggestedThreadsPerPrioPerCore[Prio][Core];
return _suggestedThreadsPerPrioPerCore[prio][core];
}
private LinkedList<KThread> ScheduledQueue(int Prio, int Core)
private LinkedList<KThread> ScheduledQueue(int prio, int core)
{
return ScheduledThreadsPerPrioPerCore[Prio][Core];
return _scheduledThreadsPerPrioPerCore[prio][core];
}
}
}

View File

@ -2,13 +2,13 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KServerPort : KSynchronizationObject
{
private KPort Parent;
private KPort _parent;
public KServerPort(Horizon System) : base(System) { }
public KServerPort(Horizon system) : base(system) { }
public void Initialize(KPort Parent)
public void Initialize(KPort parent)
{
this.Parent = Parent;
_parent = parent;
}
}
}

View File

@ -5,14 +5,14 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KSession : IDisposable
{
public IpcService Service { get; private set; }
public IpcService Service { get; }
public string ServiceName { get; private set; }
public string ServiceName { get; }
public KSession(IpcService Service, string ServiceName)
public KSession(IpcService service, string serviceName)
{
this.Service = Service;
this.ServiceName = ServiceName;
Service = service;
ServiceName = serviceName;
}
public void Dispose()
@ -20,11 +20,11 @@ namespace Ryujinx.HLE.HOS.Kernel
Dispose(true);
}
protected virtual void Dispose(bool Disposing)
protected virtual void Dispose(bool disposing)
{
if (Disposing && Service is IDisposable DisposableService)
if (disposing && Service is IDisposable disposableService)
{
DisposableService.Dispose();
disposableService.Dispose();
}
}
}

View File

@ -4,65 +4,65 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KSharedMemory
{
private KPageList PageList;
private KPageList _pageList;
private long OwnerPid;
private long _ownerPid;
private MemoryPermission OwnerPermission;
private MemoryPermission UserPermission;
private MemoryPermission _ownerPermission;
private MemoryPermission _userPermission;
public KSharedMemory(
KPageList PageList,
long OwnerPid,
MemoryPermission OwnerPermission,
MemoryPermission UserPermission)
KPageList pageList,
long ownerPid,
MemoryPermission ownerPermission,
MemoryPermission userPermission)
{
this.PageList = PageList;
this.OwnerPid = OwnerPid;
this.OwnerPermission = OwnerPermission;
this.UserPermission = UserPermission;
_pageList = pageList;
_ownerPid = ownerPid;
_ownerPermission = ownerPermission;
_userPermission = userPermission;
}
public KernelResult MapIntoProcess(
KMemoryManager MemoryManager,
ulong Address,
ulong Size,
KProcess Process,
MemoryPermission Permission)
KMemoryManager memoryManager,
ulong address,
ulong size,
KProcess process,
MemoryPermission permission)
{
ulong PagesCountRounded = BitUtils.DivRoundUp(Size, KMemoryManager.PageSize);
ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize);
if (PageList.GetPagesCount() != PagesCountRounded)
if (_pageList.GetPagesCount() != pagesCountRounded)
{
return KernelResult.InvalidSize;
}
MemoryPermission ExpectedPermission = Process.Pid == OwnerPid
? OwnerPermission
: UserPermission;
MemoryPermission expectedPermission = process.Pid == _ownerPid
? _ownerPermission
: _userPermission;
if (Permission != ExpectedPermission)
if (permission != expectedPermission)
{
return KernelResult.InvalidPermission;
}
return MemoryManager.MapPages(Address, PageList, MemoryState.SharedMemory, Permission);
return memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission);
}
public KernelResult UnmapFromProcess(
KMemoryManager MemoryManager,
ulong Address,
ulong Size,
KProcess Process)
KMemoryManager memoryManager,
ulong address,
ulong size,
KProcess process)
{
ulong PagesCountRounded = BitUtils.DivRoundUp(Size, KMemoryManager.PageSize);
ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize);
if (PageList.GetPagesCount() != PagesCountRounded)
if (_pageList.GetPagesCount() != pagesCountRounded)
{
return KernelResult.InvalidSize;
}
return MemoryManager.UnmapPages(Address, PageList, MemoryState.SharedMemory);
return memoryManager.UnmapPages(address, _pageList, MemoryState.SharedMemory);
}
}
}

View File

@ -4,46 +4,46 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KSlabHeap
{
private LinkedList<ulong> Items;
private LinkedList<ulong> _items;
public KSlabHeap(ulong Pa, ulong ItemSize, ulong Size)
public KSlabHeap(ulong pa, ulong itemSize, ulong size)
{
Items = new LinkedList<ulong>();
_items = new LinkedList<ulong>();
int ItemsCount = (int)(Size / ItemSize);
int itemsCount = (int)(size / itemSize);
for (int Index = 0; Index < ItemsCount; Index++)
for (int index = 0; index < itemsCount; index++)
{
Items.AddLast(Pa);
_items.AddLast(pa);
Pa += ItemSize;
pa += itemSize;
}
}
public bool TryGetItem(out ulong Pa)
public bool TryGetItem(out ulong pa)
{
lock (Items)
lock (_items)
{
if (Items.First != null)
if (_items.First != null)
{
Pa = Items.First.Value;
pa = _items.First.Value;
Items.RemoveFirst();
_items.RemoveFirst();
return true;
}
}
Pa = 0;
pa = 0;
return false;
}
public void Free(ulong Pa)
public void Free(ulong pa)
{
lock (Items)
lock (_items)
{
Items.AddFirst(Pa);
_items.AddFirst(pa);
}
}
}

View File

@ -6,130 +6,130 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KSynchronization
{
private Horizon System;
private Horizon _system;
public KSynchronization(Horizon System)
public KSynchronization(Horizon system)
{
this.System = System;
_system = system;
}
public long WaitFor(KSynchronizationObject[] SyncObjs, long Timeout, ref int HndIndex)
public long WaitFor(KSynchronizationObject[] syncObjs, long timeout, ref int hndIndex)
{
long Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
long result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
//Check if objects are already signaled before waiting.
for (int Index = 0; Index < SyncObjs.Length; Index++)
for (int index = 0; index < syncObjs.Length; index++)
{
if (!SyncObjs[Index].IsSignaled())
if (!syncObjs[index].IsSignaled())
{
continue;
}
HndIndex = Index;
hndIndex = index;
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return 0;
}
if (Timeout == 0)
if (timeout == 0)
{
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return Result;
return result;
}
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
if (CurrentThread.ShallBeTerminated ||
CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
if (currentThread.ShallBeTerminated ||
currentThread.SchedFlags == ThreadSchedState.TerminationPending)
{
Result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
}
else if (CurrentThread.SyncCancelled)
else if (currentThread.SyncCancelled)
{
CurrentThread.SyncCancelled = false;
currentThread.SyncCancelled = false;
Result = MakeError(ErrorModule.Kernel, KernelErr.Cancelled);
result = MakeError(ErrorModule.Kernel, KernelErr.Cancelled);
}
else
{
LinkedListNode<KThread>[] SyncNodes = new LinkedListNode<KThread>[SyncObjs.Length];
LinkedListNode<KThread>[] syncNodes = new LinkedListNode<KThread>[syncObjs.Length];
for (int Index = 0; Index < SyncObjs.Length; Index++)
for (int index = 0; index < syncObjs.Length; index++)
{
SyncNodes[Index] = SyncObjs[Index].AddWaitingThread(CurrentThread);
syncNodes[index] = syncObjs[index].AddWaitingThread(currentThread);
}
CurrentThread.WaitingSync = true;
CurrentThread.SignaledObj = null;
CurrentThread.ObjSyncResult = (int)Result;
currentThread.WaitingSync = true;
currentThread.SignaledObj = null;
currentThread.ObjSyncResult = (int)result;
CurrentThread.Reschedule(ThreadSchedState.Paused);
currentThread.Reschedule(ThreadSchedState.Paused);
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
_system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
CurrentThread.WaitingSync = false;
currentThread.WaitingSync = false;
if (Timeout > 0)
if (timeout > 0)
{
System.TimeManager.UnscheduleFutureInvocation(CurrentThread);
_system.TimeManager.UnscheduleFutureInvocation(currentThread);
}
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
Result = (uint)CurrentThread.ObjSyncResult;
result = (uint)currentThread.ObjSyncResult;
HndIndex = -1;
hndIndex = -1;
for (int Index = 0; Index < SyncObjs.Length; Index++)
for (int index = 0; index < syncObjs.Length; index++)
{
SyncObjs[Index].RemoveWaitingThread(SyncNodes[Index]);
syncObjs[index].RemoveWaitingThread(syncNodes[index]);
if (SyncObjs[Index] == CurrentThread.SignaledObj)
if (syncObjs[index] == currentThread.SignaledObj)
{
HndIndex = Index;
hndIndex = index;
}
}
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
return Result;
return result;
}
public void SignalObject(KSynchronizationObject SyncObj)
public void SignalObject(KSynchronizationObject syncObj)
{
System.CriticalSection.Enter();
_system.CriticalSection.Enter();
if (SyncObj.IsSignaled())
if (syncObj.IsSignaled())
{
LinkedListNode<KThread> Node = SyncObj.WaitingThreads.First;
LinkedListNode<KThread> node = syncObj.WaitingThreads.First;
while (Node != null)
while (node != null)
{
KThread Thread = Node.Value;
KThread thread = node.Value;
if ((Thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
{
Thread.SignaledObj = SyncObj;
Thread.ObjSyncResult = 0;
thread.SignaledObj = syncObj;
thread.ObjSyncResult = 0;
Thread.Reschedule(ThreadSchedState.Running);
thread.Reschedule(ThreadSchedState.Running);
}
Node = Node.Next;
node = node.Next;
}
}
System.CriticalSection.Leave();
_system.CriticalSection.Leave();
}
}
}

View File

@ -6,19 +6,19 @@ namespace Ryujinx.HLE.HOS.Kernel
{
public LinkedList<KThread> WaitingThreads;
public KSynchronizationObject(Horizon System) : base(System)
public KSynchronizationObject(Horizon system) : base(system)
{
WaitingThreads = new LinkedList<KThread>();
}
public LinkedListNode<KThread> AddWaitingThread(KThread Thread)
public LinkedListNode<KThread> AddWaitingThread(KThread thread)
{
return WaitingThreads.AddLast(Thread);
return WaitingThreads.AddLast(thread);
}
public void RemoveWaitingThread(LinkedListNode<KThread> Node)
public void RemoveWaitingThread(LinkedListNode<KThread> node)
{
WaitingThreads.Remove(Node);
WaitingThreads.Remove(node);
}
public virtual void Signal()

File diff suppressed because it is too large Load Diff

View File

@ -10,116 +10,116 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private class WaitingObject
{
public IKFutureSchedulerObject Object { get; private set; }
public IKFutureSchedulerObject Object { get; }
public long TimePoint { get; private set; }
public long TimePoint { get; }
public WaitingObject(IKFutureSchedulerObject Object, long TimePoint)
public WaitingObject(IKFutureSchedulerObject schedulerObj, long timePoint)
{
this.Object = Object;
this.TimePoint = TimePoint;
Object = schedulerObj;
TimePoint = timePoint;
}
}
private List<WaitingObject> WaitingObjects;
private List<WaitingObject> _waitingObjects;
private AutoResetEvent WaitEvent;
private AutoResetEvent _waitEvent;
private bool KeepRunning;
private bool _keepRunning;
public KTimeManager()
{
WaitingObjects = new List<WaitingObject>();
_waitingObjects = new List<WaitingObject>();
KeepRunning = true;
_keepRunning = true;
Thread Work = new Thread(WaitAndCheckScheduledObjects);
Thread work = new Thread(WaitAndCheckScheduledObjects);
Work.Start();
work.Start();
}
public void ScheduleFutureInvocation(IKFutureSchedulerObject Object, long Timeout)
public void ScheduleFutureInvocation(IKFutureSchedulerObject schedulerObj, long timeout)
{
long TimePoint = PerformanceCounter.ElapsedMilliseconds + ConvertNanosecondsToMilliseconds(Timeout);
long timePoint = PerformanceCounter.ElapsedMilliseconds + ConvertNanosecondsToMilliseconds(timeout);
lock (WaitingObjects)
lock (_waitingObjects)
{
WaitingObjects.Add(new WaitingObject(Object, TimePoint));
_waitingObjects.Add(new WaitingObject(schedulerObj, timePoint));
}
WaitEvent.Set();
_waitEvent.Set();
}
public static long ConvertNanosecondsToMilliseconds(long Time)
public static long ConvertNanosecondsToMilliseconds(long time)
{
Time /= 1000000;
time /= 1000000;
if ((ulong)Time > int.MaxValue)
if ((ulong)time > int.MaxValue)
{
return int.MaxValue;
}
return Time;
return time;
}
public static long ConvertMillisecondsToNanoseconds(long Time)
public static long ConvertMillisecondsToNanoseconds(long time)
{
return Time * 1000000;
return time * 1000000;
}
public static long ConvertMillisecondsToTicks(long Time)
public static long ConvertMillisecondsToTicks(long time)
{
return Time * 19200;
return time * 19200;
}
public void UnscheduleFutureInvocation(IKFutureSchedulerObject Object)
{
lock (WaitingObjects)
lock (_waitingObjects)
{
WaitingObjects.RemoveAll(x => x.Object == Object);
_waitingObjects.RemoveAll(x => x.Object == Object);
}
}
private void WaitAndCheckScheduledObjects()
{
using (WaitEvent = new AutoResetEvent(false))
using (_waitEvent = new AutoResetEvent(false))
{
while (KeepRunning)
while (_keepRunning)
{
WaitingObject Next;
WaitingObject next;
lock (WaitingObjects)
lock (_waitingObjects)
{
Next = WaitingObjects.OrderBy(x => x.TimePoint).FirstOrDefault();
next = _waitingObjects.OrderBy(x => x.TimePoint).FirstOrDefault();
}
if (Next != null)
if (next != null)
{
long TimePoint = PerformanceCounter.ElapsedMilliseconds;
long timePoint = PerformanceCounter.ElapsedMilliseconds;
if (Next.TimePoint > TimePoint)
if (next.TimePoint > timePoint)
{
WaitEvent.WaitOne((int)(Next.TimePoint - TimePoint));
_waitEvent.WaitOne((int)(next.TimePoint - timePoint));
}
bool TimeUp = PerformanceCounter.ElapsedMilliseconds >= Next.TimePoint;
bool timeUp = PerformanceCounter.ElapsedMilliseconds >= next.TimePoint;
if (TimeUp)
if (timeUp)
{
lock (WaitingObjects)
lock (_waitingObjects)
{
TimeUp = WaitingObjects.Remove(Next);
timeUp = _waitingObjects.Remove(next);
}
}
if (TimeUp)
if (timeUp)
{
Next.Object.TimeUp();
next.Object.TimeUp();
}
}
else
{
WaitEvent.WaitOne();
_waitEvent.WaitOne();
}
}
}
@ -130,13 +130,13 @@ namespace Ryujinx.HLE.HOS.Kernel
Dispose(true);
}
protected virtual void Dispose(bool Disposing)
protected virtual void Dispose(bool disposing)
{
if (Disposing)
if (disposing)
{
KeepRunning = false;
_keepRunning = false;
WaitEvent?.Set();
_waitEvent?.Set();
}
}
}

View File

@ -4,70 +4,70 @@ namespace Ryujinx.HLE.HOS.Kernel
{
public const int TlsEntrySize = 0x200;
public ulong PageAddr { get; private set; }
public ulong PageAddr { get; }
private bool[] IsSlotFree;
private bool[] _isSlotFree;
public KTlsPageInfo(ulong PageAddress)
public KTlsPageInfo(ulong pageAddress)
{
this.PageAddr = PageAddress;
PageAddr = pageAddress;
IsSlotFree = new bool[KMemoryManager.PageSize / TlsEntrySize];
_isSlotFree = new bool[KMemoryManager.PageSize / TlsEntrySize];
for (int Index = 0; Index < IsSlotFree.Length; Index++)
for (int index = 0; index < _isSlotFree.Length; index++)
{
IsSlotFree[Index] = true;
_isSlotFree[index] = true;
}
}
public bool TryGetFreePage(out ulong Address)
public bool TryGetFreePage(out ulong address)
{
Address = PageAddr;
address = PageAddr;
for (int Index = 0; Index < IsSlotFree.Length; Index++)
for (int index = 0; index < _isSlotFree.Length; index++)
{
if (IsSlotFree[Index])
if (_isSlotFree[index])
{
IsSlotFree[Index] = false;
_isSlotFree[index] = false;
return true;
}
Address += TlsEntrySize;
address += TlsEntrySize;
}
Address = 0;
address = 0;
return false;
}
public bool IsFull()
{
bool HasFree = false;
bool hasFree = false;
for (int Index = 0; Index < IsSlotFree.Length; Index++)
for (int index = 0; index < _isSlotFree.Length; index++)
{
HasFree |= IsSlotFree[Index];
hasFree |= _isSlotFree[index];
}
return !HasFree;
return !hasFree;
}
public bool IsEmpty()
{
bool AllFree = true;
bool allFree = true;
for (int Index = 0; Index < IsSlotFree.Length; Index++)
for (int index = 0; index < _isSlotFree.Length; index++)
{
AllFree &= IsSlotFree[Index];
allFree &= _isSlotFree[index];
}
return AllFree;
return allFree;
}
public void FreeTlsSlot(ulong Address)
public void FreeTlsSlot(ulong address)
{
IsSlotFree[(Address - PageAddr) / TlsEntrySize] = true;
_isSlotFree[(address - PageAddr) / TlsEntrySize] = true;
}
}
}

View File

@ -6,55 +6,55 @@ namespace Ryujinx.HLE.HOS.Kernel
{
private const int TlsEntrySize = 0x200;
private long PagePosition;
private long _pagePosition;
private int UsedSlots;
private int _usedSlots;
private bool[] Slots;
private bool[] _slots;
public bool IsEmpty => UsedSlots == 0;
public bool IsFull => UsedSlots == Slots.Length;
public bool IsEmpty => _usedSlots == 0;
public bool IsFull => _usedSlots == _slots.Length;
public KTlsPageManager(long PagePosition)
public KTlsPageManager(long pagePosition)
{
this.PagePosition = PagePosition;
_pagePosition = pagePosition;
Slots = new bool[KMemoryManager.PageSize / TlsEntrySize];
_slots = new bool[KMemoryManager.PageSize / TlsEntrySize];
}
public bool TryGetFreeTlsAddr(out long Position)
public bool TryGetFreeTlsAddr(out long position)
{
Position = PagePosition;
position = _pagePosition;
for (int Index = 0; Index < Slots.Length; Index++)
for (int index = 0; index < _slots.Length; index++)
{
if (!Slots[Index])
if (!_slots[index])
{
Slots[Index] = true;
_slots[index] = true;
UsedSlots++;
_usedSlots++;
return true;
}
Position += TlsEntrySize;
position += TlsEntrySize;
}
Position = 0;
position = 0;
return false;
}
public void FreeTlsSlot(int Slot)
public void FreeTlsSlot(int slot)
{
if ((uint)Slot > Slots.Length)
if ((uint)slot > _slots.Length)
{
throw new ArgumentOutOfRangeException(nameof(Slot));
throw new ArgumentOutOfRangeException(nameof(slot));
}
Slots[Slot] = false;
_slots[slot] = false;
UsedSlots--;
_usedSlots--;
}
}
}

View File

@ -2,13 +2,13 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KTransferMemory
{
public ulong Address { get; private set; }
public ulong Size { get; private set; }
public ulong Address { get; }
public ulong Size { get; }
public KTransferMemory(ulong Address, ulong Size)
public KTransferMemory(ulong address, ulong size)
{
this.Address = Address;
this.Size = Size;
Address = address;
Size = size;
}
}
}

View File

@ -2,21 +2,21 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class KWritableEvent
{
private KEvent Parent;
private KEvent _parent;
public KWritableEvent(KEvent Parent)
public KWritableEvent(KEvent parent)
{
this.Parent = Parent;
_parent = parent;
}
public void Signal()
{
Parent.ReadableEvent.Signal();
_parent.ReadableEvent.Signal();
}
public KernelResult Clear()
{
return Parent.ReadableEvent.Clear();
return _parent.ReadableEvent.Clear();
}
}
}

View File

@ -4,28 +4,28 @@ namespace Ryujinx.HLE.HOS.Kernel
{
static class KernelInit
{
public static void InitializeResourceLimit(KResourceLimit ResourceLimit)
public static void InitializeResourceLimit(KResourceLimit resourceLimit)
{
void EnsureSuccess(KernelResult Result)
void EnsureSuccess(KernelResult result)
{
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
throw new InvalidOperationException($"Unexpected result \"{Result}\".");
throw new InvalidOperationException($"Unexpected result \"{result}\".");
}
}
int KernelMemoryCfg = 0;
int kernelMemoryCfg = 0;
long RamSize = GetRamSize(KernelMemoryCfg);
long ramSize = GetRamSize(kernelMemoryCfg);
EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Memory, RamSize));
EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Thread, 800));
EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Event, 700));
EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.TransferMemory, 200));
EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Session, 900));
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Memory, ramSize));
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Thread, 800));
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Event, 700));
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.TransferMemory, 200));
EnsureSuccess(resourceLimit.SetLimitValue(LimitableResource.Session, 900));
if (!ResourceLimit.Reserve(LimitableResource.Memory, 0) ||
!ResourceLimit.Reserve(LimitableResource.Memory, 0x60000))
if (!resourceLimit.Reserve(LimitableResource.Memory, 0) ||
!resourceLimit.Reserve(LimitableResource.Memory, 0x60000))
{
throw new InvalidOperationException("Unexpected failure reserving memory on resource limit.");
}
@ -33,99 +33,99 @@ namespace Ryujinx.HLE.HOS.Kernel
public static KMemoryRegionManager[] GetMemoryRegions()
{
KMemoryArrange Arrange = GetMemoryArrange();
KMemoryArrange arrange = GetMemoryArrange();
return new KMemoryRegionManager[]
{
GetMemoryRegion(Arrange.Application),
GetMemoryRegion(Arrange.Applet),
GetMemoryRegion(Arrange.Service),
GetMemoryRegion(Arrange.NvServices)
GetMemoryRegion(arrange.Application),
GetMemoryRegion(arrange.Applet),
GetMemoryRegion(arrange.Service),
GetMemoryRegion(arrange.NvServices)
};
}
private static KMemoryRegionManager GetMemoryRegion(KMemoryArrangeRegion Region)
private static KMemoryRegionManager GetMemoryRegion(KMemoryArrangeRegion region)
{
return new KMemoryRegionManager(Region.Address, Region.Size, Region.EndAddr);
return new KMemoryRegionManager(region.Address, region.Size, region.EndAddr);
}
private static KMemoryArrange GetMemoryArrange()
{
int McEmemCfg = 0x1000;
int mcEmemCfg = 0x1000;
ulong EmemApertureSize = (ulong)(McEmemCfg & 0x3fff) << 20;
ulong ememApertureSize = (ulong)(mcEmemCfg & 0x3fff) << 20;
int KernelMemoryCfg = 0;
int kernelMemoryCfg = 0;
ulong RamSize = (ulong)GetRamSize(KernelMemoryCfg);
ulong ramSize = (ulong)GetRamSize(kernelMemoryCfg);
ulong RamPart0;
ulong RamPart1;
ulong ramPart0;
ulong ramPart1;
if (RamSize * 2 > EmemApertureSize)
if (ramSize * 2 > ememApertureSize)
{
RamPart0 = EmemApertureSize / 2;
RamPart1 = EmemApertureSize / 2;
ramPart0 = ememApertureSize / 2;
ramPart1 = ememApertureSize / 2;
}
else
{
RamPart0 = EmemApertureSize;
RamPart1 = 0;
ramPart0 = ememApertureSize;
ramPart1 = 0;
}
int MemoryArrange = 1;
int memoryArrange = 1;
ulong ApplicationRgSize;
ulong applicationRgSize;
switch (MemoryArrange)
switch (memoryArrange)
{
case 2: ApplicationRgSize = 0x80000000; break;
case 2: applicationRgSize = 0x80000000; break;
case 0x11:
case 0x21: ApplicationRgSize = 0x133400000; break;
default: ApplicationRgSize = 0xcd500000; break;
case 0x21: applicationRgSize = 0x133400000; break;
default: applicationRgSize = 0xcd500000; break;
}
ulong AppletRgSize;
ulong appletRgSize;
switch (MemoryArrange)
switch (memoryArrange)
{
case 2: AppletRgSize = 0x61200000; break;
case 3: AppletRgSize = 0x1c000000; break;
case 0x11: AppletRgSize = 0x23200000; break;
case 2: appletRgSize = 0x61200000; break;
case 3: appletRgSize = 0x1c000000; break;
case 0x11: appletRgSize = 0x23200000; break;
case 0x12:
case 0x21: AppletRgSize = 0x89100000; break;
default: AppletRgSize = 0x1fb00000; break;
case 0x21: appletRgSize = 0x89100000; break;
default: appletRgSize = 0x1fb00000; break;
}
KMemoryArrangeRegion ServiceRg;
KMemoryArrangeRegion NvServicesRg;
KMemoryArrangeRegion AppletRg;
KMemoryArrangeRegion ApplicationRg;
KMemoryArrangeRegion serviceRg;
KMemoryArrangeRegion nvServicesRg;
KMemoryArrangeRegion appletRg;
KMemoryArrangeRegion applicationRg;
const ulong NvServicesRgSize = 0x29ba000;
const ulong nvServicesRgSize = 0x29ba000;
ulong ApplicationRgEnd = DramMemoryMap.DramEnd; //- RamPart0;
ulong applicationRgEnd = DramMemoryMap.DramEnd; //- RamPart0;
ApplicationRg = new KMemoryArrangeRegion(ApplicationRgEnd - ApplicationRgSize, ApplicationRgSize);
applicationRg = new KMemoryArrangeRegion(applicationRgEnd - applicationRgSize, applicationRgSize);
ulong NvServicesRgEnd = ApplicationRg.Address - AppletRgSize;
ulong nvServicesRgEnd = applicationRg.Address - appletRgSize;
NvServicesRg = new KMemoryArrangeRegion(NvServicesRgEnd - NvServicesRgSize, NvServicesRgSize);
AppletRg = new KMemoryArrangeRegion(NvServicesRgEnd, AppletRgSize);
nvServicesRg = new KMemoryArrangeRegion(nvServicesRgEnd - nvServicesRgSize, nvServicesRgSize);
appletRg = new KMemoryArrangeRegion(nvServicesRgEnd, appletRgSize);
//Note: There is an extra region used by the kernel, however
//since we are doing HLE we are not going to use that memory, so give all
//the remaining memory space to services.
ulong ServiceRgSize = NvServicesRg.Address - DramMemoryMap.SlabHeapEnd;
ulong serviceRgSize = nvServicesRg.Address - DramMemoryMap.SlabHeapEnd;
ServiceRg = new KMemoryArrangeRegion(DramMemoryMap.SlabHeapEnd, ServiceRgSize);
serviceRg = new KMemoryArrangeRegion(DramMemoryMap.SlabHeapEnd, serviceRgSize);
return new KMemoryArrange(ServiceRg, NvServicesRg, AppletRg, ApplicationRg);
return new KMemoryArrange(serviceRg, nvServicesRg, appletRg, applicationRg);
}
private static long GetRamSize(int KernelMemoryCfg)
private static long GetRamSize(int kernelMemoryCfg)
{
switch ((KernelMemoryCfg >> 16) & 3)
switch ((kernelMemoryCfg >> 16) & 3)
{
case 1: return 0x180000000;
case 2: return 0x200000000;

View File

@ -4,48 +4,48 @@ namespace Ryujinx.HLE.HOS.Kernel
{
static class KernelTransfer
{
public static bool UserToKernelInt32(Horizon System, long Address, out int Value)
public static bool UserToKernelInt32(Horizon system, long address, out int value)
{
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = system.Scheduler.GetCurrentProcess();
if (CurrentProcess.CpuMemory.IsMapped(Address) &&
CurrentProcess.CpuMemory.IsMapped(Address + 3))
if (currentProcess.CpuMemory.IsMapped(address) &&
currentProcess.CpuMemory.IsMapped(address + 3))
{
Value = CurrentProcess.CpuMemory.ReadInt32(Address);
value = currentProcess.CpuMemory.ReadInt32(address);
return true;
}
Value = 0;
value = 0;
return false;
}
public static bool UserToKernelString(Horizon System, long Address, int Size, out string Value)
public static bool UserToKernelString(Horizon system, long address, int size, out string value)
{
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = system.Scheduler.GetCurrentProcess();
if (CurrentProcess.CpuMemory.IsMapped(Address) &&
CurrentProcess.CpuMemory.IsMapped(Address + Size - 1))
if (currentProcess.CpuMemory.IsMapped(address) &&
currentProcess.CpuMemory.IsMapped(address + size - 1))
{
Value = MemoryHelper.ReadAsciiString(CurrentProcess.CpuMemory, Address, Size);
value = MemoryHelper.ReadAsciiString(currentProcess.CpuMemory, address, size);
return true;
}
Value = null;
value = null;
return false;
}
public static bool KernelToUserInt32(Horizon System, long Address, int Value)
public static bool KernelToUserInt32(Horizon system, long address, int value)
{
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = system.Scheduler.GetCurrentProcess();
if (CurrentProcess.CpuMemory.IsMapped(Address) &&
CurrentProcess.CpuMemory.IsMapped(Address + 3))
if (currentProcess.CpuMemory.IsMapped(address) &&
currentProcess.CpuMemory.IsMapped(address + 3))
{
CurrentProcess.CpuMemory.WriteInt32ToSharedAddr(Address, Value);
currentProcess.CpuMemory.WriteInt32ToSharedAddr(address, value);
return true;
}
@ -53,14 +53,14 @@ namespace Ryujinx.HLE.HOS.Kernel
return false;
}
public static bool KernelToUserInt64(Horizon System, long Address, long Value)
public static bool KernelToUserInt64(Horizon system, long address, long value)
{
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = system.Scheduler.GetCurrentProcess();
if (CurrentProcess.CpuMemory.IsMapped(Address) &&
CurrentProcess.CpuMemory.IsMapped(Address + 7))
if (currentProcess.CpuMemory.IsMapped(address) &&
currentProcess.CpuMemory.IsMapped(address + 7))
{
CurrentProcess.CpuMemory.WriteInt64(Address, Value);
currentProcess.CpuMemory.WriteInt64(address, value);
return true;
}

View File

@ -4,125 +4,125 @@ namespace Ryujinx.HLE.HOS.Kernel
{
class MersenneTwister
{
private int Index;
private uint[] Mt;
private int _index;
private uint[] _mt;
public MersenneTwister(uint Seed)
public MersenneTwister(uint seed)
{
Mt = new uint[624];
_mt = new uint[624];
Mt[0] = Seed;
_mt[0] = seed;
for (int MtIdx = 1; MtIdx < Mt.Length; MtIdx++)
for (int mtIdx = 1; mtIdx < _mt.Length; mtIdx++)
{
uint Prev = Mt[MtIdx - 1];
uint prev = _mt[mtIdx - 1];
Mt[MtIdx] = (uint)(0x6c078965 * (Prev ^ (Prev >> 30)) + MtIdx);
_mt[mtIdx] = (uint)(0x6c078965 * (prev ^ (prev >> 30)) + mtIdx);
}
Index = Mt.Length;
_index = _mt.Length;
}
public long GenRandomNumber(long Min, long Max)
public long GenRandomNumber(long min, long max)
{
long Range = Max - Min;
long range = max - min;
if (Min == Max)
if (min == max)
{
return Min;
return min;
}
if (Range == -1)
if (range == -1)
{
//Increment would cause a overflow, special case.
return GenRandomNumber(2, 2, 32, 0xffffffffu, 0xffffffffu);
}
Range++;
range++;
//This is log2(Range) plus one.
int NextRangeLog2 = 64 - BitUtils.CountLeadingZeros64(Range);
int nextRangeLog2 = 64 - BitUtils.CountLeadingZeros64(range);
//If Range is already power of 2, subtract one to use log2(Range) directly.
int RangeLog2 = NextRangeLog2 - (BitUtils.IsPowerOfTwo64(Range) ? 1 : 0);
int rangeLog2 = nextRangeLog2 - (BitUtils.IsPowerOfTwo64(range) ? 1 : 0);
int Parts = RangeLog2 > 32 ? 2 : 1;
int BitsPerPart = RangeLog2 / Parts;
int parts = rangeLog2 > 32 ? 2 : 1;
int bitsPerPart = rangeLog2 / parts;
int FullParts = Parts - (RangeLog2 - Parts * BitsPerPart);
int fullParts = parts - (rangeLog2 - parts * bitsPerPart);
uint Mask = 0xffffffffu >> (32 - BitsPerPart);
uint MaskPlus1 = 0xffffffffu >> (31 - BitsPerPart);
uint mask = 0xffffffffu >> (32 - bitsPerPart);
uint maskPlus1 = 0xffffffffu >> (31 - bitsPerPart);
long RandomNumber;
long randomNumber;
do
{
RandomNumber = GenRandomNumber(Parts, FullParts, BitsPerPart, Mask, MaskPlus1);
randomNumber = GenRandomNumber(parts, fullParts, bitsPerPart, mask, maskPlus1);
}
while ((ulong)RandomNumber >= (ulong)Range);
while ((ulong)randomNumber >= (ulong)range);
return Min + RandomNumber;
return min + randomNumber;
}
private long GenRandomNumber(
int Parts,
int FullParts,
int BitsPerPart,
uint Mask,
uint MaskPlus1)
int parts,
int fullParts,
int bitsPerPart,
uint mask,
uint maskPlus1)
{
long RandomNumber = 0;
long randomNumber = 0;
int Part = 0;
int part = 0;
for (; Part < FullParts; Part++)
for (; part < fullParts; part++)
{
RandomNumber <<= BitsPerPart;
RandomNumber |= GenRandomNumber() & Mask;
randomNumber <<= bitsPerPart;
randomNumber |= GenRandomNumber() & mask;
}
for (; Part < Parts; Part++)
for (; part < parts; part++)
{
RandomNumber <<= BitsPerPart + 1;
RandomNumber |= GenRandomNumber() & MaskPlus1;
randomNumber <<= bitsPerPart + 1;
randomNumber |= GenRandomNumber() & maskPlus1;
}
return RandomNumber;
return randomNumber;
}
private uint GenRandomNumber()
{
if (Index >= Mt.Length)
if (_index >= _mt.Length)
{
Twist();
}
uint Value = Mt[Index++];
uint value = _mt[_index++];
Value ^= Value >> 11;
Value ^= (Value << 7) & 0x9d2c5680;
Value ^= (Value << 15) & 0xefc60000;
Value ^= Value >> 18;
value ^= value >> 11;
value ^= (value << 7) & 0x9d2c5680;
value ^= (value << 15) & 0xefc60000;
value ^= value >> 18;
return Value;
return value;
}
private void Twist()
{
for (int MtIdx = 0; MtIdx < Mt.Length; MtIdx++)
for (int mtIdx = 0; mtIdx < _mt.Length; mtIdx++)
{
uint Value = (Mt[MtIdx] & 0x80000000) + (Mt[(MtIdx + 1) % Mt.Length] & 0x7fffffff);
uint value = (_mt[mtIdx] & 0x80000000) + (_mt[(mtIdx + 1) % _mt.Length] & 0x7fffffff);
Mt[MtIdx] = Mt[(MtIdx + 397) % Mt.Length] ^ (Value >> 1);
_mt[mtIdx] = _mt[(mtIdx + 397) % _mt.Length] ^ (value >> 1);
if ((Value & 1) != 0)
if ((value & 1) != 0)
{
Mt[MtIdx] ^= 0x9908b0df;
_mt[mtIdx] ^= 0x9908b0df;
}
}
Index = 0;
_index = 0;
}
}
}

View File

@ -2,36 +2,36 @@ namespace Ryujinx.HLE.HOS.Kernel
{
struct ProcessCreationInfo
{
public string Name { get; private set; }
public string Name { get; }
public int Category { get; private set; }
public long TitleId { get; private set; }
public int Category { get; }
public long TitleId { get; }
public ulong CodeAddress { get; private set; }
public int CodePagesCount { get; private set; }
public ulong CodeAddress { get; }
public int CodePagesCount { get; }
public int MmuFlags { get; private set; }
public int ResourceLimitHandle { get; private set; }
public int PersonalMmHeapPagesCount { get; private set; }
public int MmuFlags { get; }
public int ResourceLimitHandle { get; }
public int PersonalMmHeapPagesCount { get; }
public ProcessCreationInfo(
string Name,
int Category,
long TitleId,
ulong CodeAddress,
int CodePagesCount,
int MmuFlags,
int ResourceLimitHandle,
int PersonalMmHeapPagesCount)
string name,
int category,
long titleId,
ulong codeAddress,
int codePagesCount,
int mmuFlags,
int resourceLimitHandle,
int personalMmHeapPagesCount)
{
this.Name = Name;
this.Category = Category;
this.TitleId = TitleId;
this.CodeAddress = CodeAddress;
this.CodePagesCount = CodePagesCount;
this.MmuFlags = MmuFlags;
this.ResourceLimitHandle = ResourceLimitHandle;
this.PersonalMmHeapPagesCount = PersonalMmHeapPagesCount;
Name = name;
Category = category;
TitleId = titleId;
CodeAddress = codeAddress;
CodePagesCount = codePagesCount;
MmuFlags = mmuFlags;
ResourceLimitHandle = resourceLimitHandle;
PersonalMmHeapPagesCount = personalMmHeapPagesCount;
}
}
}

View File

@ -10,38 +10,38 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
private delegate void SvcFunc(CpuThreadState ThreadState);
private delegate void SvcFunc(CpuThreadState threadState);
private Dictionary<int, SvcFunc> SvcFuncs;
private Dictionary<int, SvcFunc> _svcFuncs;
private Switch Device;
private KProcess Process;
private Horizon System;
private MemoryManager Memory;
private Switch _device;
private KProcess _process;
private Horizon _system;
private MemoryManager _memory;
private struct HleIpcMessage
{
public KThread Thread { get; private set; }
public KSession Session { get; private set; }
public IpcMessage Message { get; private set; }
public long MessagePtr { get; private set; }
public KThread Thread { get; }
public KSession Session { get; }
public IpcMessage Message { get; }
public long MessagePtr { get; }
public HleIpcMessage(
KThread Thread,
KSession Session,
IpcMessage Message,
long MessagePtr)
KThread thread,
KSession session,
IpcMessage message,
long messagePtr)
{
this.Thread = Thread;
this.Session = Session;
this.Message = Message;
this.MessagePtr = MessagePtr;
Thread = thread;
Session = session;
Message = message;
MessagePtr = messagePtr;
}
}
public SvcHandler(Switch Device, KProcess Process)
public SvcHandler(Switch device, KProcess process)
{
SvcFuncs = new Dictionary<int, SvcFunc>()
_svcFuncs = new Dictionary<int, SvcFunc>
{
{ 0x01, SvcSetHeapSize },
{ 0x03, SvcSetMemoryAttribute },
@ -93,23 +93,23 @@ namespace Ryujinx.HLE.HOS.Kernel
{ 0x71, ManageNamedPort64 }
};
this.Device = Device;
this.Process = Process;
this.System = Device.System;
this.Memory = Process.CpuMemory;
_device = device;
_process = process;
_system = device.System;
_memory = process.CpuMemory;
}
public void SvcCall(object sender, InstExceptionEventArgs e)
{
CpuThreadState ThreadState = (CpuThreadState)sender;
CpuThreadState threadState = (CpuThreadState)sender;
if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func))
if (_svcFuncs.TryGetValue(e.Id, out SvcFunc func))
{
Logger.PrintDebug(LogClass.KernelSvc, $"{Func.Method.Name} called.");
Logger.PrintDebug(LogClass.KernelSvc, $"{func.Method.Name} called.");
Func(ThreadState);
func(threadState);
Logger.PrintDebug(LogClass.KernelSvc, $"{Func.Method.Name} ended.");
Logger.PrintDebug(LogClass.KernelSvc, $"{func.Method.Name} ended.");
}
else
{

View File

@ -7,575 +7,575 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
private void SvcSetHeapSize(CpuThreadState ThreadState)
private void SvcSetHeapSize(CpuThreadState threadState)
{
ulong Size = ThreadState.X1;
ulong size = threadState.X1;
if ((Size & 0xfffffffe001fffff) != 0)
if ((size & 0xfffffffe001fffff) != 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Heap size 0x{Size:x16} is not aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Heap size 0x{size:x16} is not aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
KernelResult Result = Process.MemoryManager.SetHeapSize(Size, out ulong Position);
KernelResult result = _process.MemoryManager.SetHeapSize(size, out ulong position);
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
if (Result == KernelResult.Success)
if (result == KernelResult.Success)
{
ThreadState.X1 = Position;
threadState.X1 = position;
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\".");
}
}
private void SvcSetMemoryAttribute(CpuThreadState ThreadState)
private void SvcSetMemoryAttribute(CpuThreadState threadState)
{
ulong Position = ThreadState.X0;
ulong Size = ThreadState.X1;
ulong position = threadState.X0;
ulong size = threadState.X1;
if (!PageAligned(Position))
if (!PageAligned(position))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{position:x16} is not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
MemoryAttribute AttributeMask = (MemoryAttribute)ThreadState.X2;
MemoryAttribute AttributeValue = (MemoryAttribute)ThreadState.X3;
MemoryAttribute attributeMask = (MemoryAttribute)threadState.X2;
MemoryAttribute attributeValue = (MemoryAttribute)threadState.X3;
MemoryAttribute Attributes = AttributeMask | AttributeValue;
MemoryAttribute attributes = attributeMask | attributeValue;
if (Attributes != AttributeMask ||
(Attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached)
if (attributes != attributeMask ||
(attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached)
{
Logger.PrintWarning(LogClass.KernelSvc, "Invalid memory attributes!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue);
return;
}
KernelResult Result = Process.MemoryManager.SetMemoryAttribute(
Position,
Size,
AttributeMask,
AttributeValue);
KernelResult result = _process.MemoryManager.SetMemoryAttribute(
position,
size,
attributeMask,
attributeValue);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\".");
}
else
{
Memory.StopObservingRegion((long)Position, (long)Size);
_memory.StopObservingRegion((long)position, (long)size);
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcMapMemory(CpuThreadState ThreadState)
private void SvcMapMemory(CpuThreadState threadState)
{
ulong Dst = ThreadState.X0;
ulong Src = ThreadState.X1;
ulong Size = ThreadState.X2;
ulong dst = threadState.X0;
ulong src = threadState.X1;
ulong size = threadState.X2;
if (!PageAligned(Src | Dst))
if (!PageAligned(src | dst))
{
Logger.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
if (Src + Size <= Src || Dst + Size <= Dst)
if (src + size <= src || dst + size <= dst)
{
Logger.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if (!CurrentProcess.MemoryManager.InsideAddrSpace(Src, Size))
if (!currentProcess.MemoryManager.InsideAddrSpace(src, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Src address 0x{Src:x16} out of range!");
Logger.PrintWarning(LogClass.KernelSvc, $"Src address 0x{src:x16} out of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (CurrentProcess.MemoryManager.OutsideStackRegion(Dst, Size) ||
CurrentProcess.MemoryManager.InsideHeapRegion (Dst, Size) ||
CurrentProcess.MemoryManager.InsideAliasRegion (Dst, Size))
if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) ||
currentProcess.MemoryManager.InsideHeapRegion (dst, size) ||
currentProcess.MemoryManager.InsideAliasRegion (dst, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{Dst:x16} out of range!");
Logger.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{dst:x16} out of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
return;
}
KernelResult Result = Process.MemoryManager.Map(Dst, Src, Size);
KernelResult result = _process.MemoryManager.Map(dst, src, size);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcUnmapMemory(CpuThreadState ThreadState)
private void SvcUnmapMemory(CpuThreadState threadState)
{
ulong Dst = ThreadState.X0;
ulong Src = ThreadState.X1;
ulong Size = ThreadState.X2;
ulong dst = threadState.X0;
ulong src = threadState.X1;
ulong size = threadState.X2;
if (!PageAligned(Src | Dst))
if (!PageAligned(src | dst))
{
Logger.PrintWarning(LogClass.KernelSvc, "Addresses are not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
if (Src + Size <= Src || Dst + Size <= Dst)
if (src + size <= src || dst + size <= dst)
{
Logger.PrintWarning(LogClass.KernelSvc, "Addresses outside of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if (!CurrentProcess.MemoryManager.InsideAddrSpace(Src, Size))
if (!currentProcess.MemoryManager.InsideAddrSpace(src, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Src address 0x{Src:x16} out of range!");
Logger.PrintWarning(LogClass.KernelSvc, $"Src address 0x{src:x16} out of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (CurrentProcess.MemoryManager.OutsideStackRegion(Dst, Size) ||
CurrentProcess.MemoryManager.InsideHeapRegion (Dst, Size) ||
CurrentProcess.MemoryManager.InsideAliasRegion (Dst, Size))
if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) ||
currentProcess.MemoryManager.InsideHeapRegion (dst, size) ||
currentProcess.MemoryManager.InsideAliasRegion (dst, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{Dst:x16} out of range!");
Logger.PrintWarning(LogClass.KernelSvc, $"Dst address 0x{dst:x16} out of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
return;
}
KernelResult Result = Process.MemoryManager.Unmap(Dst, Src, Size);
KernelResult result = _process.MemoryManager.Unmap(dst, src, size);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcQueryMemory(CpuThreadState ThreadState)
private void SvcQueryMemory(CpuThreadState threadState)
{
long InfoPtr = (long)ThreadState.X0;
ulong Position = ThreadState.X2;
long infoPtr = (long)threadState.X0;
ulong position = threadState.X2;
KMemoryInfo BlkInfo = Process.MemoryManager.QueryMemory(Position);
KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position);
Memory.WriteUInt64(InfoPtr + 0x00, BlkInfo.Address);
Memory.WriteUInt64(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);
_memory.WriteUInt64(infoPtr + 0x00, blkInfo.Address);
_memory.WriteUInt64(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;
threadState.X0 = 0;
threadState.X1 = 0;
}
private void SvcMapSharedMemory(CpuThreadState ThreadState)
private void SvcMapSharedMemory(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X0;
ulong Address = ThreadState.X1;
ulong Size = ThreadState.X2;
int handle = (int)threadState.X0;
ulong address = threadState.X1;
ulong size = threadState.X2;
if (!PageAligned(Address))
if (!PageAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} is not page aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
if (Address + Size <= Address)
if (address + size <= address)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
MemoryPermission Permission = (MemoryPermission)ThreadState.X3;
MemoryPermission permission = (MemoryPermission)threadState.X3;
if ((Permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite)
if ((permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {permission}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
KSharedMemory SharedMemory = CurrentProcess.HandleTable.GetObject<KSharedMemory>(Handle);
KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject<KSharedMemory>(handle);
if (SharedMemory == null)
if (sharedMemory == null)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (CurrentProcess.MemoryManager.IsInvalidRegion (Address, Size) ||
CurrentProcess.MemoryManager.InsideHeapRegion (Address, Size) ||
CurrentProcess.MemoryManager.InsideAliasRegion(Address, Size))
if (currentProcess.MemoryManager.IsInvalidRegion (address, size) ||
currentProcess.MemoryManager.InsideHeapRegion (address, size) ||
currentProcess.MemoryManager.InsideAliasRegion(address, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} out of range!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} out of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KernelResult Result = SharedMemory.MapIntoProcess(
CurrentProcess.MemoryManager,
Address,
Size,
CurrentProcess,
Permission);
KernelResult result = sharedMemory.MapIntoProcess(
currentProcess.MemoryManager,
address,
size,
currentProcess,
permission);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\".");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcUnmapSharedMemory(CpuThreadState ThreadState)
private void SvcUnmapSharedMemory(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X0;
ulong Address = ThreadState.X1;
ulong Size = ThreadState.X2;
int handle = (int)threadState.X0;
ulong address = threadState.X1;
ulong size = threadState.X2;
if (!PageAligned(Address))
if (!PageAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} is not page aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
if (Address + Size <= Address)
if (address + size <= address)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
KSharedMemory SharedMemory = CurrentProcess.HandleTable.GetObject<KSharedMemory>(Handle);
KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject<KSharedMemory>(handle);
if (SharedMemory == null)
if (sharedMemory == null)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid shared memory handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (CurrentProcess.MemoryManager.IsInvalidRegion (Address, Size) ||
CurrentProcess.MemoryManager.InsideHeapRegion (Address, Size) ||
CurrentProcess.MemoryManager.InsideAliasRegion(Address, Size))
if (currentProcess.MemoryManager.IsInvalidRegion (address, size) ||
currentProcess.MemoryManager.InsideHeapRegion (address, size) ||
currentProcess.MemoryManager.InsideAliasRegion(address, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} out of range!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} out of range!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KernelResult Result = SharedMemory.UnmapFromProcess(
CurrentProcess.MemoryManager,
Address,
Size,
CurrentProcess);
KernelResult result = sharedMemory.UnmapFromProcess(
currentProcess.MemoryManager,
address,
size,
currentProcess);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\".");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcCreateTransferMemory(CpuThreadState ThreadState)
private void SvcCreateTransferMemory(CpuThreadState threadState)
{
ulong Address = ThreadState.X1;
ulong Size = ThreadState.X2;
ulong address = threadState.X1;
ulong size = threadState.X2;
if (!PageAligned(Address))
if (!PageAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} is not page aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (Address + Size <= Address)
if (address + size <= address)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
MemoryPermission Permission = (MemoryPermission)ThreadState.X3;
MemoryPermission permission = (MemoryPermission)threadState.X3;
if (Permission > MemoryPermission.ReadAndWrite || Permission == MemoryPermission.Write)
if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {permission}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);
return;
}
Process.MemoryManager.ReserveTransferMemory(Address, Size, Permission);
_process.MemoryManager.ReserveTransferMemory(address, size, permission);
KTransferMemory TransferMemory = new KTransferMemory(Address, Size);
KTransferMemory transferMemory = new KTransferMemory(address, size);
KernelResult Result = Process.HandleTable.GenerateHandle(TransferMemory, out int Handle);
KernelResult result = _process.HandleTable.GenerateHandle(transferMemory, out int handle);
ThreadState.X0 = (uint)Result;
ThreadState.X1 = (ulong)Handle;
threadState.X0 = (uint)result;
threadState.X1 = (ulong)handle;
}
private void SvcMapPhysicalMemory(CpuThreadState ThreadState)
private void SvcMapPhysicalMemory(CpuThreadState threadState)
{
ulong Address = ThreadState.X0;
ulong Size = ThreadState.X1;
ulong address = threadState.X0;
ulong size = threadState.X1;
if (!PageAligned(Address))
if (!PageAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} is not page aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
if (Address + Size <= Address)
if (address + size <= address)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if ((CurrentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0)
if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"System resource size is zero.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
return;
}
if (!CurrentProcess.MemoryManager.InsideAddrSpace (Address, Size) ||
CurrentProcess.MemoryManager.OutsideAliasRegion(Address, Size))
if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) ||
currentProcess.MemoryManager.OutsideAliasRegion(address, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address {Address:x16}.");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address {address:x16}.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KernelResult Result = Process.MemoryManager.MapPhysicalMemory(Address, Size);
KernelResult result = _process.MemoryManager.MapPhysicalMemory(address, size);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcUnmapPhysicalMemory(CpuThreadState ThreadState)
private void SvcUnmapPhysicalMemory(CpuThreadState threadState)
{
ulong Address = ThreadState.X0;
ulong Size = ThreadState.X1;
ulong address = threadState.X0;
ulong size = threadState.X1;
if (!PageAligned(Address))
if (!PageAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Address:x16} is not page aligned!");
Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
if (!PageAligned(Size) || Size == 0)
if (!PageAligned(size) || size == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");
Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidSize);
return;
}
if (Address + Size <= Address)
if (address + size <= address)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Address:x16} / size 0x{Size:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if ((CurrentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0)
if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"System resource size is zero.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
return;
}
if (!CurrentProcess.MemoryManager.InsideAddrSpace (Address, Size) ||
CurrentProcess.MemoryManager.OutsideAliasRegion(Address, Size))
if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) ||
currentProcess.MemoryManager.OutsideAliasRegion(address, size))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address {Address:x16}.");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address {address:x16}.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
KernelResult Result = Process.MemoryManager.UnmapPhysicalMemory(Address, Size);
KernelResult result = _process.MemoryManager.UnmapPhysicalMemory(address, size);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private static bool PageAligned(ulong Position)
private static bool PageAligned(ulong position)
{
return (Position & (KMemoryManager.PageSize - 1)) == 0;
return (position & (KMemoryManager.PageSize - 1)) == 0;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,458 +7,458 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
private void CreateThread64(CpuThreadState ThreadState)
private void CreateThread64(CpuThreadState threadState)
{
ulong Entrypoint = ThreadState.X1;
ulong ArgsPtr = ThreadState.X2;
ulong StackTop = ThreadState.X3;
int Priority = (int)ThreadState.X4;
int CpuCore = (int)ThreadState.X5;
ulong entrypoint = threadState.X1;
ulong argsPtr = threadState.X2;
ulong stackTop = threadState.X3;
int priority = (int)threadState.X4;
int cpuCore = (int)threadState.X5;
KernelResult Result = CreateThread(Entrypoint, ArgsPtr, StackTop, Priority, CpuCore, out int Handle);
KernelResult result = CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out int handle);
ThreadState.X0 = (ulong)Result;
ThreadState.X1 = (ulong)Handle;
threadState.X0 = (ulong)result;
threadState.X1 = (ulong)handle;
}
private KernelResult CreateThread(
ulong Entrypoint,
ulong ArgsPtr,
ulong StackTop,
int Priority,
int CpuCore,
out int Handle)
ulong entrypoint,
ulong argsPtr,
ulong stackTop,
int priority,
int cpuCore,
out int handle)
{
Handle = 0;
handle = 0;
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if (CpuCore == -2)
if (cpuCore == -2)
{
CpuCore = CurrentProcess.DefaultCpuCore;
cpuCore = currentProcess.DefaultCpuCore;
}
if ((uint)CpuCore >= KScheduler.CpuCoresCount || !CurrentProcess.IsCpuCoreAllowed(CpuCore))
if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore))
{
return KernelResult.InvalidCpuCore;
}
if ((uint)Priority >= KScheduler.PrioritiesCount || !CurrentProcess.IsPriorityAllowed(Priority))
if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority))
{
return KernelResult.InvalidPriority;
}
long Timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100);
long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100);
if (CurrentProcess.ResourceLimit != null &&
!CurrentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, Timeout))
if (currentProcess.ResourceLimit != null &&
!currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout))
{
return KernelResult.ResLimitExceeded;
}
KThread Thread = new KThread(System);
KThread thread = new KThread(_system);
KernelResult Result = CurrentProcess.InitializeThread(
Thread,
Entrypoint,
ArgsPtr,
StackTop,
Priority,
CpuCore);
KernelResult result = currentProcess.InitializeThread(
thread,
entrypoint,
argsPtr,
stackTop,
priority,
cpuCore);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
return Result;
return result;
}
Result = Process.HandleTable.GenerateHandle(Thread, out Handle);
result = _process.HandleTable.GenerateHandle(thread, out handle);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Thread.Terminate();
thread.Terminate();
CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
}
return Result;
return result;
}
private void SvcStartThread(CpuThreadState ThreadState)
private void SvcStartThread(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X0;
int handle = (int)threadState.X0;
KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
KThread thread = _process.HandleTable.GetObject<KThread>(handle);
if (Thread != null)
if (thread != null)
{
KernelResult Result = Thread.Start();
KernelResult result = thread.Start();
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\".");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
}
}
private void SvcExitThread(CpuThreadState ThreadState)
private void SvcExitThread(CpuThreadState threadState)
{
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
System.Scheduler.ExitThread(CurrentThread);
_system.Scheduler.ExitThread(currentThread);
CurrentThread.Exit();
currentThread.Exit();
}
private void SvcSleepThread(CpuThreadState ThreadState)
private void SvcSleepThread(CpuThreadState threadState)
{
long Timeout = (long)ThreadState.X0;
long timeout = (long)threadState.X0;
Logger.PrintDebug(LogClass.KernelSvc, "Timeout = 0x" + Timeout.ToString("x16"));
Logger.PrintDebug(LogClass.KernelSvc, "Timeout = 0x" + timeout.ToString("x16"));
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KThread currentThread = _system.Scheduler.GetCurrentThread();
if (Timeout < 1)
if (timeout < 1)
{
switch (Timeout)
switch (timeout)
{
case 0: CurrentThread.Yield(); break;
case -1: CurrentThread.YieldWithLoadBalancing(); break;
case -2: CurrentThread.YieldAndWaitForLoadBalancing(); break;
case 0: currentThread.Yield(); break;
case -1: currentThread.YieldWithLoadBalancing(); break;
case -2: currentThread.YieldAndWaitForLoadBalancing(); break;
}
}
else
{
CurrentThread.Sleep(Timeout);
currentThread.Sleep(timeout);
ThreadState.X0 = 0;
threadState.X0 = 0;
}
}
private void SvcGetThreadPriority(CpuThreadState ThreadState)
private void SvcGetThreadPriority(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X1;
int handle = (int)threadState.X1;
KThread Thread = Process.HandleTable.GetKThread(Handle);
KThread thread = _process.HandleTable.GetKThread(handle);
if (Thread != null)
if (thread != null)
{
ThreadState.X0 = 0;
ThreadState.X1 = (ulong)Thread.DynamicPriority;
threadState.X0 = 0;
threadState.X1 = (ulong)thread.DynamicPriority;
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
}
}
private void SvcSetThreadPriority(CpuThreadState ThreadState)
private void SvcSetThreadPriority(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X0;
int Priority = (int)ThreadState.X1;
int handle = (int)threadState.X0;
int priority = (int)threadState.X1;
Logger.PrintDebug(LogClass.KernelSvc,
"Handle = 0x" + Handle .ToString("x8") + ", " +
"Priority = 0x" + Priority.ToString("x8"));
"Handle = 0x" + handle .ToString("x8") + ", " +
"Priority = 0x" + priority.ToString("x8"));
//TODO: NPDM check.
KThread Thread = Process.HandleTable.GetKThread(Handle);
KThread thread = _process.HandleTable.GetKThread(handle);
if (Thread == null)
if (thread == null)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
Thread.SetPriority(Priority);
thread.SetPriority(priority);
ThreadState.X0 = 0;
threadState.X0 = 0;
}
private void SvcGetThreadCoreMask(CpuThreadState ThreadState)
private void SvcGetThreadCoreMask(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X2;
int handle = (int)threadState.X2;
Logger.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + Handle.ToString("x8"));
Logger.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + handle.ToString("x8"));
KThread Thread = Process.HandleTable.GetKThread(Handle);
KThread thread = _process.HandleTable.GetKThread(handle);
if (Thread != null)
if (thread != null)
{
ThreadState.X0 = 0;
ThreadState.X1 = (ulong)Thread.PreferredCore;
ThreadState.X2 = (ulong)Thread.AffinityMask;
threadState.X0 = 0;
threadState.X1 = (ulong)thread.PreferredCore;
threadState.X2 = (ulong)thread.AffinityMask;
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
}
}
private void SetThreadCoreMask64(CpuThreadState ThreadState)
private void SetThreadCoreMask64(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X0;
int PreferredCore = (int)ThreadState.X1;
long AffinityMask = (long)ThreadState.X2;
int handle = (int)threadState.X0;
int preferredCore = (int)threadState.X1;
long affinityMask = (long)threadState.X2;
Logger.PrintDebug(LogClass.KernelSvc,
"Handle = 0x" + Handle .ToString("x8") + ", " +
"PreferredCore = 0x" + PreferredCore.ToString("x8") + ", " +
"AffinityMask = 0x" + AffinityMask .ToString("x16"));
"Handle = 0x" + handle .ToString("x8") + ", " +
"PreferredCore = 0x" + preferredCore.ToString("x8") + ", " +
"AffinityMask = 0x" + affinityMask .ToString("x16"));
KernelResult Result = SetThreadCoreMask(Handle, PreferredCore, AffinityMask);
KernelResult result = SetThreadCoreMask(handle, preferredCore, affinityMask);
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{result}\".");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private KernelResult SetThreadCoreMask(int Handle, int PreferredCore, long AffinityMask)
private KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask)
{
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
if (PreferredCore == -2)
if (preferredCore == -2)
{
PreferredCore = CurrentProcess.DefaultCpuCore;
preferredCore = currentProcess.DefaultCpuCore;
AffinityMask = 1 << PreferredCore;
affinityMask = 1 << preferredCore;
}
else
{
if ((CurrentProcess.Capabilities.AllowedCpuCoresMask | AffinityMask) !=
CurrentProcess.Capabilities.AllowedCpuCoresMask)
if ((currentProcess.Capabilities.AllowedCpuCoresMask | affinityMask) !=
currentProcess.Capabilities.AllowedCpuCoresMask)
{
return KernelResult.InvalidCpuCore;
}
if (AffinityMask == 0)
if (affinityMask == 0)
{
return KernelResult.InvalidCombination;
}
if ((uint)PreferredCore > 3)
if ((uint)preferredCore > 3)
{
if ((PreferredCore | 2) != -1)
if ((preferredCore | 2) != -1)
{
return KernelResult.InvalidCpuCore;
}
}
else if ((AffinityMask & (1 << PreferredCore)) == 0)
else if ((affinityMask & (1 << preferredCore)) == 0)
{
return KernelResult.InvalidCombination;
}
}
KThread Thread = Process.HandleTable.GetKThread(Handle);
KThread thread = _process.HandleTable.GetKThread(handle);
if (Thread == null)
if (thread == null)
{
return KernelResult.InvalidHandle;
}
return Thread.SetCoreAndAffinityMask(PreferredCore, AffinityMask);
return thread.SetCoreAndAffinityMask(preferredCore, affinityMask);
}
private void SvcGetCurrentProcessorNumber(CpuThreadState ThreadState)
private void SvcGetCurrentProcessorNumber(CpuThreadState threadState)
{
ThreadState.X0 = (ulong)System.Scheduler.GetCurrentThread().CurrentCore;
threadState.X0 = (ulong)_system.Scheduler.GetCurrentThread().CurrentCore;
}
private void SvcGetThreadId(CpuThreadState ThreadState)
private void SvcGetThreadId(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X1;
int handle = (int)threadState.X1;
KThread Thread = Process.HandleTable.GetKThread(Handle);
KThread thread = _process.HandleTable.GetKThread(handle);
if (Thread != null)
if (thread != null)
{
ThreadState.X0 = 0;
ThreadState.X1 = (ulong)Thread.ThreadUid;
threadState.X0 = 0;
threadState.X1 = (ulong)thread.ThreadUid;
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
}
}
private void SvcSetThreadActivity(CpuThreadState ThreadState)
private void SvcSetThreadActivity(CpuThreadState threadState)
{
int Handle = (int)ThreadState.X0;
bool Pause = (int)ThreadState.X1 == 1;
int handle = (int)threadState.X0;
bool pause = (int)threadState.X1 == 1;
KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
KThread thread = _process.HandleTable.GetObject<KThread>(handle);
if (Thread == null)
if (thread == null)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (Thread.Owner != System.Scheduler.GetCurrentProcess())
if (thread.Owner != _system.Scheduler.GetCurrentProcess())
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (Thread == System.Scheduler.GetCurrentThread())
if (thread == _system.Scheduler.GetCurrentThread())
{
Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted.");
ThreadState.X0 = (ulong)KernelResult.InvalidThread;
threadState.X0 = (ulong)KernelResult.InvalidThread;
return;
}
long Result = Thread.SetActivity(Pause);
long result = thread.SetActivity(pause);
if (Result != 0)
if (result != 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcGetThreadContext3(CpuThreadState ThreadState)
private void SvcGetThreadContext3(CpuThreadState threadState)
{
long Position = (long)ThreadState.X0;
int Handle = (int)ThreadState.X1;
long position = (long)threadState.X0;
int handle = (int)threadState.X1;
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KThread CurrentThread = System.Scheduler.GetCurrentThread();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
KThread currentThread = _system.Scheduler.GetCurrentThread();
KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
KThread thread = _process.HandleTable.GetObject<KThread>(handle);
if (Thread == null)
if (thread == null)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (Thread.Owner != CurrentProcess)
if (thread.Owner != currentProcess)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (CurrentThread == Thread)
if (currentThread == thread)
{
Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted.");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);
return;
}
Memory.WriteUInt64(Position + 0x0, Thread.Context.ThreadState.X0);
Memory.WriteUInt64(Position + 0x8, Thread.Context.ThreadState.X1);
Memory.WriteUInt64(Position + 0x10, Thread.Context.ThreadState.X2);
Memory.WriteUInt64(Position + 0x18, Thread.Context.ThreadState.X3);
Memory.WriteUInt64(Position + 0x20, Thread.Context.ThreadState.X4);
Memory.WriteUInt64(Position + 0x28, Thread.Context.ThreadState.X5);
Memory.WriteUInt64(Position + 0x30, Thread.Context.ThreadState.X6);
Memory.WriteUInt64(Position + 0x38, Thread.Context.ThreadState.X7);
Memory.WriteUInt64(Position + 0x40, Thread.Context.ThreadState.X8);
Memory.WriteUInt64(Position + 0x48, Thread.Context.ThreadState.X9);
Memory.WriteUInt64(Position + 0x50, Thread.Context.ThreadState.X10);
Memory.WriteUInt64(Position + 0x58, Thread.Context.ThreadState.X11);
Memory.WriteUInt64(Position + 0x60, Thread.Context.ThreadState.X12);
Memory.WriteUInt64(Position + 0x68, Thread.Context.ThreadState.X13);
Memory.WriteUInt64(Position + 0x70, Thread.Context.ThreadState.X14);
Memory.WriteUInt64(Position + 0x78, Thread.Context.ThreadState.X15);
Memory.WriteUInt64(Position + 0x80, Thread.Context.ThreadState.X16);
Memory.WriteUInt64(Position + 0x88, Thread.Context.ThreadState.X17);
Memory.WriteUInt64(Position + 0x90, Thread.Context.ThreadState.X18);
Memory.WriteUInt64(Position + 0x98, Thread.Context.ThreadState.X19);
Memory.WriteUInt64(Position + 0xa0, Thread.Context.ThreadState.X20);
Memory.WriteUInt64(Position + 0xa8, Thread.Context.ThreadState.X21);
Memory.WriteUInt64(Position + 0xb0, Thread.Context.ThreadState.X22);
Memory.WriteUInt64(Position + 0xb8, Thread.Context.ThreadState.X23);
Memory.WriteUInt64(Position + 0xc0, Thread.Context.ThreadState.X24);
Memory.WriteUInt64(Position + 0xc8, Thread.Context.ThreadState.X25);
Memory.WriteUInt64(Position + 0xd0, Thread.Context.ThreadState.X26);
Memory.WriteUInt64(Position + 0xd8, Thread.Context.ThreadState.X27);
Memory.WriteUInt64(Position + 0xe0, Thread.Context.ThreadState.X28);
Memory.WriteUInt64(Position + 0xe8, Thread.Context.ThreadState.X29);
Memory.WriteUInt64(Position + 0xf0, Thread.Context.ThreadState.X30);
Memory.WriteUInt64(Position + 0xf8, Thread.Context.ThreadState.X31);
_memory.WriteUInt64(position + 0x0, thread.Context.ThreadState.X0);
_memory.WriteUInt64(position + 0x8, thread.Context.ThreadState.X1);
_memory.WriteUInt64(position + 0x10, thread.Context.ThreadState.X2);
_memory.WriteUInt64(position + 0x18, thread.Context.ThreadState.X3);
_memory.WriteUInt64(position + 0x20, thread.Context.ThreadState.X4);
_memory.WriteUInt64(position + 0x28, thread.Context.ThreadState.X5);
_memory.WriteUInt64(position + 0x30, thread.Context.ThreadState.X6);
_memory.WriteUInt64(position + 0x38, thread.Context.ThreadState.X7);
_memory.WriteUInt64(position + 0x40, thread.Context.ThreadState.X8);
_memory.WriteUInt64(position + 0x48, thread.Context.ThreadState.X9);
_memory.WriteUInt64(position + 0x50, thread.Context.ThreadState.X10);
_memory.WriteUInt64(position + 0x58, thread.Context.ThreadState.X11);
_memory.WriteUInt64(position + 0x60, thread.Context.ThreadState.X12);
_memory.WriteUInt64(position + 0x68, thread.Context.ThreadState.X13);
_memory.WriteUInt64(position + 0x70, thread.Context.ThreadState.X14);
_memory.WriteUInt64(position + 0x78, thread.Context.ThreadState.X15);
_memory.WriteUInt64(position + 0x80, thread.Context.ThreadState.X16);
_memory.WriteUInt64(position + 0x88, thread.Context.ThreadState.X17);
_memory.WriteUInt64(position + 0x90, thread.Context.ThreadState.X18);
_memory.WriteUInt64(position + 0x98, thread.Context.ThreadState.X19);
_memory.WriteUInt64(position + 0xa0, thread.Context.ThreadState.X20);
_memory.WriteUInt64(position + 0xa8, thread.Context.ThreadState.X21);
_memory.WriteUInt64(position + 0xb0, thread.Context.ThreadState.X22);
_memory.WriteUInt64(position + 0xb8, thread.Context.ThreadState.X23);
_memory.WriteUInt64(position + 0xc0, thread.Context.ThreadState.X24);
_memory.WriteUInt64(position + 0xc8, thread.Context.ThreadState.X25);
_memory.WriteUInt64(position + 0xd0, thread.Context.ThreadState.X26);
_memory.WriteUInt64(position + 0xd8, thread.Context.ThreadState.X27);
_memory.WriteUInt64(position + 0xe0, thread.Context.ThreadState.X28);
_memory.WriteUInt64(position + 0xe8, thread.Context.ThreadState.X29);
_memory.WriteUInt64(position + 0xf0, thread.Context.ThreadState.X30);
_memory.WriteUInt64(position + 0xf8, thread.Context.ThreadState.X31);
Memory.WriteInt64(Position + 0x100, Thread.LastPc);
_memory.WriteInt64(position + 0x100, thread.LastPc);
Memory.WriteUInt64(Position + 0x108, (ulong)Thread.Context.ThreadState.Psr);
_memory.WriteUInt64(position + 0x108, (ulong)thread.Context.ThreadState.Psr);
Memory.WriteVector128(Position + 0x110, Thread.Context.ThreadState.V0);
Memory.WriteVector128(Position + 0x120, Thread.Context.ThreadState.V1);
Memory.WriteVector128(Position + 0x130, Thread.Context.ThreadState.V2);
Memory.WriteVector128(Position + 0x140, Thread.Context.ThreadState.V3);
Memory.WriteVector128(Position + 0x150, Thread.Context.ThreadState.V4);
Memory.WriteVector128(Position + 0x160, Thread.Context.ThreadState.V5);
Memory.WriteVector128(Position + 0x170, Thread.Context.ThreadState.V6);
Memory.WriteVector128(Position + 0x180, Thread.Context.ThreadState.V7);
Memory.WriteVector128(Position + 0x190, Thread.Context.ThreadState.V8);
Memory.WriteVector128(Position + 0x1a0, Thread.Context.ThreadState.V9);
Memory.WriteVector128(Position + 0x1b0, Thread.Context.ThreadState.V10);
Memory.WriteVector128(Position + 0x1c0, Thread.Context.ThreadState.V11);
Memory.WriteVector128(Position + 0x1d0, Thread.Context.ThreadState.V12);
Memory.WriteVector128(Position + 0x1e0, Thread.Context.ThreadState.V13);
Memory.WriteVector128(Position + 0x1f0, Thread.Context.ThreadState.V14);
Memory.WriteVector128(Position + 0x200, Thread.Context.ThreadState.V15);
Memory.WriteVector128(Position + 0x210, Thread.Context.ThreadState.V16);
Memory.WriteVector128(Position + 0x220, Thread.Context.ThreadState.V17);
Memory.WriteVector128(Position + 0x230, Thread.Context.ThreadState.V18);
Memory.WriteVector128(Position + 0x240, Thread.Context.ThreadState.V19);
Memory.WriteVector128(Position + 0x250, Thread.Context.ThreadState.V20);
Memory.WriteVector128(Position + 0x260, Thread.Context.ThreadState.V21);
Memory.WriteVector128(Position + 0x270, Thread.Context.ThreadState.V22);
Memory.WriteVector128(Position + 0x280, Thread.Context.ThreadState.V23);
Memory.WriteVector128(Position + 0x290, Thread.Context.ThreadState.V24);
Memory.WriteVector128(Position + 0x2a0, Thread.Context.ThreadState.V25);
Memory.WriteVector128(Position + 0x2b0, Thread.Context.ThreadState.V26);
Memory.WriteVector128(Position + 0x2c0, Thread.Context.ThreadState.V27);
Memory.WriteVector128(Position + 0x2d0, Thread.Context.ThreadState.V28);
Memory.WriteVector128(Position + 0x2e0, Thread.Context.ThreadState.V29);
Memory.WriteVector128(Position + 0x2f0, Thread.Context.ThreadState.V30);
Memory.WriteVector128(Position + 0x300, Thread.Context.ThreadState.V31);
_memory.WriteVector128(position + 0x110, thread.Context.ThreadState.V0);
_memory.WriteVector128(position + 0x120, thread.Context.ThreadState.V1);
_memory.WriteVector128(position + 0x130, thread.Context.ThreadState.V2);
_memory.WriteVector128(position + 0x140, thread.Context.ThreadState.V3);
_memory.WriteVector128(position + 0x150, thread.Context.ThreadState.V4);
_memory.WriteVector128(position + 0x160, thread.Context.ThreadState.V5);
_memory.WriteVector128(position + 0x170, thread.Context.ThreadState.V6);
_memory.WriteVector128(position + 0x180, thread.Context.ThreadState.V7);
_memory.WriteVector128(position + 0x190, thread.Context.ThreadState.V8);
_memory.WriteVector128(position + 0x1a0, thread.Context.ThreadState.V9);
_memory.WriteVector128(position + 0x1b0, thread.Context.ThreadState.V10);
_memory.WriteVector128(position + 0x1c0, thread.Context.ThreadState.V11);
_memory.WriteVector128(position + 0x1d0, thread.Context.ThreadState.V12);
_memory.WriteVector128(position + 0x1e0, thread.Context.ThreadState.V13);
_memory.WriteVector128(position + 0x1f0, thread.Context.ThreadState.V14);
_memory.WriteVector128(position + 0x200, thread.Context.ThreadState.V15);
_memory.WriteVector128(position + 0x210, thread.Context.ThreadState.V16);
_memory.WriteVector128(position + 0x220, thread.Context.ThreadState.V17);
_memory.WriteVector128(position + 0x230, thread.Context.ThreadState.V18);
_memory.WriteVector128(position + 0x240, thread.Context.ThreadState.V19);
_memory.WriteVector128(position + 0x250, thread.Context.ThreadState.V20);
_memory.WriteVector128(position + 0x260, thread.Context.ThreadState.V21);
_memory.WriteVector128(position + 0x270, thread.Context.ThreadState.V22);
_memory.WriteVector128(position + 0x280, thread.Context.ThreadState.V23);
_memory.WriteVector128(position + 0x290, thread.Context.ThreadState.V24);
_memory.WriteVector128(position + 0x2a0, thread.Context.ThreadState.V25);
_memory.WriteVector128(position + 0x2b0, thread.Context.ThreadState.V26);
_memory.WriteVector128(position + 0x2c0, thread.Context.ThreadState.V27);
_memory.WriteVector128(position + 0x2d0, thread.Context.ThreadState.V28);
_memory.WriteVector128(position + 0x2e0, thread.Context.ThreadState.V29);
_memory.WriteVector128(position + 0x2f0, thread.Context.ThreadState.V30);
_memory.WriteVector128(position + 0x300, thread.Context.ThreadState.V31);
Memory.WriteInt32(Position + 0x310, Thread.Context.ThreadState.Fpcr);
Memory.WriteInt32(Position + 0x314, Thread.Context.ThreadState.Fpsr);
Memory.WriteInt64(Position + 0x318, Thread.Context.ThreadState.Tpidr);
_memory.WriteInt32(position + 0x310, thread.Context.ThreadState.Fpcr);
_memory.WriteInt32(position + 0x314, thread.Context.ThreadState.Fpsr);
_memory.WriteInt64(position + 0x318, thread.Context.ThreadState.Tpidr);
ThreadState.X0 = 0;
threadState.X0 = 0;
}
}
}

View File

@ -8,366 +8,366 @@ namespace Ryujinx.HLE.HOS.Kernel
{
partial class SvcHandler
{
private void SvcWaitSynchronization(CpuThreadState ThreadState)
private void SvcWaitSynchronization(CpuThreadState threadState)
{
long HandlesPtr = (long)ThreadState.X1;
int HandlesCount = (int)ThreadState.X2;
long Timeout = (long)ThreadState.X3;
long handlesPtr = (long)threadState.X1;
int handlesCount = (int)threadState.X2;
long timeout = (long)threadState.X3;
Logger.PrintDebug(LogClass.KernelSvc,
"HandlesPtr = 0x" + HandlesPtr .ToString("x16") + ", " +
"HandlesCount = 0x" + HandlesCount.ToString("x8") + ", " +
"Timeout = 0x" + Timeout .ToString("x16"));
"HandlesPtr = 0x" + handlesPtr .ToString("x16") + ", " +
"HandlesCount = 0x" + handlesCount.ToString("x8") + ", " +
"Timeout = 0x" + timeout .ToString("x16"));
if ((uint)HandlesCount > 0x40)
if ((uint)handlesCount > 0x40)
{
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange);
return;
}
List<KSynchronizationObject> SyncObjs = new List<KSynchronizationObject>();
List<KSynchronizationObject> syncObjs = new List<KSynchronizationObject>();
for (int Index = 0; Index < HandlesCount; Index++)
for (int index = 0; index < handlesCount; index++)
{
int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
int handle = _memory.ReadInt32(handlesPtr + index * 4);
Logger.PrintDebug(LogClass.KernelSvc, $"Sync handle 0x{Handle:x8}");
Logger.PrintDebug(LogClass.KernelSvc, $"Sync handle 0x{handle:x8}");
KSynchronizationObject SyncObj = Process.HandleTable.GetObject<KSynchronizationObject>(Handle);
KSynchronizationObject syncObj = _process.HandleTable.GetObject<KSynchronizationObject>(handle);
if (SyncObj == null)
if (syncObj == null)
{
break;
}
SyncObjs.Add(SyncObj);
syncObjs.Add(syncObj);
}
int HndIndex = (int)ThreadState.X1;
int hndIndex = (int)threadState.X1;
ulong High = ThreadState.X1 & (0xffffffffUL << 32);
ulong high = threadState.X1 & (0xffffffffUL << 32);
long Result = System.Synchronization.WaitFor(SyncObjs.ToArray(), Timeout, ref HndIndex);
long result = _system.Synchronization.WaitFor(syncObjs.ToArray(), timeout, ref hndIndex);
if (Result != 0)
if (result != 0)
{
if (Result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) ||
Result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled))
if (result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) ||
result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled))
{
Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
}
ThreadState.X0 = (ulong)Result;
ThreadState.X1 = (uint)HndIndex | High;
threadState.X0 = (ulong)result;
threadState.X1 = (uint)hndIndex | high;
}
private void SvcCancelSynchronization(CpuThreadState ThreadState)
private void SvcCancelSynchronization(CpuThreadState threadState)
{
int ThreadHandle = (int)ThreadState.X0;
int threadHandle = (int)threadState.X0;
Logger.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + ThreadHandle.ToString("x8"));
Logger.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + threadHandle.ToString("x8"));
KThread Thread = Process.HandleTable.GetKThread(ThreadHandle);
KThread thread = _process.HandleTable.GetKThread(threadHandle);
if (Thread == null)
if (thread == null)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{threadHandle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
Thread.CancelSynchronization();
thread.CancelSynchronization();
ThreadState.X0 = 0;
threadState.X0 = 0;
}
private void SvcArbitrateLock(CpuThreadState ThreadState)
private void SvcArbitrateLock(CpuThreadState threadState)
{
int OwnerHandle = (int)ThreadState.X0;
long MutexAddress = (long)ThreadState.X1;
int RequesterHandle = (int)ThreadState.X2;
int ownerHandle = (int)threadState.X0;
long mutexAddress = (long)threadState.X1;
int requesterHandle = (int)threadState.X2;
Logger.PrintDebug(LogClass.KernelSvc,
"OwnerHandle = 0x" + OwnerHandle .ToString("x8") + ", " +
"MutexAddress = 0x" + MutexAddress .ToString("x16") + ", " +
"RequesterHandle = 0x" + RequesterHandle.ToString("x8"));
"OwnerHandle = 0x" + ownerHandle .ToString("x8") + ", " +
"MutexAddress = 0x" + mutexAddress .ToString("x16") + ", " +
"RequesterHandle = 0x" + requesterHandle.ToString("x8"));
if (IsPointingInsideKernel(MutexAddress))
if (IsPointingInsideKernel(mutexAddress))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{mutexAddress:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (IsAddressNotWordAligned(MutexAddress))
if (IsAddressNotWordAligned(mutexAddress))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{mutexAddress:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
long Result = CurrentProcess.AddressArbiter.ArbitrateLock(OwnerHandle, MutexAddress, RequesterHandle);
long result = currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle);
if (Result != 0)
if (result != 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcArbitrateUnlock(CpuThreadState ThreadState)
private void SvcArbitrateUnlock(CpuThreadState threadState)
{
long MutexAddress = (long)ThreadState.X0;
long mutexAddress = (long)threadState.X0;
Logger.PrintDebug(LogClass.KernelSvc, "MutexAddress = 0x" + MutexAddress.ToString("x16"));
Logger.PrintDebug(LogClass.KernelSvc, "MutexAddress = 0x" + mutexAddress.ToString("x16"));
if (IsPointingInsideKernel(MutexAddress))
if (IsPointingInsideKernel(mutexAddress))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{mutexAddress:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (IsAddressNotWordAligned(MutexAddress))
if (IsAddressNotWordAligned(mutexAddress))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{mutexAddress:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
long Result = CurrentProcess.AddressArbiter.ArbitrateUnlock(MutexAddress);
long result = currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress);
if (Result != 0)
if (result != 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcWaitProcessWideKeyAtomic(CpuThreadState ThreadState)
private void SvcWaitProcessWideKeyAtomic(CpuThreadState threadState)
{
long MutexAddress = (long)ThreadState.X0;
long CondVarAddress = (long)ThreadState.X1;
int ThreadHandle = (int)ThreadState.X2;
long Timeout = (long)ThreadState.X3;
long mutexAddress = (long)threadState.X0;
long condVarAddress = (long)threadState.X1;
int threadHandle = (int)threadState.X2;
long timeout = (long)threadState.X3;
Logger.PrintDebug(LogClass.KernelSvc,
"MutexAddress = 0x" + MutexAddress .ToString("x16") + ", " +
"CondVarAddress = 0x" + CondVarAddress.ToString("x16") + ", " +
"ThreadHandle = 0x" + ThreadHandle .ToString("x8") + ", " +
"Timeout = 0x" + Timeout .ToString("x16"));
"MutexAddress = 0x" + mutexAddress .ToString("x16") + ", " +
"CondVarAddress = 0x" + condVarAddress.ToString("x16") + ", " +
"ThreadHandle = 0x" + threadHandle .ToString("x8") + ", " +
"Timeout = 0x" + timeout .ToString("x16"));
if (IsPointingInsideKernel(MutexAddress))
if (IsPointingInsideKernel(mutexAddress))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{mutexAddress:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (IsAddressNotWordAligned(MutexAddress))
if (IsAddressNotWordAligned(mutexAddress))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{mutexAddress:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
long Result = CurrentProcess.AddressArbiter.WaitProcessWideKeyAtomic(
MutexAddress,
CondVarAddress,
ThreadHandle,
Timeout);
long result = currentProcess.AddressArbiter.WaitProcessWideKeyAtomic(
mutexAddress,
condVarAddress,
threadHandle,
timeout);
if (Result != 0)
if (result != 0)
{
if (Result == MakeError(ErrorModule.Kernel, KernelErr.Timeout))
if (result == MakeError(ErrorModule.Kernel, KernelErr.Timeout))
{
Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
else
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcSignalProcessWideKey(CpuThreadState ThreadState)
private void SvcSignalProcessWideKey(CpuThreadState threadState)
{
long Address = (long)ThreadState.X0;
int Count = (int)ThreadState.X1;
long address = (long)threadState.X0;
int count = (int)threadState.X1;
Logger.PrintDebug(LogClass.KernelSvc,
"Address = 0x" + Address.ToString("x16") + ", " +
"Count = 0x" + Count .ToString("x8"));
"Address = 0x" + address.ToString("x16") + ", " +
"Count = 0x" + count .ToString("x8"));
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
CurrentProcess.AddressArbiter.SignalProcessWideKey(Address, Count);
currentProcess.AddressArbiter.SignalProcessWideKey(address, count);
ThreadState.X0 = 0;
threadState.X0 = 0;
}
private void SvcWaitForAddress(CpuThreadState ThreadState)
private void SvcWaitForAddress(CpuThreadState threadState)
{
long Address = (long)ThreadState.X0;
ArbitrationType Type = (ArbitrationType)ThreadState.X1;
int Value = (int)ThreadState.X2;
long Timeout = (long)ThreadState.X3;
long address = (long)threadState.X0;
ArbitrationType type = (ArbitrationType)threadState.X1;
int value = (int)threadState.X2;
long timeout = (long)threadState.X3;
Logger.PrintDebug(LogClass.KernelSvc,
"Address = 0x" + Address.ToString("x16") + ", " +
"Type = " + Type .ToString() + ", " +
"Value = 0x" + Value .ToString("x8") + ", " +
"Timeout = 0x" + Timeout.ToString("x16"));
"Address = 0x" + address.ToString("x16") + ", " +
"Type = " + type .ToString() + ", " +
"Value = 0x" + value .ToString("x8") + ", " +
"Timeout = 0x" + timeout.ToString("x16"));
if (IsPointingInsideKernel(Address))
if (IsPointingInsideKernel(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{address:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (IsAddressNotWordAligned(Address))
if (IsAddressNotWordAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{address:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
long Result;
long result;
switch (Type)
switch (type)
{
case ArbitrationType.WaitIfLessThan:
Result = CurrentProcess.AddressArbiter.WaitForAddressIfLessThan(Address, Value, false, Timeout);
result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout);
break;
case ArbitrationType.DecrementAndWaitIfLessThan:
Result = CurrentProcess.AddressArbiter.WaitForAddressIfLessThan(Address, Value, true, Timeout);
result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout);
break;
case ArbitrationType.WaitIfEqual:
Result = CurrentProcess.AddressArbiter.WaitForAddressIfEqual(Address, Value, Timeout);
result = currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout);
break;
default:
Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
break;
}
if (Result != 0)
if (result != 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private void SvcSignalToAddress(CpuThreadState ThreadState)
private void SvcSignalToAddress(CpuThreadState threadState)
{
long Address = (long)ThreadState.X0;
SignalType Type = (SignalType)ThreadState.X1;
int Value = (int)ThreadState.X2;
int Count = (int)ThreadState.X3;
long address = (long)threadState.X0;
SignalType type = (SignalType)threadState.X1;
int value = (int)threadState.X2;
int count = (int)threadState.X3;
Logger.PrintDebug(LogClass.KernelSvc,
"Address = 0x" + Address.ToString("x16") + ", " +
"Type = " + Type .ToString() + ", " +
"Value = 0x" + Value .ToString("x8") + ", " +
"Count = 0x" + Count .ToString("x8"));
"Address = 0x" + address.ToString("x16") + ", " +
"Type = " + type .ToString() + ", " +
"Value = 0x" + value .ToString("x8") + ", " +
"Count = 0x" + count .ToString("x8"));
if (IsPointingInsideKernel(Address))
if (IsPointingInsideKernel(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{address:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
return;
}
if (IsAddressNotWordAligned(Address))
if (IsAddressNotWordAligned(address))
{
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{address:x16}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
return;
}
KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
long Result;
long result;
switch (Type)
switch (type)
{
case SignalType.Signal:
Result = CurrentProcess.AddressArbiter.Signal(Address, Count);
result = currentProcess.AddressArbiter.Signal(address, count);
break;
case SignalType.SignalAndIncrementIfEqual:
Result = CurrentProcess.AddressArbiter.SignalAndIncrementIfEqual(Address, Value, Count);
result = currentProcess.AddressArbiter.SignalAndIncrementIfEqual(address, value, count);
break;
case SignalType.SignalAndModifyIfEqual:
Result = CurrentProcess.AddressArbiter.SignalAndModifyIfEqual(Address, Value, Count);
result = currentProcess.AddressArbiter.SignalAndModifyIfEqual(address, value, count);
break;
default:
Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
break;
}
if (Result != 0)
if (result != 0)
{
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!");
}
ThreadState.X0 = (ulong)Result;
threadState.X0 = (ulong)result;
}
private bool IsPointingInsideKernel(long Address)
private bool IsPointingInsideKernel(long address)
{
return ((ulong)Address + 0x1000000000) < 0xffffff000;
return ((ulong)address + 0x1000000000) < 0xffffff000;
}
private bool IsAddressNotWordAligned(long Address)
private bool IsAddressNotWordAligned(long address)
{
return (Address & 3) != 0;
return (address & 3) != 0;
}
}
}