예제 #1
0
 public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context)
 {
     context.Interrupt      += InterruptHandler;
     context.SupervisorCall += KernelContext.SyscallHandler.SvcCall;
     context.Undefined      += UndefinedInstructionHandler;
 }
예제 #2
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;
            }

            HostThread = new Thread(() => ThreadStart(entrypoint));

            if (System.UseLegacyJit)
            {
                Context = new ChocolArm64.State.CpuThreadState();
            }
            else
            {
                Context = new ARMeilleure.State.ExecutionContext();
            }

            bool isAarch32 = (Owner.MmuFlags & 1) == 0;

            Context.SetX(0, argsPtr);

            if (isAarch32)
            {
                Context.SetX(13, (uint)stackTop);
            }
            else
            {
                Context.SetX(31, stackTop);
            }

            Context.CntfrqEl0 = 19200000;
            Context.Tpidr     = (long)_tlsAddress;

            owner.SubscribeThreadEventHandlers(Context);

            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);
        }