Exemplo n.º 1
0
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals queueThreadLocals = (ThreadPoolWorkQueueThreadLocals)null;

            if (!forceGlobal)
            {
                queueThreadLocals = ThreadPoolWorkQueueThreadLocals.threadLocals;
            }
            if (this.loggingEnabled)
            {
                FrameworkEventSource.Log.ThreadPoolEnqueueWorkObject((object)callback);
            }
            if (queueThreadLocals != null)
            {
                queueThreadLocals.workStealingQueue.LocalPush(callback);
            }
            else
            {
                ThreadPoolWorkQueue.QueueSegment comparand = this.queueHead;
                while (!comparand.TryEnqueue(callback))
                {
                    Interlocked.CompareExchange <ThreadPoolWorkQueue.QueueSegment>(ref comparand.Next, new ThreadPoolWorkQueue.QueueSegment(), (ThreadPoolWorkQueue.QueueSegment)null);
                    for (; comparand.Next != null; comparand = this.queueHead)
                    {
                        Interlocked.CompareExchange <ThreadPoolWorkQueue.QueueSegment>(ref this.queueHead, comparand.Next, comparand);
                    }
                }
            }
            this.EnsureThreadRequested();
        }
Exemplo n.º 2
0
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals threadLocals = null;

            if (!forceGlobal)
            {
                threadLocals = ThreadPoolWorkQueueThreadLocals.threadLocals;
            }
            if (threadLocals != null)
            {
                threadLocals.workStealingQueue.LocalPush(callback);
            }
            else
            {
                QueueSegment queueHead = this.queueHead;
                while (!queueHead.TryEnqueue(callback))
                {
                    Interlocked.CompareExchange <QueueSegment>(ref queueHead.Next, new QueueSegment(), null);
                    while (queueHead.Next != null)
                    {
                        Interlocked.CompareExchange <QueueSegment>(ref this.queueHead, queueHead.Next, queueHead);
                        queueHead = this.queueHead;
                    }
                }
            }
            this.EnsureThreadRequested();
        }
Exemplo n.º 3
0
        public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal)
        {
            callback    = null;
            missedSteal = false;
            WorkStealingQueue workStealingQueue = tl.workStealingQueue;

            workStealingQueue.LocalPop(out callback);
            if (callback == null)
            {
                for (QueueSegment segment = this.queueTail; (!segment.TryDequeue(out callback) && (segment.Next != null)) && segment.IsUsedUp(); segment = this.queueTail)
                {
                    Interlocked.CompareExchange <QueueSegment>(ref this.queueTail, segment.Next, segment);
                }
            }
            if (callback == null)
            {
                WorkStealingQueue[] current = allThreadQueues.Current;
                int num = tl.random.Next(current.Length);
                for (int i = current.Length; i > 0; i--)
                {
                    WorkStealingQueue queue2 = current[num % current.Length];
                    if (((queue2 != null) && (queue2 != workStealingQueue)) && queue2.TrySteal(out callback, ref missedSteal))
                    {
                        return;
                    }
                    num++;
                }
            }
        }
Exemplo n.º 4
0
        public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal)
        {
            callback    = (IThreadPoolWorkItem)null;
            missedSteal = false;
            ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue1 = tl.workStealingQueue;
            workStealingQueue1.LocalPop(out callback);
            if (callback == null)
            {
                for (ThreadPoolWorkQueue.QueueSegment comparand = this.queueTail; !comparand.TryDequeue(out callback) && comparand.Next != null && comparand.IsUsedUp(); comparand = this.queueTail)
                {
                    Interlocked.CompareExchange <ThreadPoolWorkQueue.QueueSegment>(ref this.queueTail, comparand.Next, comparand);
                }
            }
            if (callback != null)
            {
                return;
            }
            ThreadPoolWorkQueue.WorkStealingQueue[] current = ThreadPoolWorkQueue.allThreadQueues.Current;
            int num = tl.random.Next(current.Length);

            for (int length = current.Length; length > 0; --length)
            {
                ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue2 = Volatile.Read <ThreadPoolWorkQueue.WorkStealingQueue>(ref current[num % current.Length]);
                if (workStealingQueue2 != null && workStealingQueue2 != workStealingQueue1 && workStealingQueue2.TrySteal(out callback, ref missedSteal))
                {
                    break;
                }
                ++num;
            }
        }
