/ src / Ryujinx.HLE / HOS / Kernel / KernelContext.cs
KernelContext.cs
  1  using Ryujinx.Cpu;
  2  using Ryujinx.HLE.HOS.Kernel.Common;
  3  using Ryujinx.HLE.HOS.Kernel.Memory;
  4  using Ryujinx.HLE.HOS.Kernel.Process;
  5  using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
  6  using Ryujinx.HLE.HOS.Kernel.Threading;
  7  using Ryujinx.Memory;
  8  using System;
  9  using System.Collections.Concurrent;
 10  using System.Threading;
 11  
 12  namespace Ryujinx.HLE.HOS.Kernel
 13  {
 14      class KernelContext : IDisposable
 15      {
 16          public long PrivilegedProcessLowestId { get; set; } = 1;
 17          public long PrivilegedProcessHighestId { get; set; } = 8;
 18  
 19          public bool EnableVersionChecks { get; set; }
 20  
 21          public bool KernelInitialized { get; }
 22  
 23          public bool Running { get; private set; }
 24  
 25          public Switch Device { get; }
 26          public MemoryBlock Memory { get; }
 27          public ITickSource TickSource { get; }
 28          public Syscall Syscall { get; }
 29          public SyscallHandler SyscallHandler { get; }
 30  
 31          public KResourceLimit ResourceLimit { get; }
 32  
 33          public KMemoryManager MemoryManager { get; }
 34  
 35          public KMemoryBlockSlabManager LargeMemoryBlockSlabManager { get; }
 36          public KMemoryBlockSlabManager SmallMemoryBlockSlabManager { get; }
 37  
 38          public KSlabHeap UserSlabHeapPages { get; }
 39  
 40          public KCriticalSection CriticalSection { get; }
 41          public KScheduler[] Schedulers { get; }
 42          public KPriorityQueue PriorityQueue { get; }
 43          public KTimeManager TimeManager { get; }
 44          public KSynchronization Synchronization { get; }
 45          public KContextIdManager ContextIdManager { get; }
 46  
 47          public ConcurrentDictionary<ulong, KProcess> Processes { get; }
 48          public ConcurrentDictionary<string, KAutoObject> AutoObjectNames { get; }
 49  
 50          public bool ThreadReselectionRequested { get; set; }
 51  
 52          private ulong _kipId;
 53          private ulong _processId;
 54          private ulong _threadUid;
 55  
 56          public KernelContext(
 57              ITickSource tickSource,
 58              Switch device,
 59              MemoryBlock memory,
 60              MemorySize memorySize,
 61              MemoryArrange memoryArrange)
 62          {
 63              TickSource = tickSource;
 64              Device = device;
 65              Memory = memory;
 66  
 67              Running = true;
 68  
 69              Syscall = new Syscall(this);
 70  
 71              SyscallHandler = new SyscallHandler(this);
 72  
 73              ResourceLimit = new KResourceLimit(this);
 74  
 75              KernelInit.InitializeResourceLimit(ResourceLimit, memorySize);
 76  
 77              MemoryManager = new KMemoryManager(memorySize, memoryArrange);
 78  
 79              LargeMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize * 2);
 80              SmallMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize);
 81  
 82              UserSlabHeapPages = new KSlabHeap(
 83                  KernelConstants.UserSlabHeapBase,
 84                  KernelConstants.UserSlabHeapItemSize,
 85                  KernelConstants.UserSlabHeapSize);
 86  
 87              CommitMemory(KernelConstants.UserSlabHeapBase - DramMemoryMap.DramBase, KernelConstants.UserSlabHeapSize);
 88  
 89              CriticalSection = new KCriticalSection(this);
 90              Schedulers = new KScheduler[KScheduler.CpuCoresCount];
 91              PriorityQueue = new KPriorityQueue();
 92              TimeManager = new KTimeManager(this);
 93              Synchronization = new KSynchronization(this);
 94              ContextIdManager = new KContextIdManager();
 95  
 96              for (int core = 0; core < KScheduler.CpuCoresCount; core++)
 97              {
 98                  Schedulers[core] = new KScheduler(this, core);
 99              }
100  
101              StartPreemptionThread();
102  
103              KernelInitialized = true;
104  
105              Processes = new ConcurrentDictionary<ulong, KProcess>();
106              AutoObjectNames = new ConcurrentDictionary<string, KAutoObject>();
107  
108              _kipId = KernelConstants.InitialKipId;
109              _processId = KernelConstants.InitialProcessId;
110          }
111  
112          private void StartPreemptionThread()
113          {
114              void PreemptionThreadStart()
115              {
116                  KScheduler.PreemptionThreadLoop(this);
117              }
118  
119              new Thread(PreemptionThreadStart) { Name = "HLE.PreemptionThread" }.Start();
120          }
121  
122          public void CommitMemory(ulong address, ulong size)
123          {
124              ulong alignment = MemoryBlock.GetPageSize();
125              ulong endAddress = address + size;
126  
127              address &= ~(alignment - 1);
128              endAddress = (endAddress + (alignment - 1)) & ~(alignment - 1);
129  
130              Memory.Commit(address, endAddress - address);
131          }
132  
133          public ulong NewThreadUid()
134          {
135              return Interlocked.Increment(ref _threadUid) - 1;
136          }
137  
138          public ulong NewKipId()
139          {
140              return Interlocked.Increment(ref _kipId) - 1;
141          }
142  
143          public ulong NewProcessId()
144          {
145              return Interlocked.Increment(ref _processId) - 1;
146          }
147  
148          public void Dispose()
149          {
150              Running = false;
151  
152              for (int i = 0; i < KScheduler.CpuCoresCount; i++)
153              {
154                  Schedulers[i].Dispose();
155              }
156  
157              TimeManager.Dispose();
158          }
159      }
160  }