Ejemplo n.º 1
0
        private void CombineForcePauseFlags()
        {
            ThreadSchedState oldFlags  = SchedFlags;
            ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask;

            SchedFlags = lowNibble | _forcePauseFlags;

            AdjustScheduling(oldFlags);
        }
Ejemplo n.º 2
0
        private void CombineExceptionalSchedFlags()
        {
            ThreadSchedState OldStat   = SchedFlags;
            ThreadSchedState LowNibble = SchedFlags & ThreadSchedState.LowNibbleMask;

            SchedFlags = LowNibble | ExceptionalSchedFlags;

            AdjustScheduling(OldStat);
        }
Ejemplo n.º 3
0
        private void CombineForcePauseFlags()
        {
            ThreadSchedState OldFlags  = SchedFlags;
            ThreadSchedState LowNibble = SchedFlags & ThreadSchedState.LowNibbleMask;

            SchedFlags = LowNibble | ForcePauseFlags;

            AdjustScheduling(OldFlags);
        }
Ejemplo n.º 4
0
        public void Exit()
        {
            System.CriticalSectionLock.Lock();

            ForcePauseFlags &= ~ThreadSchedState.ExceptionalMask;

            ExitImpl();

            System.CriticalSectionLock.Unlock();
        }
Ejemplo n.º 5
0
        public void Exit()
        {
            System.CriticalSection.Enter();

            _forcePauseFlags &= ~ThreadSchedState.ForcePauseMask;

            ExitImpl();

            System.CriticalSection.Leave();
        }
Ejemplo n.º 6
0
        private void SetNewSchedFlags(ThreadSchedState NewFlags)
        {
            System.CriticalSectionLock.Lock();

            ThreadSchedState OldStat = SchedFlags;

            SchedFlags = (OldStat & ThreadSchedState.HighNibbleMask) | NewFlags;

            AdjustScheduling(OldStat);

            System.CriticalSectionLock.Unlock();
        }
Ejemplo n.º 7
0
        public void Reschedule(ThreadSchedState NewFlags)
        {
            System.CriticalSectionLock.Lock();

            ThreadSchedState OldFlags = SchedFlags;

            SchedFlags = (OldFlags & ThreadSchedState.HighNibbleMask) |
                         (NewFlags & ThreadSchedState.LowNibbleMask);

            AdjustScheduling(OldFlags);

            System.CriticalSectionLock.Unlock();
        }
Ejemplo n.º 8
0
        public void Reschedule(ThreadSchedState newFlags)
        {
            System.CriticalSection.Enter();

            ThreadSchedState oldFlags = SchedFlags;

            SchedFlags = (oldFlags & ThreadSchedState.HighMask) |
                         (newFlags & ThreadSchedState.LowMask);

            AdjustScheduling(oldFlags);

            System.CriticalSection.Leave();
        }
Ejemplo n.º 9
0
        private void SetNewSchedFlags(ThreadSchedState newFlags)
        {
            System.CriticalSection.Enter();

            ThreadSchedState oldFlags = SchedFlags;

            SchedFlags = (oldFlags & ThreadSchedState.HighMask) | newFlags;

            if ((oldFlags & ThreadSchedState.LowMask) != newFlags)
            {
                AdjustScheduling(oldFlags);
            }

            System.CriticalSection.Leave();
        }
Ejemplo n.º 10
0
        private void SetNewSchedFlags(ThreadSchedState NewFlags)
        {
            System.CriticalSectionLock.Lock();

            ThreadSchedState OldFlags = SchedFlags;

            SchedFlags = (OldFlags & ThreadSchedState.HighNibbleMask) | NewFlags;

            if ((OldFlags & ThreadSchedState.LowNibbleMask) != NewFlags)
            {
                AdjustScheduling(OldFlags);
            }

            System.CriticalSectionLock.Unlock();
        }
Ejemplo n.º 11
0
        private void AdjustScheduling(ThreadSchedState OldFlags)
        {
            if (OldFlags == SchedFlags)
            {
                return;
            }

            if (OldFlags == ThreadSchedState.Running)
            {
                //Was running, now it's stopped.
                if (CurrentCore >= 0)
                {
                    SchedulingData.Unschedule(DynamicPriority, CurrentCore, this);
                }

                for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
                {
                    if (Core != CurrentCore && ((AffinityMask >> Core) & 1) != 0)
                    {
                        SchedulingData.Unsuggest(DynamicPriority, Core, this);
                    }
                }
            }
            else if (SchedFlags == ThreadSchedState.Running)
            {
                //Was stopped, now it's running.
                if (CurrentCore >= 0)
                {
                    SchedulingData.Schedule(DynamicPriority, CurrentCore, this);
                }

                for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
                {
                    if (Core != CurrentCore && ((AffinityMask >> Core) & 1) != 0)
                    {
                        SchedulingData.Suggest(DynamicPriority, Core, this);
                    }
                }
            }

            Scheduler.ThreadReselectionRequested = true;
        }
Ejemplo n.º 12
0
        public void Exit()
        {
            //TODO: Debug event.

            if (Owner != null)
            {
                Owner.ResourceLimit?.Release(LimitableResource.Thread, 0, 1);

                _hasBeenReleased = true;
            }

            System.CriticalSection.Enter();

            _forcePauseFlags &= ~ThreadSchedState.ForcePauseMask;

            ExitImpl();

            System.CriticalSection.Leave();

            DecrementReferenceCount();
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
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);
        }