Exemplo n.º 5
0
        public IThreadPoolWorkItem Dequeue(ThreadPoolWorkQueueThreadLocals tl, ref bool missedSteal)
        {
            WorkStealingQueue   localWsq = tl.workStealingQueue;
            IThreadPoolWorkItem callback;

            if ((callback = localWsq.LocalPop()) == null && // first try the local queue
                !workItems.TryDequeue(out callback))        // then try the global queue
            {
                // finally try to steal from another thread's local queue
                WorkStealingQueue[] queues = WorkStealingQueueList.Queues;
                int c = queues.Length;
                Debug.Assert(c > 0, "There must at least be a queue for this thread.");
                int maxIndex = c - 1;
                int i        = tl.random.Next(c);
                while (c > 0)
                {
                    i = (i < maxIndex) ? i + 1 : 0;
                    WorkStealingQueue otherQueue = queues[i];
                    if (otherQueue != localWsq && otherQueue.CanSteal)
                    {
                        callback = otherQueue.TrySteal(ref missedSteal);
                        if (callback != null)
                        {
                            break;
                        }
                    }
                    c--;
                }
            }

            return(callback);
        }
Exemplo n.º 6
0
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals tl = null;

            if (!forceGlobal)
            {
                tl = ThreadPoolWorkQueueThreadLocals.threadLocals;
            }

            if (null != tl)
            {
                tl.workStealingQueue.LocalPush(callback);

                // We must guarantee wsqActive is set to WsqNowActive after we push
                // The ordering must be global because we rely on other threads
                // observing in this order
                Interlocked.MemoryBarrier();

                // We do not want to simply write.  We want to prevent unnecessary writes
                // which would invalidate reader's caches
                if (WorkStealingQueueList.wsqActive != WorkStealingQueueList.WsqNowActive)
                {
                    Volatile.Write(ref WorkStealingQueueList.wsqActive, WorkStealingQueueList.WsqNowActive);
                }
            }
            else
            {
                workItems.Enqueue(callback);
            }

            EnsureThreadRequested();
        }
