Пример #1
0
        public override void AddRunnableThread(Thread thread)
        {
            ThreadState newState;

            // Change thread's state to runnable: Runpolicy will decide latter on
            // if it can actually run the thread
            newState = thread.ChangeSchedulerState(ThreadState.Runnable);

            // Add thread to runnable queue only if new state is runnable
            if (newState == ThreadState.Runnable)
            {
                // While we adding a thread to runnable queue someone could have called freeze on
                // it again - RunPolicy will notice it and remove thread from runnable queue appropriatly

                this.unblockedThreads.EnqueueTail(thread.schedulerEntry);
            }
        }
Пример #2
0
        public override Thread RunPolicy(
            int affinity,
            Thread currentThread,
            ThreadState schedulerAction,
            SchedulerTime currentTime)
        {
            Thread      threadToReturn = null;
            ThreadState newState       = ThreadState.Undefined;
            ThreadEntry entry          = null;

            // Put current thread on a runnable queue only if it is currently in a running state
            if (currentThread != null)
            {
                // At this point current threads state has to be
                // running - when running derived scheduler state we will deduce new state
                // but until then it has to be running
                VTable.Assert(currentThread.ThreadState == ThreadState.Running);

                // If scheduler action is running make it runnable to have proper state transition
                // Currently we disallow to go from running to running
                if (schedulerAction == ThreadState.Running)
                {
                    schedulerAction = ThreadState.Runnable;
                }

                // Change current's thread new scheudler state
                newState = currentThread.ChangeSchedulerState(schedulerAction);

                // If new state is runnable add it to runnable queue
                if (newState == ThreadState.Runnable)
                {
                    // REVIEW: Should we make sure the thread is enqueue already?

                    // Indicate that thread has been marked as runnable
                    this.runnableThreads.EnqueueTail(currentThread.schedulerEntry);
                }
            }

            // Derived state of entry on the runnable queue can be either suspended or runnable.
            // Consequently first we remove an entry from the queue. If it is runnable,
            // we will be able to convert it to running, If it is suspended,
            // we will convert its real state to suspended. The first thread that marks the entry
            // unsuspended will be responsible for putting it on back on a runnable queue.

            // Check the unblocked queue first.
            while ((entry = this.unblockedThreads.DequeueHead()) != null)
            {
                // At this point thread direct state can be only runnable...
                VTable.Assert(entry.Thread.IsRunnable);

                // Attempt to make thread running
                newState = entry.Thread.ChangeSchedulerState(ThreadState.Running);

                // Get of the loop if we marked one of the entries as running
                if (newState == ThreadState.Running)
                {
                    break;
                }

                // If the thread is suspended, then look for another.
                VTable.Assert(newState == ThreadState.Suspended);
            }

            // If no recently unblocked threads, then check the runnable queue.
            if (entry == null)
            {
                while ((entry = this.runnableThreads.DequeueHead()) != null)
                {
                    // At this point thread direct state can be only runnable...
                    VTable.Assert(entry.Thread.IsRunnable);

                    // Attempt to make thread running
                    newState = entry.Thread.ChangeSchedulerState(ThreadState.Running);

                    // Get of the loop if we marked one of the entries as running
                    if (newState == ThreadState.Running)
                    {
                        break;
                    }

                    // If the thread is suspended, then look for another.
                    VTable.Assert(newState == ThreadState.Suspended);
                }
            }

            // We got an entry from the runnable queue that we can actually run.
            if (entry != null)
            {
                // Thread must realy by in the running state.
                VTable.Assert(newState == ThreadState.Running);

                // Initialize thread we about to return.
                threadToReturn          = entry.Thread;
                threadToReturn.Affinity = affinity;
            }

            return(threadToReturn);
        }