Exemplo n.º 1
0
 public void Teardown()
 {
     Marshal.FreeHGlobal(_ramPointer);
     _memory     = null;
     _thread     = null;
     _unicornEmu = null;
 }
Exemplo n.º 2
0
        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;
        }
Exemplo n.º 3
0
        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();
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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;
            }
        }
Exemplo n.º 6
0
        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();
            }
        }
Exemplo n.º 7
0
 public void SubscribeThreadEventHandlers(CpuThread context)
 {
     context.ThreadState.Interrupt += InterruptHandler;
     context.ThreadState.SvcCall   += _svcHandler.SvcCall;
     context.ThreadState.Undefined += UndefinedInstructionHandler;
 }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
 public void SubscribeThreadEventHandlers(CpuThread context)
 {
     context.ThreadState.Interrupt += InterruptHandler;
     context.ThreadState.SvcCall   += _svcHandler.SvcCall;
 }
Exemplo n.º 10
0
        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);
        }