Exemplo n.º 7
0
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals tl = null;

            if (!forceGlobal)
            {
                tl = ThreadPoolWorkQueueThreadLocals.Current;
            }

            if (null != tl)
            {
                tl.workStealingQueue.LocalPush(callback);
            }
            else
            {
                QueueSegment head = queueHead;

                while (!head.TryEnqueue(callback))
                {
                    Interlocked.CompareExchange(ref head.Next, new QueueSegment(), null);

                    while (head.Next != null)
                    {
                        Interlocked.CompareExchange(ref queueHead, head.Next, head);
                        head = queueHead;
                    }
                }
            }

            EnsureThreadRequested();
        }
 public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal)
 {
     callback    = null;
     missedSteal = false;
     ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue = tl.workStealingQueue;
     workStealingQueue.LocalPop(out callback);
     if (callback == null)
     {
         ThreadPoolWorkQueue.QueueSegment queueSegment = this.queueTail;
         while (!queueSegment.TryDequeue(out callback) && queueSegment.Next != null && queueSegment.IsUsedUp())
         {
             Interlocked.CompareExchange <ThreadPoolWorkQueue.QueueSegment>(ref this.queueTail, queueSegment.Next, queueSegment);
             queueSegment = this.queueTail;
         }
     }
     if (callback == null)
     {
         ThreadPoolWorkQueue.WorkStealingQueue[] array = ThreadPoolWorkQueue.allThreadQueues.Current;
         int num = tl.random.Next(array.Length);
         for (int i = array.Length; i > 0; i--)
         {
             ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue2 = Volatile.Read <ThreadPoolWorkQueue.WorkStealingQueue>(ref array[num % array.Length]);
             if (workStealingQueue2 != null && workStealingQueue2 != workStealingQueue && workStealingQueue2.TrySteal(out callback, ref missedSteal))
             {
                 break;
             }
             num++;
         }
     }
 }
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals threadPoolWorkQueueThreadLocals = null;

            if (!forceGlobal)
            {
                threadPoolWorkQueueThreadLocals = ThreadPoolWorkQueueThreadLocals.threadLocals;
            }
            if (this.loggingEnabled)
            {
                FrameworkEventSource.Log.ThreadPoolEnqueueWorkObject(callback);
            }
            if (threadPoolWorkQueueThreadLocals != null)
            {
                threadPoolWorkQueueThreadLocals.workStealingQueue.LocalPush(callback);
            }
            else
            {
                ThreadPoolWorkQueue.QueueSegment queueSegment = this.queueHead;
                while (!queueSegment.TryEnqueue(callback))
                {
                    Interlocked.CompareExchange <ThreadPoolWorkQueue.QueueSegment>(ref queueSegment.Next, new ThreadPoolWorkQueue.QueueSegment(), null);
                    while (queueSegment.Next != null)
                    {
                        Interlocked.CompareExchange <ThreadPoolWorkQueue.QueueSegment>(ref this.queueHead, queueSegment.Next, queueSegment);
                        queueSegment = this.queueHead;
                    }
                }
            }
            this.EnsureThreadRequested();
        }
Exemplo n.º 10
0
        public IThreadPoolWorkItem Dequeue(ThreadPoolWorkQueueThreadLocals tl, ref bool missedSteal)
        {
            IThreadPoolWorkItem callback;
            int wsqActiveObserved = WorkStealingQueueList.wsqActive;

            if (wsqActiveObserved > 0)
            {
                WorkStealingQueue localWsq = tl.workStealingQueue;

                if ((callback = localWsq.LocalPop()) == null && // first try the local queue
                    !workItems.TryDequeue(out callback))        // then try the global queue
                {
                    // finally try to steal from another thread's local queue
                    WorkStealingQueue[] queues = WorkStealingQueueList.Queues;
                    int c = queues.Length;
                    Debug.Assert(c > 0, "There must at least be a queue for this thread.");
                    int maxIndex = c - 1;
                    int i        = tl.random.Next(c);
                    while (c > 0)
                    {
                        i = (i < maxIndex) ? i + 1 : 0;
                        WorkStealingQueue otherQueue = queues[i];
                        if (otherQueue != localWsq && otherQueue.CanSteal)
                        {
                            callback = otherQueue.TrySteal(ref missedSteal);
                            if (callback != null)
                            {
                                break;
                            }
                        }
                        c--;
                    }
                    if ((callback == null) && !missedSteal)
                    {
                        // Only decrement if the value is unchanged since we started looking for work
                        // This prevents multiple threads decrementing based on overlapping scans.
                        //
                        // When we decrement from active, the producer may have inserted a queue item during our scan
                        // therefore we cannot transition to empty
                        //
                        // When we decrement from Maybe Inactive, if the producer inserted a queue item during our scan,
                        // the producer must write Active.  We may transition to empty briefly if we beat the
                        // producer's write, but the producer will then overwrite us before waking threads.
                        // So effectively we cannot mark the queue empty when an item is in the queue.
                        Interlocked.CompareExchange(ref WorkStealingQueueList.wsqActive, wsqActiveObserved - 1, wsqActiveObserved);
                    }
                }
            }
            else
            {
                // We only need to look at the global queue since WorkStealingQueueList is inactive
                workItems.TryDequeue(out callback);
            }

            return(callback);
        }
