Beispiel #1
0
        public void YieldWithLoadBalancing()
        {
            if (YieldCount == Owner.YieldCounter)
            {
                return;
            }

            int Prio = DynamicPriority;
            int Core = CurrentCore;

            System.CriticalSectionLock.Lock();

            if (SchedFlags != ThreadSchedState.Running)
            {
                System.CriticalSectionLock.Unlock();

                System.Scheduler.ContextSwitch();

                return;
            }

            KThread NextThreadOnCurrentQueue = null;

            if (DynamicPriority < KScheduler.PrioritiesCount)
            {
                //Move current thread to the end of the queue.
                SchedulingData.Reschedule(Prio, Core, this);

                NextThreadOnCurrentQueue = SchedulingData.ScheduledThreadsPerPrioPerCore[Prio][Core].First?.Value;
            }

            if (Owner != null)
            {
                Owner.YieldCounter++;
            }

            foreach (KThread Thread in SchedulingData.SuggestedThreads(Core))
            {
                KThread SelectedOnCandidateCore = null;

                if (Thread.CurrentCore >= 0)
                {
                    SelectedOnCandidateCore = Scheduler.CoreContexts[Thread.CurrentCore].SelectedThread;
                }

                if (Thread == SelectedOnCandidateCore)
                {
                    continue;
                }

                if (this != NextThreadOnCurrentQueue)
                {
                    //If the candidate has lower priority than the current thread,
                    //or the priority is the same, but it was already scheduled
                    //after the next thread on the queue, then it's not worth to run
                    //it, as the next thread on the queue is already a better candidate.
                    if (Thread.DynamicPriority > DynamicPriority ||
                        (Thread.DynamicPriority == DynamicPriority &&
                         Thread.LastScheduledTicks > NextThreadOnCurrentQueue.LastScheduledTicks))
                    {
                        break;
                    }
                }
                else if (Thread.DynamicPriority > DynamicPriority)
                {
                    break;
                }

                if (SelectedOnCandidateCore == null || SelectedOnCandidateCore.DynamicPriority >= 2)
                {
                    SchedulingData.MoveTo(Thread.DynamicPriority, Core, Thread);

                    Scheduler.ThreadReselectionRequested = true;

                    if (Thread.Owner != null)
                    {
                        Thread.Owner.YieldCounter++;
                    }

                    break;
                }
            }

            if (this != NextThreadOnCurrentQueue)
            {
                Scheduler.ThreadReselectionRequested = true;
            }
            else
            {
                YieldCount = Owner.YieldCounter;
            }

            System.CriticalSectionLock.Unlock();

            System.Scheduler.ContextSwitch();
        }
Beispiel #2
0
        public void YieldWithLoadBalancing()
        {
            int Prio = DynamicPriority;
            int Core = CurrentCore;

            System.CriticalSectionLock.Lock();

            if (SchedFlags != ThreadSchedState.Running)
            {
                System.CriticalSectionLock.Unlock();

                System.Scheduler.ContextSwitch();

                return;
            }

            KThread NextThreadOnCurrentQueue = null;

            if (DynamicPriority < KScheduler.PrioritiesCount)
            {
                //Move current thread to the end of the queue.
                SchedulingData.Reschedule(Prio, Core, this);

                Func <KThread, bool> Predicate = x => x.DynamicPriority == Prio;

                NextThreadOnCurrentQueue = SchedulingData.ScheduledThreads(Core).FirstOrDefault(Predicate);
            }

            IEnumerable <KThread> SuitableCandidates()
            {
                foreach (KThread Thread in SchedulingData.SuggestedThreads(Core))
                {
                    int SrcCore = Thread.CurrentCore;

                    if (SrcCore >= 0)
                    {
                        KThread SelectedSrcCore = Scheduler.CoreContexts[SrcCore].SelectedThread;

                        if (SelectedSrcCore == Thread || ((SelectedSrcCore?.DynamicPriority ?? 2) < 2))
                        {
                            continue;
                        }
                    }

                    //If the candidate was scheduled after the current thread, then it's not worth it,
                    //unless the priority is higher than the current one.
                    if (NextThreadOnCurrentQueue.LastScheduledTicks >= Thread.LastScheduledTicks ||
                        NextThreadOnCurrentQueue.DynamicPriority < Thread.DynamicPriority)
                    {
                        yield return(Thread);
                    }
                }
            }

            KThread Dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority <= Prio);

            if (Dst != null)
            {
                SchedulingData.TransferToCore(Dst.DynamicPriority, Core, Dst);

                Scheduler.ThreadReselectionRequested = true;
            }

            if (this != NextThreadOnCurrentQueue)
            {
                Scheduler.ThreadReselectionRequested = true;
            }

            System.CriticalSectionLock.Unlock();

            System.Scheduler.ContextSwitch();
        }
Beispiel #3
0
        public void YieldWithLoadBalancing()
        {
            System.CriticalSection.Enter();

            if (SchedFlags != ThreadSchedState.Running)
            {
                System.CriticalSection.Leave();

                System.Scheduler.ContextSwitch();

                return;
            }

            int prio = DynamicPriority;
            int core = CurrentCore;

            KThread nextThreadOnCurrentQueue = null;

            if (DynamicPriority < KScheduler.PrioritiesCount)
            {
                //Move current thread to the end of the queue.
                _schedulingData.Reschedule(prio, core, this);

                Func <KThread, bool> predicate = x => x.DynamicPriority == prio;

                nextThreadOnCurrentQueue = _schedulingData.ScheduledThreads(core).FirstOrDefault(predicate);
            }

            IEnumerable <KThread> SuitableCandidates()
            {
                foreach (KThread thread in _schedulingData.SuggestedThreads(core))
                {
                    int srcCore = thread.CurrentCore;

                    if (srcCore >= 0)
                    {
                        KThread selectedSrcCore = _scheduler.CoreContexts[srcCore].SelectedThread;

                        if (selectedSrcCore == thread || ((selectedSrcCore?.DynamicPriority ?? 2) < 2))
                        {
                            continue;
                        }
                    }

                    //If the candidate was scheduled after the current thread, then it's not worth it,
                    //unless the priority is higher than the current one.
                    if (nextThreadOnCurrentQueue.LastScheduledTime >= thread.LastScheduledTime ||
                        nextThreadOnCurrentQueue.DynamicPriority < thread.DynamicPriority)
                    {
                        yield return(thread);
                    }
                }
            }

            KThread dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority <= prio);

            if (dst != null)
            {
                _schedulingData.TransferToCore(dst.DynamicPriority, core, dst);

                _scheduler.ThreadReselectionRequested = true;
            }

            if (this != nextThreadOnCurrentQueue)
            {
                _scheduler.ThreadReselectionRequested = true;
            }

            System.CriticalSection.Leave();

            System.Scheduler.ContextSwitch();
        }