public void DequeueAll(ThreadQueue newParentQueue) { ThreadEntry threadEntry = head; // Navigate through all elements and set the queue to the new queue while (threadEntry != null) { threadEntry.queue = newParentQueue; threadEntry = threadEntry.next; } // Move queue elements to parent queue if (newParentQueue.tail != null) { // If new parent queue is not empty enqueue new elements at the end of the // new parent queue newParentQueue.tail.next = this.head; newParentQueue.tail = this.tail; } else { // New queue is empty update head and tail newParentQueue.head = this.head; newParentQueue.tail = this.tail; } // Reset initial queue this.head = null; this.tail = null; return; }
public void Remove(ThreadEntry entry) { if (entry.next != null) { entry.next.prev = entry.prev; } else { VTable.Assert(entry == tail); tail = entry.prev; } if (entry.prev != null) { entry.prev.next = entry.next; } else { VTable.Assert(entry == head); head = entry.next; } entry.next = null; entry.prev = null; entry.queue = null; }
public Thread DequeueTailThread() { ThreadEntry entry = DequeueTail(); if (entry != null) { return(entry.Thread); } return(null); }
public ThreadEntry GetNext() { ThreadEntry entryToReturn = this.current; if (this.current != null) { current = current.next; } return(entryToReturn); }
public ThreadEntry DequeueTail() { ThreadEntry entry = tail; if (entry != null) { Remove(entry); return(entry); } else { return(null); } }
public ThreadEntry DequeueHead() { ThreadEntry entry = head; if (entry != null) { Remove(entry); return(entry); } else { return(null); } }
public void EnqueueHead(ThreadEntry entry) { VTable.Assert(entry.next == null); VTable.Assert(entry.prev == null); VTable.Assert(entry.queue == null); entry.next = head; if (head != null) { VTable.Assert(head.prev == null); head.prev = entry; } else { VTable.Assert(tail == null); tail = entry; } head = entry; }
public void EnqueueTail(ThreadEntry entry) { VTable.Assert(entry.next == null); VTable.Assert(entry.prev == null); VTable.Assert(entry.queue == null); entry.prev = this.tail; if (tail != null) { VTable.Assert(tail.next == null); tail.next = entry; } else { VTable.Assert(head == null); head = entry; } tail = entry; }
public void InsertBefore(ThreadEntry position, ThreadEntry entry) { if (position == null) { EnqueueTail(entry); } else if (position == head) { EnqueueHead(entry); } else { VTable.Assert(head != null); VTable.Assert(entry.queue == null); entry.queue = this; entry.prev = position.prev; entry.next = position; position.prev = entry; entry.prev.next = entry; } }
private void EnqueueTimer(Thread thread, SchedulerTime stop) { // For now disable interrupts and acquire scheduler lock... bool shouldEnable = Processor.DisableInterrupts(); int unblockedBy; SchedulerTime now = SchedulerTime.Now; TimeSpan delta = stop - now; //Acquire scheduler lock: this.timerLock.Acquire(); // Find out if we need to update alarm. bool shouldChangeAlarm = ((this.timerThreads.Head == null) || (this.timerThreads.Head.Thread.blockedUntil > stop)); // If new wait already expired just try to fail it right a way. Alarm upate // indicates that only this new wait can be retired if (shouldChangeAlarm && stop <= now) { unblockedBy = thread.Unblock(WaitHandle.WaitTimeout); // We no longer should be changing alarm shouldChangeAlarm = false; // if we unblocked by timer or by someone else we don't have to anything - // OnThreadBlock will adjust thread's state accordingly. For more info see // OnThreadBlock, Dispatcher.ContextSwitch and RunPolicy } else { // Enqueue thread in the right place ThreadEntry entry = this.timerThreads.Head; while (entry != null && entry.Thread.blockedUntil <= stop) { // Loop until we find the first thread with a later stop. entry = entry.Next; } // Store thread's block until information thread.blockedUntil = stop; // Found the right place go ahead and put the thread into the queue this.timerThreads.InsertBefore(entry, thread.timerEntry); } // Before we let others to party on a timer check if timer has to be reset: // and if so rember it and reset once we release the lock if (shouldChangeAlarm && this.nextTimer > stop) { this.nextTimer = stop; } else { shouldChangeAlarm = false; } // Release timer lock this.timerLock.Release(); // If we are required to set a time on dispatcher, do it outside of // spinlock since nobody is currently can be running on our processor // since we have interrupts disabled. if (shouldChangeAlarm) { Processor.CurrentProcessor.SetNextTimerInterrupt(delta); } // Re-enable interrupts Processor.RestoreInterrupts(shouldEnable); }
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); }
public bool IsEnqueued(ThreadEntry entry) { return(entry.queue == this); }
public ThreadEntryEnum(ThreadEntry entry) { this.current = entry; }
public ThreadQueue(WaitHandleBase handle) { this.head = null; this.tail = null; this.handle = handle; }
public ThreadQueue() { this.head = null; this.tail = null; this.handle = null; }