Exemplo n.º 11
0
        internal bool LocalFindAndPop(IThreadPoolWorkItem callback)
        {
            ThreadPoolWorkQueueThreadLocals queueThreadLocals = ThreadPoolWorkQueueThreadLocals.threadLocals;

            if (queueThreadLocals == null)
            {
                return(false);
            }
            return(queueThreadLocals.workStealingQueue.LocalFindAndPop(callback));
        }
Exemplo n.º 12
0
        public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal)
        {
            callback    = null;
            missedSteal = false;
            WorkStealingQueue wsq = tl.workStealingQueue;

            if (wsq.LocalPop(out callback))
            {
                Debug.Assert(null != callback);
            }

            if (null == callback)
            {
                QueueSegment tail = queueTail;
                while (true)
                {
                    if (tail.TryDequeue(out callback))
                    {
                        Debug.Assert(null != callback);
                        break;
                    }

                    if (null == tail.Next || !tail.IsUsedUp())
                    {
                        break;
                    }
                    else
                    {
                        Interlocked.CompareExchange(ref queueTail, tail.Next, tail);
                        tail = queueTail;
                    }
                }
            }

            if (null == callback)
            {
                WorkStealingQueue[] otherQueues = allThreadQueues.Current;
                int i = tl.random.Next(otherQueues.Length);
                int c = otherQueues.Length;
                while (c > 0)
                {
                    WorkStealingQueue otherQueue = Volatile.Read(ref otherQueues[i % otherQueues.Length]);
                    if (otherQueue != null &&
                        otherQueue != wsq &&
                        otherQueue.TrySteal(out callback, ref missedSteal))
                    {
                        Debug.Assert(null != callback);
                        break;
                    }
                    i++;
                    c--;
                }
            }
        }
Exemplo n.º 13
0
        internal bool LocalFindAndPop(IThreadPoolWorkItem callback)
        {
            ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.Current;

            if (null == tl)
            {
                return(false);
            }

            return(tl.workStealingQueue.LocalFindAndPop(callback));
        }
Exemplo n.º 14
0
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals tl = null;

            if (!forceGlobal)
            {
                tl = ThreadPoolWorkQueueThreadLocals.threadLocals;
            }

            if (null != tl)
            {
                tl.workStealingQueue.LocalPush(callback);
            }
            else
            {
                workItems.Enqueue(callback);
            }

            EnsureThreadRequested();
        }
Exemplo n.º 15
0
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
        {
            ThreadPoolWorkQueueThreadLocals tl = null;

            if (!forceGlobal)
            {
                tl = ThreadPoolWorkQueueThreadLocals.Current;
            }

#if !FEATURE_CORECLR
            //if (loggingEnabled)
            //    System.Diagnostics.Tracing.FrameworkEventSource.Log.ThreadPoolEnqueueWorkObject(callback);
#endif

            if (null != tl)
            {
                tl.workStealingQueue.LocalPush(callback);
            }
            else
            {
                QueueSegment head = queueHead;

                while (!head.TryEnqueue(callback))
                {
                    Interlocked.CompareExchange(ref head.Next, new QueueSegment(), null);

                    while (head.Next != null)
                    {
                        Interlocked.CompareExchange(ref queueHead, head.Next, head);
                        head = queueHead;
                    }
                }
            }

            EnsureThreadRequested();
        }