Ejemplo n.º 15
0
        public KernelResult Start()
        {
            if (!System.KernelInitialized)
            {
                System.CriticalSection.Enter();

                if (!ShallBeTerminated && SchedFlags != ThreadSchedState.TerminationPending)
                {
                    _forcePauseFlags |= ThreadSchedState.KernelInitPauseFlag;

                    CombineForcePauseFlags();
                }

                System.CriticalSection.Leave();
            }

            KernelResult result = KernelResult.ThreadTerminating;

            System.CriticalSection.Enter();

            if (!ShallBeTerminated)
            {
                KThread currentThread = System.Scheduler.GetCurrentThread();

                while (SchedFlags != ThreadSchedState.TerminationPending &&
                       currentThread.SchedFlags != ThreadSchedState.TerminationPending &&
                       !currentThread.ShallBeTerminated)
                {
                    if ((SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.None)
                    {
                        result = KernelResult.InvalidState;

                        break;
                    }

                    if (currentThread._forcePauseFlags == ThreadSchedState.None)
                    {
                        if (Owner != null && _forcePauseFlags != ThreadSchedState.None)
                        {
                            CombineForcePauseFlags();
                        }

                        SetNewSchedFlags(ThreadSchedState.Running);

                        result = KernelResult.Success;

                        break;
                    }
                    else
                    {
                        currentThread.CombineForcePauseFlags();

                        System.CriticalSection.Leave();
                        System.CriticalSection.Enter();

                        if (currentThread.ShallBeTerminated)
                        {
                            break;
                        }
                    }
                }
            }

            System.CriticalSection.Leave();

            return(result);
        }
Ejemplo n.º 16
0
        public long SetActivity(bool Pause)
        {
            long Result = 0;

            System.CriticalSectionLock.Lock();

            ThreadSchedState LowNibble = SchedFlags & ThreadSchedState.LowNibbleMask;

            if (LowNibble != ThreadSchedState.Paused && LowNibble != ThreadSchedState.Running)
            {
                System.CriticalSectionLock.Unlock();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
            }

            System.CriticalSectionLock.Lock();

            if (!ShallBeTerminated && SchedFlags != ThreadSchedState.TerminationPending)
            {
                if (Pause)
                {
                    //Pause, the force pause flag should be clear (thread is NOT paused).
                    if ((ForcePauseFlags & ThreadSchedState.ForcePauseFlag) == 0)
                    {
                        ForcePauseFlags |= ThreadSchedState.ForcePauseFlag;

                        CombineForcePauseFlags();
                    }
                    else
                    {
                        Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
                    }
                }
                else
                {
                    //Unpause, the force pause flag should be set (thread is paused).
                    if ((ForcePauseFlags & ThreadSchedState.ForcePauseFlag) != 0)
                    {
                        ThreadSchedState OldForcePauseFlags = ForcePauseFlags;

                        ForcePauseFlags &= ~ThreadSchedState.ForcePauseFlag;

                        if ((OldForcePauseFlags & ~ThreadSchedState.ForcePauseFlag) == ThreadSchedState.None)
                        {
                            ThreadSchedState OldSchedFlags = SchedFlags;

                            SchedFlags &= ThreadSchedState.LowNibbleMask;

                            AdjustScheduling(OldSchedFlags);
                        }
                    }
                    else
                    {
                        Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
                    }
                }
            }

            System.CriticalSectionLock.Unlock();
            System.CriticalSectionLock.Unlock();

            return(Result);
        }
Ejemplo n.º 17
0
        public KernelResult SetActivity(bool pause)
        {
            KernelResult result = KernelResult.Success;

            System.CriticalSection.Enter();

            ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask;

            if (lowNibble != ThreadSchedState.Paused && lowNibble != ThreadSchedState.Running)
            {
                System.CriticalSection.Leave();

                return(KernelResult.InvalidState);
            }

            System.CriticalSection.Enter();

            if (!ShallBeTerminated && SchedFlags != ThreadSchedState.TerminationPending)
            {
                if (pause)
                {
                    //Pause, the force pause flag should be clear (thread is NOT paused).
                    if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) == 0)
                    {
                        _forcePauseFlags |= ThreadSchedState.ThreadPauseFlag;

                        CombineForcePauseFlags();
                    }
                    else
                    {
                        result = KernelResult.InvalidState;
                    }
                }
                else
                {
                    //Unpause, the force pause flag should be set (thread is paused).
                    if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) != 0)
                    {
                        ThreadSchedState oldForcePauseFlags = _forcePauseFlags;

                        _forcePauseFlags &= ~ThreadSchedState.ThreadPauseFlag;

                        if ((oldForcePauseFlags & ~ThreadSchedState.ThreadPauseFlag) == ThreadSchedState.None)
                        {
                            ThreadSchedState oldSchedFlags = SchedFlags;

                            SchedFlags &= ThreadSchedState.LowMask;

                            AdjustScheduling(oldSchedFlags);
                        }
                    }
                    else
                    {
                        result = KernelResult.InvalidState;
                    }
                }
            }

            System.CriticalSection.Leave();
            System.CriticalSection.Leave();

            return(result);
        }