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 }