public void Teardown() { Marshal.FreeHGlobal(_ramPointer); _memory = null; _thread = null; _unicornEmu = null; }
public KThread( CpuThread Thread, Process Process, Horizon System, int ProcessorId, int Priority, int ThreadId) : base(System) { this.ThreadId = ThreadId; Context = Thread; Owner = Process; PreferredCore = ProcessorId; Scheduler = System.Scheduler; SchedulingData = System.Scheduler.SchedulingData; SiblingsPerCore = new LinkedListNode <KThread> [KScheduler.CpuCoresCount]; MutexWaiters = new LinkedList <KThread>(); AffinityMask = 1 << ProcessorId; DynamicPriority = BasePriority = Priority; CurrentCore = PreferredCore; }
internal void ExecuteSubroutine(CpuThread thread, long position) { if (Interlocked.Increment(ref _threadCount) == 1) { _backgroundTranslator = new Thread(TranslateQueuedSubs); _backgroundTranslator.Start(); } ExecuteSubroutine(thread.ThreadState, position); if (Interlocked.Decrement(ref _threadCount) == 0) { _queue.ForceSignal(); } }
public int MakeThread( long EntryPoint, long StackTop, long ArgsPtr, int Priority, int ProcessorId) { if (Disposed) { throw new ObjectDisposedException(nameof(Process)); } CpuThread CpuThread = new CpuThread(GetTranslator(), Memory, EntryPoint); long Tpidr = GetFreeTls(); int ThreadId = ThreadIdCtr++; //(int)((Tpidr - MemoryManager.TlsIoRegionStart) / 0x200) + 1; KThread Thread = new KThread(CpuThread, this, Device.System, ProcessorId, Priority, ThreadId); Thread.LastPc = EntryPoint; HandleTable.GenerateHandle(Thread, out int Handle); CpuThread.ThreadState.CntfrqEl0 = TickFreq; CpuThread.ThreadState.Tpidr = Tpidr; CpuThread.ThreadState.X0 = (ulong)ArgsPtr; CpuThread.ThreadState.X1 = (ulong)Handle; CpuThread.ThreadState.X31 = (ulong)StackTop; CpuThread.ThreadState.Interrupt += InterruptHandler; CpuThread.ThreadState.Break += BreakHandler; CpuThread.ThreadState.SvcCall += SvcHandler.SvcCall; CpuThread.ThreadState.Undefined += UndefinedHandler; CpuThread.WorkFinished += ThreadFinished; Threads.TryAdd(CpuThread.ThreadState.Tpidr, Thread); return(Handle); }
public void Setup() { Position = 0x1000; _size = 0x1000; _entryPoint = Position; Translator translator = new Translator(); _ramPointer = Marshal.AllocHGlobal(new IntPtr(_size)); _memory = new MemoryManager(_ramPointer); _memory.Map(Position, 0, _size); _thread = new CpuThread(translator, _memory, _entryPoint); if (_unicornAvailable) { _unicornEmu = new UnicornAArch64(); _unicornEmu.MemoryMap((ulong)Position, (ulong)_size, MemoryPermission.READ | MemoryPermission.EXEC); _unicornEmu.PC = (ulong)_entryPoint; } }
public void Leave() { if (_recursionCount == 0) { return; } bool doContextSwitch = false; if (--_recursionCount == 0) { if (_system.Scheduler.ThreadReselectionRequested) { _system.Scheduler.SelectThreads(); } Monitor.Exit(LockObj); if (_system.Scheduler.MultiCoreScheduling) { lock (_system.Scheduler.CoreContexts) { for (int core = 0; core < KScheduler.CpuCoresCount; core++) { KCoreContext coreContext = _system.Scheduler.CoreContexts[core]; if (coreContext.ContextSwitchNeeded) { CpuThread currentHleThread = coreContext.CurrentThread?.Context; if (currentHleThread == null) { //Nothing is running, we can perform the context switch immediately. coreContext.ContextSwitch(); } else if (currentHleThread.IsCurrentThread()) { //Thread running on the current core, context switch will block. doContextSwitch = true; } else { //Thread running on another core, request a interrupt. currentHleThread.RequestInterrupt(); } } } } } else { doContextSwitch = true; } } else { Monitor.Exit(LockObj); } if (doContextSwitch) { _system.Scheduler.ContextSwitch(); } }
public void SubscribeThreadEventHandlers(CpuThread context) { context.ThreadState.Interrupt += InterruptHandler; context.ThreadState.SvcCall += _svcHandler.SvcCall; context.ThreadState.Undefined += UndefinedInstructionHandler; }
public KernelResult Initialize( ulong entrypoint, ulong argsPtr, ulong stackTop, int priority, int defaultCpuCore, KProcess owner, ThreadType type = ThreadType.User) { if ((uint)type > 3) { throw new ArgumentException($"Invalid thread type \"{type}\"."); } PreferredCore = defaultCpuCore; AffinityMask |= 1L << defaultCpuCore; SchedFlags = type == ThreadType.Dummy ? ThreadSchedState.Running : ThreadSchedState.None; CurrentCore = PreferredCore; DynamicPriority = priority; BasePriority = priority; ObjSyncResult = KernelResult.ThreadNotStarted; _entrypoint = entrypoint; if (type == ThreadType.User) { if (owner.AllocateThreadLocalStorage(out _tlsAddress) != KernelResult.Success) { return(KernelResult.OutOfMemory); } TlsDramAddress = owner.MemoryManager.GetDramAddressFromVa(_tlsAddress); MemoryHelper.FillWithZeros(owner.CpuMemory, (long)_tlsAddress, KTlsPageInfo.TlsEntrySize); } bool is64Bits; if (owner != null) { Owner = owner; owner.IncrementReferenceCount(); owner.IncrementThreadCount(); is64Bits = (owner.MmuFlags & 1) != 0; } else { is64Bits = true; } Context = new CpuThread(owner.Translator, owner.CpuMemory, (long)entrypoint); bool isAarch32 = (Owner.MmuFlags & 1) == 0; Context.ThreadState.Aarch32 = isAarch32; Context.ThreadState.X0 = argsPtr; if (isAarch32) { Context.ThreadState.X13 = (uint)stackTop; } else { Context.ThreadState.X31 = stackTop; } Context.ThreadState.CntfrqEl0 = 19200000; Context.ThreadState.Tpidr = (long)_tlsAddress; owner.SubscribeThreadEventHandlers(Context); Context.WorkFinished += ThreadFinishedHandler; ThreadUid = System.GetThreadUid(); _hasBeenInitialized = true; if (owner != null) { owner.AddThread(this); if (owner.IsPaused) { System.CriticalSection.Enter(); if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending) { System.CriticalSection.Leave(); return(KernelResult.Success); } _forcePauseFlags |= ThreadSchedState.ProcessPauseFlag; CombineForcePauseFlags(); System.CriticalSection.Leave(); } } return(KernelResult.Success); }
public void SubscribeThreadEventHandlers(CpuThread context) { context.ThreadState.Interrupt += InterruptHandler; context.ThreadState.SvcCall += _svcHandler.SvcCall; }
public KernelResult Initialize( ulong Entrypoint, ulong ArgsPtr, ulong StackTop, int Priority, int DefaultCpuCore, KProcess Owner, ThreadType Type = ThreadType.User) { if ((uint)Type > 3) { throw new ArgumentException($"Invalid thread type \"{Type}\"."); } PreferredCore = DefaultCpuCore; AffinityMask |= 1L << DefaultCpuCore; SchedFlags = Type == ThreadType.Dummy ? ThreadSchedState.Running : ThreadSchedState.None; CurrentCore = PreferredCore; DynamicPriority = Priority; BasePriority = Priority; ObjSyncResult = 0x7201; this.Entrypoint = Entrypoint; if (Type == ThreadType.User) { if (Owner.AllocateThreadLocalStorage(out TlsAddress) != KernelResult.Success) { return(KernelResult.OutOfMemory); } MemoryHelper.FillWithZeros(Owner.CpuMemory, (long)TlsAddress, KTlsPageInfo.TlsEntrySize); } bool Is64Bits; if (Owner != null) { this.Owner = Owner; Owner.IncrementThreadCount(); Is64Bits = (Owner.MmuFlags & 1) != 0; } else { Is64Bits = true; } Context = new CpuThread(Owner.Translator, Owner.CpuMemory, (long)Entrypoint); Context.ThreadState.X0 = ArgsPtr; Context.ThreadState.X31 = StackTop; Context.ThreadState.CntfrqEl0 = 19200000; Context.ThreadState.Tpidr = (long)TlsAddress; Owner.SubscribeThreadEventHandlers(Context); Context.WorkFinished += ThreadFinishedHandler; ThreadUid = System.GetThreadUid(); if (Owner != null) { Owner.AddThread(this); if (Owner.IsPaused) { System.CriticalSection.Enter(); if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending) { System.CriticalSection.Leave(); return(KernelResult.Success); } ForcePauseFlags |= ThreadSchedState.ProcessPauseFlag; CombineForcePauseFlags(); System.CriticalSection.Leave(); } } return(KernelResult.Success); }