Exemplo n.º 16
0
        /// <summary>
        /// Dispatches work items to this thread.
        /// </summary>
        /// <returns>
        /// <c>true</c> if this thread did as much work as was available or its quantum expired.
        /// <c>false</c> if this thread stopped working early.
        /// </returns>
        internal static bool Dispatch()
        {
            var workQueue = ThreadPoolGlobals.workQueue;

            //
            // Save the start time
            //
            int startTickCount = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            workQueue.MarkThreadRequestSatisfied();

            Interlocked.Increment(ref workQueue.numWorkingThreads);

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool needAnotherThread       = true;
            IThreadPoolWorkItem workItem = null;

            try
            {
                //
                // Set up our thread-local data
                //
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires or there is no work.
                //
                while (ThreadPool.KeepDispatching(startTickCount))
                {
                    bool missedSteal = false;
                    workItem = workQueue.Dequeue(tl, ref missedSteal);

                    if (workItem == null)
                    {
                        //
                        // No work.
                        // If we missed a steal, though, there may be more work in the queue.
                        // Instead of looping around and trying again, we'll just request another thread.  Hopefully the thread
                        // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                        // which will be more efficient than this thread doing it anyway.
                        //
                        needAnotherThread = missedSteal;

                        // Tell the VM we're returning normally, not because Hill Climbing asked us to return.
                        return(true);
                    }

                    //
                    // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                    // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                    //
                    workQueue.EnsureThreadRequested();

                    try
                    {
                        SynchronizationContext.SetSynchronizationContext(null);
                        workItem.ExecuteWorkItem();
                    }
                    finally
                    {
                        workItem = null;
                        SynchronizationContext.SetSynchronizationContext(null);
                    }

                    RuntimeThread.CurrentThread.ResetThreadPoolThread();

                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }

                // If we get here, it's because our quantum expired.
                return(true);
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
                return(true); // Will never actually be executed because Environment.FailFast doesn't return
            }
            finally
            {
                int numWorkers = Interlocked.Decrement(ref workQueue.numWorkingThreads);
                Debug.Assert(numWorkers >= 0);

                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
        }
Exemplo n.º 17
0
        internal bool LocalFindAndPop(IThreadPoolWorkItem callback)
        {
            ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.threadLocals;

            return(tl != null && tl.workStealingQueue.LocalFindAndPop(callback));
        }
Exemplo n.º 18
0
        internal static bool Dispatch()
        {
            ThreadPoolWorkQueue threadPoolWorkQueue = ThreadPoolGlobals.workQueue;
            int tickCount = Environment.TickCount;

            threadPoolWorkQueue.MarkThreadRequestSatisfied();
            threadPoolWorkQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, (EventKeywords)18);
            bool flag1 = true;
            IThreadPoolWorkItem callback = (IThreadPoolWorkItem)null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = threadPoolWorkQueue.EnsureCurrentThreadHasQueue();
                while ((long)(Environment.TickCount - tickCount) < (long)ThreadPoolGlobals.tpQuantum)
                {
                    try
                    {
                    }
                    finally
                    {
                        bool missedSteal = false;
                        threadPoolWorkQueue.Dequeue(tl, out callback, out missedSteal);
                        if (callback == null)
                        {
                            flag1 = missedSteal;
                        }
                        else
                        {
                            threadPoolWorkQueue.EnsureThreadRequested();
                        }
                    }
                    if (callback == null)
                    {
                        return(true);
                    }
                    if (threadPoolWorkQueue.loggingEnabled)
                    {
                        FrameworkEventSource.Log.ThreadPoolDequeueWorkObject((object)callback);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag2 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag2 = true;
                            }
                            callback.ExecuteWorkItem();
                            callback = (IThreadPoolWorkItem)null;
                        }
                        finally
                        {
                            if (flag2)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                    }
                    else
                    {
                        callback.ExecuteWorkItem();
                        callback = (IThreadPoolWorkItem)null;
                    }
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }
                return(true);
            }
            catch (ThreadAbortException ex)
            {
                if (callback != null)
                {
                    callback.MarkAborted(ex);
                }
                flag1 = false;
            }
            finally
            {
                if (flag1)
                {
                    threadPoolWorkQueue.EnsureThreadRequested();
                }
            }
            return(true);
        }
