Ryubing/src/Ryujinx.HLE/HOS/Kernel/KernelContext.cs
LotP1 918ec1bde3
cores rework (#505)
This PR changes the core count to be defined in the device instead of
being a const value.
This is mostly a change for future features I want to implement and
should not impact any functionality.
The console will now log the range of cores requested from the
application, and for now, if the requested range is not 0 to 2 (the 3
cores used for application emulation), it will give an error message
which tells the user to contact me on discord. I'm doing this because
I'm interested in finding applications/games that don't use 3 cores and
the error will be removed in the future once I've gotten enough data.
2025-01-09 21:43:18 -06:00

162 lines
5.1 KiB
C#

using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Memory;
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel
{
class KernelContext : IDisposable
{
public long PrivilegedProcessLowestId { get; set; } = 1;
public long PrivilegedProcessHighestId { get; set; } = 8;
public bool EnableVersionChecks { get; set; }
public bool KernelInitialized { get; }
public bool Running { get; private set; }
public Switch Device { get; }
public MemoryBlock Memory { get; }
public ITickSource TickSource { get; }
public Syscall Syscall { get; }
public SyscallHandler SyscallHandler { get; }
public KResourceLimit ResourceLimit { get; }
public KMemoryManager MemoryManager { get; }
public KMemoryBlockSlabManager LargeMemoryBlockSlabManager { get; }
public KMemoryBlockSlabManager SmallMemoryBlockSlabManager { get; }
public KSlabHeap UserSlabHeapPages { get; }
public KCriticalSection CriticalSection { get; }
public KScheduler[] Schedulers { get; }
public KPriorityQueue PriorityQueue { get; }
public KTimeManager TimeManager { get; }
public KSynchronization Synchronization { get; }
public KContextIdManager ContextIdManager { get; }
public ConcurrentDictionary<ulong, KProcess> Processes { get; }
public ConcurrentDictionary<string, KAutoObject> AutoObjectNames { get; }
public bool ThreadReselectionRequested { get; set; }
private ulong _kipId;
private ulong _processId;
private ulong _threadUid;
public KernelContext(
ITickSource tickSource,
Switch device,
MemoryBlock memory,
MemorySize memorySize,
MemoryArrange memoryArrange)
{
TickSource = tickSource;
Device = device;
Memory = memory;
KScheduler.CpuCoresCount = device.CpuCoresCount;
Running = true;
Syscall = new Syscall(this);
SyscallHandler = new SyscallHandler(this);
ResourceLimit = new KResourceLimit(this);
KernelInit.InitializeResourceLimit(ResourceLimit, memorySize);
MemoryManager = new KMemoryManager(memorySize, memoryArrange);
LargeMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize * 2);
SmallMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize);
UserSlabHeapPages = new KSlabHeap(
KernelConstants.UserSlabHeapBase,
KernelConstants.UserSlabHeapItemSize,
KernelConstants.UserSlabHeapSize);
CommitMemory(KernelConstants.UserSlabHeapBase - DramMemoryMap.DramBase, KernelConstants.UserSlabHeapSize);
CriticalSection = new KCriticalSection(this);
Schedulers = new KScheduler[KScheduler.CpuCoresCount];
PriorityQueue = new KPriorityQueue();
TimeManager = new KTimeManager(this);
Synchronization = new KSynchronization(this);
ContextIdManager = new KContextIdManager();
for (int core = 0; core < KScheduler.CpuCoresCount; core++)
{
Schedulers[core] = new KScheduler(this, core);
}
StartPreemptionThread();
KernelInitialized = true;
Processes = new ConcurrentDictionary<ulong, KProcess>();
AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>();
_kipId = KernelConstants.InitialKipId;
_processId = KernelConstants.InitialProcessId;
}
private void StartPreemptionThread()
{
void PreemptionThreadStart()
{
KScheduler.PreemptionThreadLoop(this);
}
new Thread(PreemptionThreadStart) { Name = "HLE.PreemptionThread" }.Start();
}
public void CommitMemory(ulong address, ulong size)
{
ulong alignment = MemoryBlock.GetPageSize();
ulong endAddress = address + size;
address &= ~(alignment - 1);
endAddress = (endAddress + (alignment - 1)) & ~(alignment - 1);
Memory.Commit(address, endAddress - address);
}
public ulong NewThreadUid()
{
return Interlocked.Increment(ref _threadUid) - 1;
}
public ulong NewKipId()
{
return Interlocked.Increment(ref _kipId) - 1;
}
public ulong NewProcessId()
{
return Interlocked.Increment(ref _processId) - 1;
}
public void Dispose()
{
Running = false;
for (int i = 0; i < KScheduler.CpuCoresCount; i++)
{
Schedulers[i].Dispose();
}
TimeManager.Dispose();
}
}
}