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