Exemplo n.º 19
0
        static internal void Dispatch()
        {
            var workQueue = ThreadPoolGlobals.workQueue;

            //
            // The clock is ticking!  We have ThreadPoolGlobals.tpQuantum milliseconds to get some work done, and then
            // we need to return to the VM.
            //
            int quantumStartTime = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            // Note that if this thread is aborted before we get a chance to request another one, the VM will
            // record a thread request on our behalf.  So we don't need to worry about getting aborted right here.
            //
            workQueue.MarkThreadRequestSatisfied();

#if !FEATURE_CORECLR
            // Has the desire for logging changed since the last time we entered?
            //workQueue.loggingEnabled = System.Diagnostics.Tracing.FrameworkEventSource.Log.IsEnabled(System.Diagnostics.Tracing.EventLevel.Verbose, System.Diagnostics.Tracing.FrameworkEventSource.Keywords.ThreadPool);
#endif

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool needAnotherThread       = true;
            IThreadPoolWorkItem workItem = null;
            try
            {
                //
                // Set up our thread-local data
                //
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires.
                //
                while ((Environment.TickCount - quantumStartTime) < tpQuantum)
                {
                    //
                    // Dequeue and EnsureThreadRequested must be protected from ThreadAbortException.
                    // These are fast, so this will not delay aborts/AD-unloads for very long.
                    //
                    try { }
                    finally
                    {
                        bool missedSteal = false;
                        workQueue.Dequeue(tl, out workItem, out missedSteal);

                        if (workItem == null)
                        {
                            //
                            // No work.  We're going to return to the VM once we leave this protected region.
                            // If we missed a steal, though, there may be more work in the queue.
                            // Instead of looping around and trying again, we'll just request another thread.  This way
                            // we won't starve other AppDomains while we spin trying to get locks, and hopefully the thread
                            // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                            // which will be more efficient than this thread doing it anyway.
                            //
                            needAnotherThread = missedSteal;
                        }
                        else
                        {
                            //
                            // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                            // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                            //
                            workQueue.EnsureThreadRequested();
                        }
                    }

                    if (workItem == null)
                    {
                        // no more work to do
                        return;
                    }
                    else
                    {
#if !FEATURE_CORECLR
                        //if (workQueue.loggingEnabled)
                        //    System.Diagnostics.Tracing.FrameworkEventSource.Log.ThreadPoolDequeueWorkObject(workItem);
#endif

                        //
                        // Execute the workitem outside of any finally blocks, so that it can be aborted if needed.
                        //
                        //RuntimeHelpers.PrepareConstrainedRegions();
                        try
                        {
                            SynchronizationContext.SetSynchronizationContext(null);
                            workItem.ExecuteWorkItem();
                        }
                        finally
                        {
                            workItem = null;
                            SynchronizationContext.SetSynchronizationContext(null);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
            }
            finally
            {
                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
        }
        internal static bool Dispatch()
        {
            ThreadPoolWorkQueue workQueue = ThreadPoolGlobals.workQueue;
            int tickCount = Environment.TickCount;

            workQueue.MarkThreadRequestSatisfied();
            workQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, (EventKeywords)18L);
            bool flag = true;
            IThreadPoolWorkItem threadPoolWorkItem = null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();
                while ((long)(Environment.TickCount - tickCount) < (long)((ulong)ThreadPoolGlobals.tpQuantum))
                {
                    try
                    {
                    }
                    finally
                    {
                        bool flag2 = false;
                        workQueue.Dequeue(tl, out threadPoolWorkItem, out flag2);
                        if (threadPoolWorkItem == null)
                        {
                            flag = flag2;
                        }
                        else
                        {
                            workQueue.EnsureThreadRequested();
                        }
                    }
                    if (threadPoolWorkItem == null)
                    {
                        return(true);
                    }
                    if (workQueue.loggingEnabled)
                    {
                        FrameworkEventSource.Log.ThreadPoolDequeueWorkObject(threadPoolWorkItem);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag3 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag3 = true;
                            }
                            threadPoolWorkItem.ExecuteWorkItem();
                            threadPoolWorkItem = null;
                            goto IL_A6;
                        }
                        finally
                        {
                            if (flag3)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                        goto IL_9E;
                    }
                    goto IL_9E;
IL_A6:
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                    continue;
IL_9E:
                    threadPoolWorkItem.ExecuteWorkItem();
                    threadPoolWorkItem = null;
                    goto IL_A6;
                }
                return(true);
            }
            catch (ThreadAbortException tae)
            {
                if (threadPoolWorkItem != null)
                {
                    threadPoolWorkItem.MarkAborted(tae);
                }
                flag = false;
            }
            finally
            {
                if (flag)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
            return(true);
        }
Exemplo n.º 21
0
        internal static void Dispatch()
        {
            var workQueue = ThreadPoolGlobals.workQueue;

            //
            // The clock is ticking!  We have ThreadPoolGlobals.tpQuantum milliseconds to get some work done, and then
            // we need to return to the VM.
            //
            int quantumStartTime = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            workQueue.MarkThreadRequestSatisfied();

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool needAnotherThread       = true;
            IThreadPoolWorkItem workItem = null;

            try
            {
                //
                // Set up our thread-local data
                //
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires.
                //
                while ((Environment.TickCount - quantumStartTime) < tpQuantum)
                {
                    bool missedSteal = false;
                    workQueue.Dequeue(tl, out workItem, out missedSteal);

                    if (workItem == null)
                    {
                        //
                        // No work.  We're going to return to the VM once we leave this protected region.
                        // If we missed a steal, though, there may be more work in the queue.
                        // Instead of looping around and trying again, we'll just request another thread.  This way
                        // we won't starve other AppDomains while we spin trying to get locks, and hopefully the thread
                        // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                        // which will be more efficient than this thread doing it anyway.
                        //
                        needAnotherThread = missedSteal;
                        return;
                    }

                    //
                    // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                    // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                    //
                    workQueue.EnsureThreadRequested();

                    try
                    {
                        SynchronizationContext.SetSynchronizationContext(null);
                        workItem.ExecuteWorkItem();
                    }
                    finally
                    {
                        workItem = null;
                        SynchronizationContext.SetSynchronizationContext(null);
                    }
                }
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
            }
            finally
            {
                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
        }
Exemplo n.º 22
0
        internal static bool Dispatch()
        {
            bool flag4;
            int  tickCount = Environment.TickCount;

            ThreadPoolGlobals.workQueue.MarkThreadRequestSatisfied();
            bool flag = true;
            IThreadPoolWorkItem callback = null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = ThreadPoolGlobals.workQueue.EnsureCurrentThreadHasQueue();
                while ((Environment.TickCount - tickCount) < ThreadPoolGlobals.tpQuantum)
                {
                    try
                    {
                    }
                    finally
                    {
                        bool missedSteal = false;
                        ThreadPoolGlobals.workQueue.Dequeue(tl, out callback, out missedSteal);
                        if (callback == null)
                        {
                            flag = missedSteal;
                        }
                        else
                        {
                            ThreadPoolGlobals.workQueue.EnsureThreadRequested();
                        }
                    }
                    if (callback == null)
                    {
                        return(true);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag3 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag3 = true;
                            }
                            callback.ExecuteWorkItem();
                            callback = null;
                        }
                        finally
                        {
                            if (flag3)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                    }
                    else
                    {
                        callback.ExecuteWorkItem();
                        callback = null;
                    }
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }
                flag4 = true;
            }
            catch (ThreadAbortException exception)
            {
                if (callback != null)
                {
                    callback.MarkAborted(exception);
                }
                flag = false;
                throw;
            }
            finally
            {
                if (flag)
                {
                    ThreadPoolGlobals.workQueue.EnsureThreadRequested();
                }
            }
            return(flag4);
        }