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;
            }
        }
Exemple #10
0
        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);
        }
Exemple #11
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);
        }
 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;
 }