ThreadPool.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / ThreadPool.cs / 1305376 / ThreadPool.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//
// [....] 
/*============================================================================== 
**
** Class: ThreadPool 
**
**
** Purpose: Class for creating and managing a threadpool
** 
**
=============================================================================*/ 
 
#pragma warning disable 0420
 
/*
 * Below you'll notice two sets of APIs that are separated by the
 * use of 'Unsafe' in their names.  The unsafe versions are called
 * that because they do not propagate the calling stack onto the 
 * worker thread.  This allows code to lose the calling stack and
 * thereby elevate its security privileges.  Note that this operation 
 * is much akin to the combined ability to control security policy 
 * and control security evidence.  With these privileges, a person
 * can gain the right to load assemblies that are fully trusted which 
 * then assert full trust and can call any code they want regardless
 * of the previous stack information.
 */
 
namespace System.Threading
{ 
    using System.Security; 
    using System.Runtime.Remoting;
    using System.Security.Permissions; 
    using System;
    using Microsoft.Win32;
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution; 
    using System.Runtime.InteropServices;
    using System.Runtime.Versioning; 
    using System.Collections.Generic; 
    using System.Diagnostics.Contracts;
 
    internal static class ThreadPoolGlobals
    {
#if FEATURE_LEGACY_THREADPOOL
        public static bool useNewWorkerPool = ThreadPool.ShouldUseNewWorkerPool(); 
#endif
 
        //Per-appDomain quantum (in ms) for which the thread keeps processing 
        //requests in the current domain.
 
#if FEATURE_LEGACY_THREADPOOL
        public static uint tpQuantum = ThreadPool.ShouldUseNewWorkerPool() ? 30U : 2U;
#else
        public static uint tpQuantum = 30U; 
#endif
 
        public static int processorCount = Environment.ProcessorCount; 

#if FEATURE_LEGACY_THREADPOOL 
        public static int tpWarmupCount =  Environment.ProcessorCount * 2;
#endif

        public static bool tpHosted = ThreadPool.IsThreadPoolHosted(); 

        public static bool vmTpInitialized; 
        public static bool enableWorkerTracking; 

#if FEATURE_LEGACY_THREADPOOL 
        public static ThreadPoolRequestQueue tpQueue = ThreadPool.ShouldUseNewWorkerPool() ? null : new ThreadPoolRequestQueue();

        [SecurityCritical]
        public static ThreadPoolWorkQueue workQueue = ThreadPool.ShouldUseNewWorkerPool() ? new ThreadPoolWorkQueue() : null; 
#else
        [SecurityCritical] 
        public static ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue(); 
#endif
 
        [System.Security.SecuritySafeCritical] // static constructors should be safe to call
        static ThreadPoolGlobals()
        {
        } 
    }
 
#if FEATURE_LEGACY_THREADPOOL 
    internal sealed class ThreadPoolRequestQueue
    { 
        private _ThreadPoolWaitCallback tpHead;
        private _ThreadPoolWaitCallback tpTail;

        //The dummy object used to synchronize thread pool queue access. 
        private object tpSync = new object();
 
        //The number of work-items in thread pool queue. 
        private int tpCount;
 
        [System.Security.SecuritySafeCritical]
        public int EnQueue(_ThreadPoolWaitCallback tpcallBack)
        {
            Contract.Assert(!ThreadPoolGlobals.useNewWorkerPool); 

            int count = 0; 
            bool tookLock = false; 
            bool setNativeTpEvent = false;
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                Monitor.Enter(tpSync, ref tookLock); 
            }
            finally 
            { 
                if (tookLock)
                { 
                    if (tpCount == 0)
                    {

                        //Indicate to the VM that there is work in this domain. 
                        //Its important to synchronize this notice, otherwise
                        //the VM may not schedule any thread in this domain. 
 
                        setNativeTpEvent = ThreadPool.SetAppDomainRequestActive();
                    } 

                    tpCount++;
                    count = tpCount;
 
                    if (tpHead == null)
                    { 
                        tpHead = tpcallBack; 
                        tpTail = tpcallBack;
                    } 
                    else
                    {
                        tpTail._next = tpcallBack;
                        tpTail = tpcallBack; 
                    }
 
                    Monitor.Exit(tpSync); 

                    if (setNativeTpEvent) 
                    {
                        ThreadPool.SetNativeTpEvent();
                    }
                } 
            }
 
            return count; 
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        public int DeQueue(ref _ThreadPoolWaitCallback callback)
        {
            Contract.Assert(!ThreadPoolGlobals.useNewWorkerPool); 

            bool tookLock = false; 
            _ThreadPoolWaitCallback tpWaitCallBack = null; 

            RuntimeHelpers.PrepareConstrainedRegions(); 
            try
            {
                Monitor.Enter(tpSync, ref tookLock);
            } 
            finally
            { 
                if (tookLock) 
                {
                    _ThreadPoolWaitCallback head = tpHead; 
                    if ( head != null)
                    {
                        tpWaitCallBack = head;
                        tpHead = head._next; 
                        tpCount--;
 
                        if(tpCount == 0) 
                        {
                            Contract.Assert(tpHead == null,"TP Queue head expected to be null"); 

                            tpTail = null;

                            //Indicate to the VM that there is no work in this 
                            //domain. Its important to synchronize this notice,
                            //otherwise the VM may keep calling the Managed 
                            //callbacks endlessly. 

                            ThreadPool.ClearAppDomainRequestActive(); 
                        }
                    }

                    Monitor.Exit(tpSync); 
                }
            } 
 
            callback = tpWaitCallBack;
            return tpCount; 
        }

        public int GetQueueCount()
        { 
            Contract.Assert(!ThreadPoolGlobals.useNewWorkerPool);
            return tpCount; 
        } 

    } 
#endif //FEATURE_LEGACY_THREADPOOL

    internal sealed class ThreadPoolWorkQueue
    { 
        // Simple sparsely populated array to allow lock-free reading.
        internal class SparseArray where T : class 
        { 
            private T[] m_array;
 
            internal SparseArray(int initialSize)
            {
                m_array = new T[initialSize];
            } 

            internal T[] Current 
            { 
                get { return m_array; }
            } 

            internal int Add(T e)
            {
                while (true) 
                {
                    T[] array = m_array; 
                    lock (array) 
                    {
                        for (int i = 0; i < array.Length; i++) 
                        {
                            if (array[i] == null)
                            {
                                array[i] = e; 
                                return i;
                            } 
                            else if (i == array.Length - 1) 
                            {
                                // Must resize. If we ----d and lost, we start over again. 
                                if (array != m_array)
                                    continue;

                                T[] newArray = new T[array.Length * 2]; 
                                Array.Copy(array, newArray, i + 1);
                                newArray[i + 1] = e; 
                                m_array = newArray; 
                                return i + 1;
                            } 
                        }
                    }
                }
            } 

            internal void Remove(T e) 
            { 
                T[] array = m_array;
                lock (array) 
                {
                    for (int i = 0; i < m_array.Length; i++)
                    {
                        if (m_array[i] == e) 
                        {
                            m_array[i] = null; 
                            break; 
                        }
                    } 
                }
            }
        }
 
        internal class WorkStealingQueue
        { 
            private const int INITIAL_SIZE = 32; 
            internal IThreadPoolWorkItem[] m_array = new IThreadPoolWorkItem[INITIAL_SIZE];
            private int m_mask = INITIAL_SIZE - 1; 

#if DEBUG
            // in debug builds, start at the end so we exercise the index reset logic.
            private const int START_INDEX = int.MaxValue; 
#else
            private const int START_INDEX = 0; 
#endif 

            private volatile int m_headIndex = START_INDEX; 
            private volatile int m_tailIndex = START_INDEX;

            private SpinLock m_foreignLock = new SpinLock(false);
 
            public void LocalPush(IThreadPoolWorkItem obj)
            { 
                int tail = m_tailIndex; 

                // We're going to increment the tail; if we'll overflow, then we need to reset our counts 
                if (tail == int.MaxValue)
                {
                    bool lockTaken = false;
                    try 
                    {
                        m_foreignLock.Enter(ref lockTaken); 
 
                        if (m_tailIndex == int.MaxValue)
                        { 
                            //
                            // Rather than resetting to zero, we'll just mask off the bits we don't care about.
                            // This way we don't need to rearrange the items already in the queue; they'll be found
                            // correctly exactly where they are.  One subtlety here is that we need to make sure that 
                            // if head is currently < tail, it remains that way.  This happens to just fall out from
                            // the bit-masking, because we only do this if tail == int.MaxValue, meaning that all 
                            // bits are set, so all of the bits we're keeping will also be set.  Thus it's impossible 
                            // for the head to end up > than the tail, since you can't set any more bits than all of
                            // them. 
                            //
                            m_headIndex = m_headIndex & m_mask;
                            m_tailIndex = tail = m_tailIndex & m_mask;
                            Contract.Assert(m_headIndex <= m_tailIndex); 
                        }
                    } 
                    finally 
                    {
                        if (lockTaken) 
                            m_foreignLock.Exit(true);
                    }
                }
 
                // When there are at least 2 elements' worth of space, we can take the fast path.
                if (tail < m_headIndex + m_mask) 
                { 
                    m_array[tail & m_mask] = obj;
                    m_tailIndex = tail + 1; 
                }
                else
                {
                    // We need to contend with foreign pops, so we lock. 
                    bool lockTaken = false;
                    try 
                    { 
                        m_foreignLock.Enter(ref lockTaken);
 
                        int head = m_headIndex;
                        int count = m_tailIndex - m_headIndex;

                        // If there is still space (one left), just add the element. 
                        if (count >= m_mask)
                        { 
                            // We're full; expand the queue by doubling its size. 
                            IThreadPoolWorkItem[] newArray = new IThreadPoolWorkItem[m_array.Length << 1];
                            for (int i = 0; i < m_array.Length; i++) 
                                newArray[i] = m_array[(i + head) & m_mask];

                            // Reset the field values, incl. the mask.
                            m_array = newArray; 
                            m_headIndex = 0;
                            m_tailIndex = tail = count; 
                            m_mask = (m_mask << 1) | 1; 
                        }
 
                        m_array[tail & m_mask] = obj;
                        m_tailIndex = tail + 1;
                    }
                    finally 
                    {
                        if (lockTaken) 
                            m_foreignLock.Exit(false); 
                    }
                } 
            }

            public bool LocalFindAndPop(IThreadPoolWorkItem obj)
            { 
                // Fast path: check the tail. If equal, we can skip the lock.
                if (m_array[(m_tailIndex - 1) & m_mask] == obj) 
                { 
                    IThreadPoolWorkItem unused;
                    if (LocalPop(out unused)) 
                    {
                        Contract.Assert(unused == obj);
                        return true;
                    } 
                    return false;
                } 
 
                // Else, do an O(N) search for the work item. The theory of work stealing and our
                // inlining logic is that most waits will happen on recently queued work.  And 
                // since recently queued work will be close to the tail end (which is where we
                // begin our search), we will likely find it quickly.  In the worst case, we
                // will traverse the whole local queue; this is typically not going to be a
                // problem (although degenerate cases are clearly an issue) because local work 
                // queues tend to be somewhat shallow in length, and because if we fail to find
                // the work item, we are about to block anyway (which is very expensive). 
                for (int i = m_tailIndex - 2; i >= m_headIndex; i--) 
                {
                    if (m_array[i & m_mask] == obj) 
                    {
                        // If we found the element, block out steals to avoid interference.
                        // @
                        bool lockTaken = false; 
                        try
                        { 
                            m_foreignLock.Enter(ref lockTaken); 

                            // If we lost the ----, bail. 
                            if (m_array[i & m_mask] == null)
                            {
                                //Console.WriteLine("{0} Pop(failed)", Thread.CurrentThread.ManagedThreadId);
                                return false; 
                            }
 
                            // Otherwise, null out the element. 
                            m_array[i & m_mask] = null;
 
                            // And then check to see if we can fix up the indexes (if we're at
                            // the edge).  If we can't, we just leave nulls in the array and they'll
                            // get filtered out eventually (but may lead to superflous resizing).
                            if (i == m_tailIndex) 
                                m_tailIndex -= 1;
                            else if (i == m_headIndex) 
                                m_headIndex += 1; 

                            //Console.WriteLine("{0} Pop(success)", Thread.CurrentThread.ManagedThreadId); 
                            return true;
                        }
                        finally
                        { 
                            if (lockTaken)
                                m_foreignLock.Exit(false); 
                        } 
                    }
                } 

                //Console.WriteLine("{0} Pop(failed)", Thread.CurrentThread.ManagedThreadId);
                return false;
            } 

            public bool LocalPop(out IThreadPoolWorkItem obj) 
            { 
                while (true)
                { 
                    // Decrement the tail using a fence to ensure subsequent read doesn't come before.
                    int tail = m_tailIndex;
                    if (m_headIndex >= tail)
                    { 
                        obj = null;
                        return false; 
                    } 

                    tail -= 1; 
                    Interlocked.Exchange(ref m_tailIndex, tail);

                    // If there is no interaction with a take, we can head down the fast path.
                    if (m_headIndex <= tail) 
                    {
                        int idx = tail & m_mask; 
                        obj = m_array[idx]; 

                        // Check for nulls in the array. 
                        if (obj == null) continue;

                        m_array[idx] = null;
                        return true; 
                    }
                    else 
                    { 
                        // Interaction with takes: 0 or 1 elements left.
                        bool lockTaken = false; 
                        try
                        {
                            m_foreignLock.Enter(ref lockTaken);
 
                            if (m_headIndex <= tail)
                            { 
                                // Element still available. Take it. 
                                int idx = tail & m_mask;
                                obj = m_array[idx]; 

                                // Check for nulls in the array.
                                if (obj == null) continue;
 
                                m_array[idx] = null;
                                return true; 
                            } 
                            else
                            { 
                                // We lost the ----, element was stolen, restore the tail.
                                m_tailIndex = tail + 1;
                                obj = null;
                                return false; 
                            }
                        } 
                        finally 
                        {
                            if (lockTaken) 
                                m_foreignLock.Exit(false);
                        }
                    }
                } 
            }
 
            public bool TrySteal(out IThreadPoolWorkItem obj, ref bool missedSteal) 
            {
                return TrySteal(out obj, ref missedSteal, 0); // no blocking by default. 
            }

            private bool TrySteal(out IThreadPoolWorkItem obj, ref bool missedSteal, int millisecondsTimeout)
            { 
                obj = null;
 
                while (true) 
                {
                    if (m_headIndex >= m_tailIndex) 
                        return false;

                    bool taken = false;
                    try 
                    {
                        m_foreignLock.TryEnter(millisecondsTimeout, ref taken); 
                        if (taken) 
                        {
                            // Increment head, and ensure read of tail doesn't move before it (fence). 
                            int head = m_headIndex;
                            Interlocked.Exchange(ref m_headIndex, head + 1);

                            if (head < m_tailIndex) 
                            {
                                int idx = head & m_mask; 
                                obj = m_array[idx]; 

                                // Check for nulls in the array. 
                                if (obj == null) continue;

                                m_array[idx] = null;
                                return true; 
                            }
                            else 
                            { 
                                // Failed, restore head.
                                m_headIndex = head; 
                                obj = null;
                                missedSteal = true;
                            }
                        } 
                        else
                        { 
                            missedSteal = true; 
                        }
                    } 
                    finally
                    {
                        if (taken)
                            m_foreignLock.Exit(false); 
                    }
 
                    return false; 
                }
            } 
        }

        internal class QueueSegment
        { 
            // Holds a segment of the queue.  Enqueues/Dequeues start at element 0, and work their way up.
            internal IThreadPoolWorkItem[] nodes; 
            private const int QueueSegmentLength = 256; 

            // Holds the indexes of the lowest and highest valid elements of the nodes array. 
            // The low index is in the lower 16 bits, high index is in the upper 16 bits.
            // Use GetIndexes and CompareExchangeIndexes to manipulate this.
            private volatile int indexes;
 
            // The next segment in the queue.
            public volatile QueueSegment Next; 
 

            const int SixteenBits = 0xffff; 

            void GetIndexes(out int upper, out int lower)
            {
                int i = indexes; 
                upper = (i >> 16) & SixteenBits;
                lower = i & SixteenBits; 
 
                Contract.Assert(upper >= lower);
                Contract.Assert(upper <= nodes.Length); 
                Contract.Assert(lower <= nodes.Length);
                Contract.Assert(upper >= 0);
                Contract.Assert(lower >= 0);
            } 

            bool CompareExchangeIndexes(ref int prevUpper, int newUpper, ref int prevLower, int newLower) 
            { 
                Contract.Assert(newUpper >= newLower);
                Contract.Assert(newUpper <= nodes.Length); 
                Contract.Assert(newLower <= nodes.Length);
                Contract.Assert(newUpper >= 0);
                Contract.Assert(newLower >= 0);
                Contract.Assert(newUpper >= prevUpper); 
                Contract.Assert(newLower >= prevLower);
                Contract.Assert(newUpper == prevUpper ^ newLower == prevLower); 
 
                int oldIndexes = (prevUpper << 16) | (prevLower & SixteenBits);
                int newIndexes = (newUpper << 16) | (newLower & SixteenBits); 
                int prevIndexes = Interlocked.CompareExchange(ref indexes, newIndexes, oldIndexes);
                prevUpper = (prevIndexes >> 16) & SixteenBits;
                prevLower = prevIndexes & SixteenBits;
                return prevIndexes == oldIndexes; 
            }
 
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
            public QueueSegment()
            { 
                Contract.Assert(QueueSegmentLength <= SixteenBits);
                nodes = new IThreadPoolWorkItem[QueueSegmentLength];
            }
 

            public bool IsUsedUp() 
            { 
                int upper, lower;
                GetIndexes(out upper, out lower); 
                return (upper == nodes.Length) &&
                       (lower == nodes.Length);
            }
 
            public bool TryEnqueue(IThreadPoolWorkItem node)
            { 
                // 
                // If there's room in this segment, atomically increment the upper count (to reserve
                // space for this node), then store the node. 
                // Note that this leaves a window where it will look like there is data in that
                // array slot, but it hasn't been written yet.  This is taken care of in TryDequeue
                // with a busy-wait loop, waiting for the element to become non-null.  This implies
                // that we can never store null nodes in this data structure. 
                //
                Contract.Assert(null != node); 
 
                int upper, lower;
                GetIndexes(out upper, out lower); 

                while (true)
                {
                    if (upper == nodes.Length) 
                        return false;
 
                    if (CompareExchangeIndexes(ref upper, upper + 1, ref lower, lower)) 
                    {
                        Contract.Assert(nodes[upper] == null); 
                        nodes[upper] = node;
                        return true;
                    }
                } 
            }
 
            public bool TryDequeue(out IThreadPoolWorkItem node) 
            {
                // 
                // If there are nodes in this segment, increment the lower count, then take the
                // element we find there.
                //
                int upper, lower; 
                GetIndexes(out upper, out lower);
 
                while(true) 
                {
                    if (lower == upper) 
                    {
                        node = null;
                        return false;
                    } 

                    if (CompareExchangeIndexes(ref upper, upper, ref lower, lower + 1)) 
                    { 
                        // It's possible that a concurrent call to Enqueue hasn't yet
                        // written the node reference to the array.  We need to spin until 
                        // it shows up.
                        SpinWait spinner = new SpinWait();
                        while (nodes[lower] == null)
                            spinner.SpinOnce(); 

                        node = nodes[lower]; 
 
                        // Null-out the reference so the object can be GC'd earlier.
                        nodes[lower] = null; 

                        return true;
                    }
                } 
            }
        } 
 
        // The head and tail of the queue.  We enqueue to the head, and dequeue from the tail.
        internal volatile QueueSegment queueHead; 
        internal volatile QueueSegment queueTail;

        internal static SparseArray allThreadQueues = new SparseArray(16); //
 
        private volatile int numOutstandingThreadRequests = 0;
 
        public ThreadPoolWorkQueue() 
        {
            queueTail = queueHead = new QueueSegment(); 
        }

        [SecurityCritical]
        public ThreadPoolWorkQueueThreadLocals EnsureCurrentThreadHasQueue() 
        {
            if (null == ThreadPoolWorkQueueThreadLocals.threadLocals) 
                ThreadPoolWorkQueueThreadLocals.threadLocals = new ThreadPoolWorkQueueThreadLocals(this); 
            return ThreadPoolWorkQueueThreadLocals.threadLocals;
        } 

        [SecurityCritical]
        internal void EnsureThreadRequested()
        { 
            //
            // If we have not yet requested #procs threads from the VM, then request a new thread. 
            // Note that there is a separate count in the VM which will also be incremented in this case, 
            // which is handled by AdjustThreadsInPool.
            // 
            int count = numOutstandingThreadRequests;
            while (count < ThreadPoolGlobals.processorCount)
            {
                int prev = Interlocked.CompareExchange(ref numOutstandingThreadRequests, count+1, count); 
                if (prev == count)
                { 
                    ThreadPool.AdjustThreadsInPool(1); 
                    break;
                } 
                count = prev;
            }
        }
 
        [SecurityCritical]
        internal void MarkThreadRequestSatisfied() 
        { 
            //
            // The VM has called us, so one of our outstanding thread requests has been satisfied. 
            // Decrement the count so that future calls to EnsureThreadRequested will succeed.
            // Note that there is a separate count in the VM which has already been decremented by the VM
            // by the time we reach this point.
            // 
            int count = numOutstandingThreadRequests;
            while (count > 0) 
            { 
                int prev = Interlocked.CompareExchange(ref numOutstandingThreadRequests, count - 1, count);
                if (prev == count) 
                {
                    break;
                }
                count = prev; 
            }
        } 
 
        [SecurityCritical]
        public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal) 
        {
#if FEATURE_LEGACY_THREADPOOL
            Contract.Assert(ThreadPoolGlobals.useNewWorkerPool);
#endif //FEATURE_LEGACY_THREADPOOL 

            ThreadPoolWorkQueueThreadLocals tl = null; 
            if (!forceGlobal) 
                tl = ThreadPoolWorkQueueThreadLocals.threadLocals;
 
            if (null != tl)
            {
                //Console.WriteLine("{0} Enqueue(local)", Thread.CurrentThread.ManagedThreadId);
                tl.workStealingQueue.LocalPush(callback); 
            }
            else 
            { 
                //Console.WriteLine("{0} Enqueue(global)", Thread.CurrentThread.ManagedThreadId);
                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();
        } 
 
        [SecurityCritical]
        internal bool LocalFindAndPop(IThreadPoolWorkItem callback) 
        {
#if FEATURE_LEGACY_THREADPOOL
            Contract.Assert(ThreadPoolGlobals.useNewWorkerPool);
#endif //FEATURE_LEGACY_THREADPOOL 

            ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.threadLocals; 
            if (null == tl) 
                return false;
 
            return tl.workStealingQueue.LocalFindAndPop(callback);
        }

        [SecurityCritical] 
        public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal)
        { 
#if FEATURE_LEGACY_THREADPOOL 
            Contract.Assert(ThreadPoolGlobals.useNewWorkerPool);
#endif //FEATURE_LEGACY_THREADPOOL 

            callback = null;
            missedSteal = false;
            WorkStealingQueue wsq = tl.workStealingQueue; 

            if (wsq.LocalPop(out callback)) 
            { 
                //Console.WriteLine("{0} Dequeue(local)", Thread.CurrentThread.ManagedThreadId);
                Contract.Assert(null != callback); 
            }

            if (null == callback)
            { 
                QueueSegment tail = queueTail;
                while (true) 
                { 
                    if (tail.TryDequeue(out callback))
                    { 
                        //Console.WriteLine("{0} Dequeue(global)", Thread.CurrentThread.ManagedThreadId);
                        Contract.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 = otherQueues[i % otherQueues.Length]; 
                    if (otherQueue != null &&
                        otherQueue != wsq && 
                        otherQueue.TrySteal(out callback, ref missedSteal))
                    {
                        //Console.WriteLine("{0} Dequeue(steal)", Thread.CurrentThread.ManagedThreadId);
                        Contract.Assert(null != callback); 
                        break;
                    } 
                    i++; 
                    c--;
                } 
            }

            //if (null == callback)
                //Console.WriteLine("{0} Dequeue(failed!)", Thread.CurrentThread.ManagedThreadId); 
        }
 
        [SecurityCritical] 
        static internal bool Dispatch()
        { 
            //
            // 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. 
            //
            ThreadPoolGlobals.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 = ThreadPoolGlobals.workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires. 
                //
                while ((Environment.TickCount - quantumStartTime) < ThreadPoolGlobals.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; 
                        ThreadPoolGlobals.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. 
                            //
                            ThreadPoolGlobals.workQueue.EnsureThreadRequested(); 
                        }
                    }

                    if (workItem == null) 
                    {
                        // Tell the VM we're returning normally, not because Hill Climbing asked us to return. 
                        return true; 
                    }
                    else 
                    {
                        //
                        // Execute the workitem outside of any finally blocks, so that it can be aborted if needed.
                        // 
                        if (ThreadPoolGlobals.enableWorkerTracking)
                        { 
                            bool reportedStatus = false; 
                            try
                            { 
                                try { }
                                finally
                                {
                                    ThreadPool.ReportThreadStatus(true); 
                                    reportedStatus = true;
                                } 
                                workItem.ExecuteWorkItem(); 
                                workItem = null;
                            } 
                            finally
                            {
                                if (reportedStatus)
                                    ThreadPool.ReportThreadStatus(false); 
                            }
                        } 
                        else 
                        {
                            workItem.ExecuteWorkItem(); 
                            workItem = null;
                        }

                        // 
                        // Notify the VM that we executed this workitem.  This is also our opportunity to ask whether Hill Climbing wants
                        // us to return the thread to the pool or not. 
                        // 
                        if (!ThreadPool.NotifyWorkItemComplete())
                            return false; 
                    }
                }

                // If we get here, it's because our quantum expired.  Tell the VM we're returning normally. 
                return true;
            } 
            catch (ThreadAbortException tae) 
            {
                // 
                // This is here to catch the case where this thread is aborted between the time we exit the finally block in the dispatch
                // loop, and the time we execute the work item.  QueueUserWorkItemCallback uses this to update its accounting of whether
                // it was executed or not (in debug builds only).  Task uses this to communicate the ThreadAbortException to anyone
                // who waits for the task to complete. 
                //
                if (workItem != null) 
                    workItem.MarkAborted(tae); 

                // 
                // In this case, the VM is going to request another thread on our behalf.  No need to do it twice.
                //
                needAnotherThread = false;
                throw; 
            }
            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)
                    ThreadPoolGlobals.workQueue.EnsureThreadRequested(); 
            }
        } 
    } 

    // Holds a WorkStealingQueue, and remmoves it from the list when this object is no longer referened. 
    internal sealed class ThreadPoolWorkQueueThreadLocals
    {
        [ThreadStatic]
        [SecurityCritical] 
        public static ThreadPoolWorkQueueThreadLocals threadLocals;
 
        public readonly ThreadPoolWorkQueue workQueue; 
        public readonly ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue;
        public readonly Random random = new Random(Thread.CurrentThread.ManagedThreadId); 

        public ThreadPoolWorkQueueThreadLocals(ThreadPoolWorkQueue tpq)
        {
            workQueue = tpq; 
            workStealingQueue = new ThreadPoolWorkQueue.WorkStealingQueue();
            ThreadPoolWorkQueue.allThreadQueues.Add(workStealingQueue); 
        } 

        [SecurityCritical] 
        private void CleanUp()
        {
            if (null != workStealingQueue)
            { 
                if (null != workQueue)
                { 
                    bool done = false; 
                    while (!done)
                    { 
                        // Ensure that we won't be aborted between LocalPop and Enqueue.
                        try { }
                        finally
                        { 
                            IThreadPoolWorkItem cb = null;
                            if (workStealingQueue.LocalPop(out cb)) 
                            { 
                                Contract.Assert(null != cb);
                                workQueue.Enqueue(cb, true); 
                            }
                            else
                            {
                                done = true; 
                            }
                        } 
                    } 
                }
 
                ThreadPoolWorkQueue.allThreadQueues.Remove(workStealingQueue);
            }
        }
 
        [SecuritySafeCritical]
        ~ThreadPoolWorkQueueThreadLocals() 
        { 
            // Since the purpose of calling CleanUp is to transfer any pending workitems into the global
            // queue so that they will be executed by another thread, there's no point in doing this cleanup 
            // if we're in the process of shutting down or unloading the AD.  In those cases, the work won't
            // execute anyway.  And there are subtle ----s involved there that would lead us to do the wrong
            // thing anyway.  So we'll only clean up if this is a "normal" finalization.
            if (!(Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload())) 
                CleanUp();
        } 
    } 

    internal sealed class RegisteredWaitHandleSafe : CriticalFinalizerObject 
    {
        private static IntPtr InvalidHandle
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get
            { 
                return Win32Native.INVALID_HANDLE_VALUE; 
            }
        } 
        private IntPtr registeredWaitHandle;
        private WaitHandle m_internalWaitObject;
        private bool bReleaseNeeded = false;
        private int m_lock = 0; 

        internal RegisteredWaitHandleSafe() 
        { 
            registeredWaitHandle = InvalidHandle;
        } 

        internal IntPtr GetHandle()
        {
           return registeredWaitHandle; 
        }
 
        internal void SetHandle(IntPtr handle) 
        {
            registeredWaitHandle = handle; 
        }

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
        internal void SetWaitObject(WaitHandle waitObject) 
        {
            // needed for DangerousAddRef 
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
            } 
            finally
            { 
                m_internalWaitObject = waitObject; 
                if (waitObject != null)
                { 
                    m_internalWaitObject.SafeWaitHandle.DangerousAddRef(ref bReleaseNeeded);
                }
            }
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
        internal bool Unregister(
             WaitHandle     waitObject          // object to be notified when all callbacks to delegates have completed
             )
        { 
            bool result = false;
            // needed for DangerousRelease 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try
            { 
            }
            finally
            {
                // lock(this) cannot be used reliably in Cer since thin lock could be 
                // promoted to syncblock and that is not a guaranteed operation
                bool bLockTaken = false; 
                do 
                {
                    if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) 
                    {
                        bLockTaken = true;
                        try
                        { 
                            if (ValidHandle())
                            { 
                                result = UnregisterWaitNative(GetHandle(), waitObject == null ? null : waitObject.SafeWaitHandle); 
                                if (result == true)
                                { 
                                    if (bReleaseNeeded)
                                    {
                                        m_internalWaitObject.SafeWaitHandle.DangerousRelease();
                                        bReleaseNeeded = false; 
                                    }
                                    // if result not true don't release/suppress here so finalizer can make another attempt 
                                    SetHandle(InvalidHandle); 
                                    m_internalWaitObject = null;
                                    GC.SuppressFinalize(this); 
                                }
                            }
                        }
                        finally 
                        {
                            m_lock = 0; 
                        } 
                    }
                    Thread.SpinWait(1);     // yield to processor 
                }
                while (!bLockTaken);
            }
            return result; 
        }
 
        private bool ValidHandle() 
        {
            return (registeredWaitHandle != InvalidHandle && registeredWaitHandle != IntPtr.Zero); 
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        ~RegisteredWaitHandleSafe() 
        { 
            // if the app has already unregistered the wait, there is nothing to cleanup
            // we can detect this by checking the handle. Normally, there is no ---- here 
            // so no need to protect reading of handle. However, if this object gets
            // resurrected and then someone does an unregister, it would introduce a ----

            // PrepareConstrainedRegions call not needed since finalizer already in Cer 

            // lock(this) cannot be used reliably even in Cer since thin lock could be 
            // promoted to syncblock and that is not a guaranteed operation 

            bool bLockTaken = false; 
            do
            {
                if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0)
                { 
                    bLockTaken = true;
                    try 
                    { 
                        if (ValidHandle())
                        { 
                            WaitHandleCleanupNative(registeredWaitHandle);
                            if (bReleaseNeeded)
                            {
                                m_internalWaitObject.SafeWaitHandle.DangerousRelease(); 
                                bReleaseNeeded = false;
                            } 
                            SetHandle(InvalidHandle); 
                            m_internalWaitObject = null;
                        } 
                    }
                    finally
                    {
                        m_lock = 0; 
                    }
                } 
                Thread.SpinWait(1);     // yield to processor 
            }
            while (!bLockTaken); 
        }

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void WaitHandleCleanupNative(IntPtr handle); 
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern bool UnregisterWaitNative(IntPtr handle, SafeHandle waitObject);
    }
 
[System.Runtime.InteropServices.ComVisible(true)]
#if FEATURE_REMOTING 
    public sealed class RegisteredWaitHandle : MarshalByRefObject { 
#if false
    } 
#endif // FALSE
#else // FEATURE_REMOTING
    public sealed class RegisteredWaitHandle {
#endif // FEATURE_REMOTING 
        private RegisteredWaitHandleSafe internalRegisteredWait;
 
        internal RegisteredWaitHandle() 
        {
            internalRegisteredWait = new RegisteredWaitHandleSafe(); 
        }

        internal void SetHandle(IntPtr handle)
        { 
           internalRegisteredWait.SetHandle(handle);
        } 
 
        [System.Security.SecurityCritical]  // auto-generated
        internal void SetWaitObject(WaitHandle waitObject) 
        {
           internalRegisteredWait.SetWaitObject(waitObject);
        }
 

[System.Security.SecuritySafeCritical]  // auto-generated 
[System.Runtime.InteropServices.ComVisible(true)] 
        // This is the only public method on this class
        public bool Unregister( 
             WaitHandle     waitObject          // object to be notified when all callbacks to delegates have completed
             )
        {
            return internalRegisteredWait.Unregister(waitObject); 
        }
    } 
 
    [System.Runtime.InteropServices.ComVisible(true)]
    public delegate void WaitCallback(Object state); 

    [System.Runtime.InteropServices.ComVisible(true)]
    public delegate void WaitOrTimerCallback(Object state, bool timedOut);  // signalled or timed out
 
    internal class _ThreadPoolWaitCallback
    { 
#if FEATURE_LEGACY_THREADPOOL 
        WaitCallback _waitCallback;
        ExecutionContext _executionContext; 
        Object _state;

        //ThreadPoolWaitCallBack is the unit of thread pool work, and is
        //chained together. The _next field is the link. This field should be 
        //accessible to the Thread pool queue in order to reduce number of
        //object allocations as this is on a perf-critical path. 
 
        protected internal _ThreadPoolWaitCallback _next;
 
        static internal ContextCallback _ccb = new ContextCallback(WaitCallback_Context);
        static internal void WaitCallback_Context(Object state)
        {
            _ThreadPoolWaitCallback obj = (_ThreadPoolWaitCallback)state; 
            obj._waitCallback(obj._state);
        } 
 
        [System.Security.SecurityCritical]  // auto-generated
        internal _ThreadPoolWaitCallback(WaitCallback waitCallback, Object state, bool compressStack, ref StackCrawlMark stackMark) 
        {
            _waitCallback = waitCallback;
            _state = state;
            if (compressStack && !ExecutionContext.IsFlowSuppressed()) 
            {
                // clone the exection context 
                _executionContext = ExecutionContext.Capture( 
                    ref stackMark,
                    ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase); 
            }
        }

#endif //FEATURE_LEGACY_THREADPOOL 

        // call back helper 
        // This function dispatches requests to the user-callbacks. The 
        // work-items are fetched from the per-appdomain queue in a loop until
        // either there is no more work or the quantum has expired. The quantum 
        // is enforced to maintain fairness among appdomains.
        [System.Security.SecurityCritical]  // auto-generated
        static internal bool PerformWaitCallback()
        { 
#if FEATURE_LEGACY_THREADPOOL
            if (ThreadPoolGlobals.useNewWorkerPool) 
#endif //FEATURE_LEGACY_THREADPOOL 
                return ThreadPoolWorkQueue.Dispatch();
 
#if FEATURE_LEGACY_THREADPOOL
            int totTime = 0;

            _ThreadPoolWaitCallback tpWaitCallBack = null; 

            int startTime = Environment.TickCount; 
 
            do
            { 
                int count = ThreadPoolGlobals.tpQueue.DeQueue(ref tpWaitCallBack);

                if (tpWaitCallBack == null)
                { 
                    break;
                } 
 
                // This call in the VM updates queue counts, number of
                // completed requests, etc. More importantly, it also 
                // resets thread state like CriticalRegionCount, priority etc.
                //

                ThreadPool.CompleteThreadPoolRequest((uint)count); 

                PerformWaitCallbackInternal(tpWaitCallBack); 
 
                int endTime = Environment.TickCount;
 
                totTime = (endTime - startTime);

                // Check to see if quantum has expired.
 
                if (totTime > ThreadPoolGlobals.tpQuantum)
                { 
                    if(ThreadPool.ShouldReturnToVm()) 
                    {
                        break; 
                    }
                }

             } while (true); 

            return true; 
#endif //FEATURE_LEGACY_THREADPOOL 
        }
 

#if FEATURE_LEGACY_THREADPOOL
        [System.Security.SecurityCritical]  // auto-generated
        static internal void PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack) 
        {
 
            // call directly if it is an unsafe call OR EC flow is suppressed 
            if (tpWaitCallBack._executionContext == null)
            { 
                WaitCallback callback = tpWaitCallBack._waitCallback;
                callback(tpWaitCallBack._state);
            }
            else 
            {
                ExecutionContext.Run(tpWaitCallBack._executionContext, _ccb, tpWaitCallBack, true); 
            } 
        }
#endif //FEATURE_LEGACY_THREADPOOL 
    }

    //
    // Interface to something that can be queued to the TP.  This is implemented by 
    // QueueUserWorkItemCallback and Task.  If we decide to expose some of the workstealing
    // stuff, this is NOT the thing we want to expose to the public. 
    // 
    internal interface IThreadPoolWorkItem
    { 
        [SecurityCritical]
        void ExecuteWorkItem();
        [SecurityCritical]
        void MarkAborted(ThreadAbortException tae); 
    }
 
    internal sealed class QueueUserWorkItemCallback : IThreadPoolWorkItem 
    {
        private WaitCallback callback; 
        private ExecutionContext context;
        private Object state;

#if DEBUG 
        volatile int executed;
 
        ~QueueUserWorkItemCallback() 
        {
            Contract.Assert( 
                executed != 0 || Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload(),
                "A QueueUserWorkItemCallback was never called!");
        }
 
        void MarkExecuted(bool aborted)
        { 
            GC.SuppressFinalize(this); 
            Contract.Assert(
                0 == Interlocked.Exchange(ref executed, 1) || aborted, 
                "A QueueUserWorkItemCallback was called twice!");
        }
#endif
 
        [SecurityCritical]
        internal QueueUserWorkItemCallback(WaitCallback waitCallback, Object stateObj, bool compressStack, ref StackCrawlMark stackMark) 
        { 
            callback = waitCallback;
            state = stateObj; 
            if (compressStack && !ExecutionContext.IsFlowSuppressed())
            {
                // clone the exection context
                context = ExecutionContext.Capture( 
                    ref stackMark,
                    ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase); 
            } 
        }
 
        //
        // internal test hook - used by tests to exercise work-stealing, etc.
        //
        internal QueueUserWorkItemCallback(WaitCallback waitCallback, Object stateObj, ExecutionContext ec) 
        {
            callback = waitCallback; 
            state = stateObj; 
            context = ec;
        } 

        [SecurityCritical]
        void IThreadPoolWorkItem.ExecuteWorkItem()
        { 
#if DEBUG
            MarkExecuted(false); 
#endif 

            // call directly if it is an unsafe call OR EC flow is suppressed 
            if (context == null)
            {
                WaitCallback cb = callback;
                callback = null; 
                cb(state);
            } 
            else 
            {
                ExecutionContext.Run(context, ccb, this, true); 
            }
        }

        [SecurityCritical] 
        void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
        { 
#if DEBUG 
            // this workitem didn't execute because we got a ThreadAbortException prior to the call to ExecuteWorkItem.
            // This counts as being executed for our purposes. 
            MarkExecuted(true);
#endif
        }
 
        static internal ContextCallback ccb = new ContextCallback(WaitCallback_Context);
 
        static internal void WaitCallback_Context(Object state) 
        {
            QueueUserWorkItemCallback obj = (QueueUserWorkItemCallback)state; 
            WaitCallback wc = obj.callback as WaitCallback;
            Contract.Assert(null != wc);
            wc(obj.state);
        } 
    }
 
    internal class _ThreadPoolWaitOrTimerCallback 
    {
        WaitOrTimerCallback _waitOrTimerCallback; 
        ExecutionContext _executionContext;
        Object _state;
        static private ContextCallback _ccbt = new ContextCallback(WaitOrTimerCallback_Context_t);
        static private ContextCallback _ccbf = new ContextCallback(WaitOrTimerCallback_Context_f); 

        [System.Security.SecurityCritical]  // auto-generated 
        internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, Object state, bool compressStack, ref StackCrawlMark stackMark) 
        {
            _waitOrTimerCallback = waitOrTimerCallback; 
            _state = state;

            if (compressStack && !ExecutionContext.IsFlowSuppressed())
            { 
                // capture the exection context
                _executionContext = ExecutionContext.Capture( 
                    ref stackMark, 
                    ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
            } 
        }

        static private void WaitOrTimerCallback_Context_t(Object state)
        { 
            WaitOrTimerCallback_Context(state, true);
        } 
        static private void WaitOrTimerCallback_Context_f(Object state) 
        {
            WaitOrTimerCallback_Context(state, false); 
        }

        static private void WaitOrTimerCallback_Context(Object state, bool timedOut)
        { 
            _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
            helper._waitOrTimerCallback(helper._state, timedOut); 
        } 

        // call back helper 
        [System.Security.SecurityCritical]  // auto-generated
        static internal void PerformWaitOrTimerCallback(Object state, bool timedOut)
        {
            _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state; 
            Contract.Assert(helper != null, "Null state passed to PerformWaitOrTimerCallback!");
            // call directly if it is an unsafe call OR EC flow is suppressed 
            if (helper._executionContext == null) 
            {
                WaitOrTimerCallback callback = helper._waitOrTimerCallback; 
                callback(helper._state, timedOut);
            }
            else
            { 
                using (ExecutionContext executionContext = helper._executionContext.CreateCopy())
                { 
                if (timedOut) 
                        ExecutionContext.Run(executionContext, _ccbt, helper, true);
                else 
                        ExecutionContext.Run(executionContext, _ccbf, helper, true);
                }
            }
        } 

    } 
 
    [System.Security.SecurityCritical]
    [CLSCompliant(false)] 
    [System.Runtime.InteropServices.ComVisible(true)]
    unsafe public delegate void IOCompletionCallback(uint errorCode, // Error code
                                       uint numBytes, // No. of bytes transferred
                                       NativeOverlapped* pOVERLAP // ptr to OVERLAP structure 
                                       );
 
    [HostProtection(Synchronization=true, ExternalThreading=true)] 
    public static class ThreadPool
    { 

        [System.Security.SecuritySafeCritical]  // auto-generated
        [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
        public static bool SetMaxThreads(int workerThreads, int completionPortThreads) 
        {
            return SetMaxThreadsNative(workerThreads, completionPortThreads); 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public static void GetMaxThreads(out int workerThreads, out int completionPortThreads)
        {
            GetMaxThreadsNative(out workerThreads, out completionPortThreads);
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] 
        public static bool SetMinThreads(int workerThreads, int completionPortThreads)
        { 
            return SetMinThreadsNative(workerThreads, completionPortThreads);
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public static void GetMinThreads(out int workerThreads, out int completionPortThreads)
        { 
            GetMinThreadsNative(out workerThreads, out completionPortThreads); 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads)
        {
            GetAvailableThreadsNative(out workerThreads, out completionPortThreads); 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject,
             WaitOrTimerCallback    callBack,
             Object                 state, 
             uint               millisecondsTimeOutInterval,
             bool               executeOnlyOnce    // NOTE: we do not allow other options that allow the callback to be queued as an APC 
             ) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
        }

        [System.Security.SecurityCritical]  // auto-generated_required 
        [CLSCompliant(false)]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(  // throws RegisterWaitException 
             WaitHandle             waitObject,
             WaitOrTimerCallback    callBack, 
             Object                 state,
             uint               millisecondsTimeOutInterval,
             bool               executeOnlyOnce    // NOTE: we do not allow other options that allow the callback to be queued as an APC
             ) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false); 
        }
 

        [System.Security.SecurityCritical]  // auto-generated
        private static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject, 
             WaitOrTimerCallback    callBack,
             Object                 state, 
             uint               millisecondsTimeOutInterval, 
             bool               executeOnlyOnce,   // NOTE: we do not allow other options that allow the callback to be queued as an APC
             ref StackCrawlMark stackMark, 
             bool               compressStack
             )
        {
#if FEATURE_REMOTING 
            if (RemotingServices.IsTransparentProxy(waitObject))
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); 
            Contract.EndContractBlock(); 
#endif
 
            RegisteredWaitHandle registeredWaitHandle = new RegisteredWaitHandle();

            if (callBack != null)
            { 
                _ThreadPoolWaitOrTimerCallback callBackHelper = new _ThreadPoolWaitOrTimerCallback(callBack, state, compressStack, ref stackMark);
                state = (Object)callBackHelper; 
                // call SetWaitObject before native call so that waitObject won't be closed before threadpoolmgr registration 
                // this could occur if callback were to fire before SetWaitObject does its addref
                registeredWaitHandle.SetWaitObject(waitObject); 
                IntPtr nativeRegisteredWaitHandle = RegisterWaitForSingleObjectNative(waitObject,
                                                                               state,
                                                                               millisecondsTimeOutInterval,
                                                                               executeOnlyOnce, 
                                                                               registeredWaitHandle,
                                                                               ref stackMark, 
                                                                               compressStack); 
                registeredWaitHandle.SetHandle(nativeRegisteredWaitHandle);
            } 
            else
            {
                throw new ArgumentNullException("WaitOrTimerCallback");
            } 
            return registeredWaitHandle;
        } 
 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject,
             WaitOrTimerCallback    callBack, 
             Object                 state,
             int                    millisecondsTimeOutInterval, 
             bool               executeOnlyOnce    // NOTE: we do not allow other options that allow the callback to be queued as an APC 
             )
        { 
            if (millisecondsTimeOutInterval < -1)
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            Contract.EndContractBlock();
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
        } 
 
        [System.Security.SecurityCritical]  // auto-generated_required
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(  // throws RegisterWaitException
             WaitHandle             waitObject,
             WaitOrTimerCallback    callBack,
             Object                 state, 
             int                    millisecondsTimeOutInterval,
             bool               executeOnlyOnce    // NOTE: we do not allow other options that allow the callback to be queued as an APC 
             ) 
        {
            if (millisecondsTimeOutInterval < -1) 
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            Contract.EndContractBlock();
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false); 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static RegisteredWaitHandle RegisterWaitForSingleObject(  // throws RegisterWaitException 
            WaitHandle          waitObject,
            WaitOrTimerCallback callBack,
            Object                  state,
            long                    millisecondsTimeOutInterval, 
            bool                executeOnlyOnce    // NOTE: we do not allow other options that allow the callback to be queued as an APC
        ) 
        { 
            if (millisecondsTimeOutInterval < -1)
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); 
            Contract.EndContractBlock();
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
        } 

        [System.Security.SecurityCritical]  // auto-generated_required 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(  // throws RegisterWaitException
            WaitHandle          waitObject, 
            WaitOrTimerCallback callBack,
            Object                  state,
            long                    millisecondsTimeOutInterval,
            bool                executeOnlyOnce    // NOTE: we do not allow other options that allow the callback to be queued as an APC 
        )
        { 
            if (millisecondsTimeOutInterval < -1) 
                throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            Contract.EndContractBlock(); 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle RegisterWaitForSingleObject( 
                          WaitHandle            waitObject,
                          WaitOrTimerCallback   callBack, 
                          Object                state,
                          TimeSpan              timeout,
                          bool                  executeOnlyOnce
                          ) 
        {
            long tm = (long)timeout.TotalMilliseconds; 
            if (tm < -1) 
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            if (tm > (long) Int32.MaxValue) 
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,true);
        } 

        [System.Security.SecurityCritical]  // auto-generated_required 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable 
        public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
                          WaitHandle            waitObject, 
                          WaitOrTimerCallback   callBack,
                          Object                state,
                          TimeSpan              timeout,
                          bool                  executeOnlyOnce 
                          )
        { 
            long tm = (long)timeout.TotalMilliseconds; 
            if (tm < -1)
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); 
            if (tm > (long) Int32.MaxValue)
                throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,false); 
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static bool QueueUserWorkItem( 
             WaitCallback           callBack,     // NOTE: we do not expose options that allow the callback to be queued as an APC
             Object                 state
             )
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return QueueUserWorkItemHelper(callBack,state,ref stackMark,true); 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static bool QueueUserWorkItem(
             WaitCallback           callBack     // NOTE: we do not expose options that allow the callback to be queued as an APC
             ) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            return QueueUserWorkItemHelper(callBack,null,ref stackMark,true); 
        }
 
        [System.Security.SecurityCritical]  // auto-generated_required
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static bool UnsafeQueueUserWorkItem(
             WaitCallback           callBack,     // NOTE: we do not expose options that allow the callback to be queued as an APC 
             Object                 state
             ) 
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            return QueueUserWorkItemHelper(callBack,state,ref stackMark,false); 
        }

        //ThreadPool has per-appdomain managed queue of work-items. The VM is
        //responsible for just scheduling threads into appdomains. After that 
        //work-items are dispatched from the managed queue.
        [System.Security.SecurityCritical]  // auto-generated 
        private static bool QueueUserWorkItemHelper(WaitCallback callBack, Object state, ref StackCrawlMark stackMark, bool compressStack ) 
        {
            bool success =  true; 

            if (callBack != null)
            {
                        //The thread pool maintains a per-appdomain managed work queue. 
                //New thread pool entries are added in the managed queue.
                //The VM is responsible for the actual growing/shrinking of 
                //threads. 

                EnsureVMInitialized(); 

#if FEATURE_LEGACY_THREADPOOL
                if (ThreadPoolGlobals.useNewWorkerPool)
                { 
#endif //FEATURE_LEGACY_THREADPOOL
                    // 
                    // If we are able to create the workitem, we need to get it in the queue without being interrupted 
                    // by a ThreadAbortException.
                    // 
                    try { }
                    finally
                    {
                        QueueUserWorkItemCallback tpcallBack = new QueueUserWorkItemCallback(callBack, state, compressStack, ref stackMark); 
                        ThreadPoolGlobals.workQueue.Enqueue(tpcallBack, true);
                        success = true; 
                    } 
#if FEATURE_LEGACY_THREADPOOL
                } 
                else
                {
                    _ThreadPoolWaitCallback tpcallBack = new _ThreadPoolWaitCallback(callBack, state, compressStack, ref stackMark);
 
                    int queueCount = ThreadPoolGlobals.tpQueue.EnQueue(tpcallBack);
 
                    //Make sure the unmanaged thread pool creates some threads 
                    //before accepting requests in the managed queue.
 
                    if ((ThreadPoolGlobals.tpHosted) || (queueCount < ThreadPoolGlobals.tpWarmupCount))
                    {
                        success = AdjustThreadsInPool((uint)ThreadPoolGlobals.tpQueue.GetQueueCount());
                    } 
                    else
                    { 
                        UpdateNativeTpCount((uint)ThreadPoolGlobals.tpQueue.GetQueueCount()); 
                    }
                } 
#endif //FEATURE_LEGACY_THREADPOOL
            }
            else
            { 
                throw new ArgumentNullException("WaitCallback");
            } 
            return success; 
        }
 
        [SecurityCritical]
        internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
        {
            Contract.Assert(null != workItem); 
            EnsureVMInitialized();
 
            // 
            // Enqueue needs to be protected from ThreadAbort
            // 
            try { }
            finally
            {
                ThreadPoolGlobals.workQueue.Enqueue(workItem, forceGlobal); 
            }
        } 
 
        // This method tries to take the target callback out of the current thread's queue.
        [SecurityCritical] 
        internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
        {
            Contract.Assert(null != workItem);
            if (!ThreadPoolGlobals.vmTpInitialized) 
                return false; //Not initialized, so there's no way this workitem was ever queued.
            return ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem); 
        } 

        // Get all workitems.  Called by TaskScheduler in its debugger hooks. 
        [SecurityCritical]
        internal static IEnumerable GetQueuedWorkItems()
        {
            return EnumerateQueuedWorkItems(ThreadPoolWorkQueue.allThreadQueues.Current, ThreadPoolGlobals.workQueue.queueTail); 
        }
 
        internal static IEnumerable EnumerateQueuedWorkItems(ThreadPoolWorkQueue.WorkStealingQueue[] wsQueues, ThreadPoolWorkQueue.QueueSegment globalQueueTail) 
        {
#if FEATURE_LEGACY_THREADPOOL 
            Contract.Assert(ThreadPoolGlobals.useNewWorkerPool);
#endif //FEATURE_LEGACY_THREADPOOL

            if (wsQueues != null) 
            {
                // First, enumerate all workitems in thread-local queues. 
                foreach (ThreadPoolWorkQueue.WorkStealingQueue wsq in wsQueues) 
                {
                    if (wsq != null && wsq.m_array != null) 
                    {
                        IThreadPoolWorkItem[] items = wsq.m_array;
                        for (int i = 0; i < items.Length; i++)
                        { 
                            IThreadPoolWorkItem item = items[i];
                            if (item != null) 
                                yield return item; 
                        }
                    } 
                }
            }

            if (globalQueueTail != null) 
            {
                // Now the global queue 
                for (ThreadPoolWorkQueue.QueueSegment segment = globalQueueTail; 
                    segment != null;
                    segment = segment.Next) 
                {
                    IThreadPoolWorkItem[] items = segment.nodes;
                    for (int i = 0; i < items.Length; i++)
                    { 
                        IThreadPoolWorkItem item = items[i];
                        if (item != null) 
                            yield return item; 
                    }
                } 
            }
        }

        [SecurityCritical] 
        internal static IEnumerable GetLocallyQueuedWorkItems()
        { 
#if FEATURE_LEGACY_THREADPOOL 
            Contract.Assert(ThreadPoolGlobals.useNewWorkerPool);
#endif //FEATURE_LEGACY_THREADPOOL 

            return EnumerateQueuedWorkItems(new ThreadPoolWorkQueue.WorkStealingQueue[] { ThreadPoolWorkQueueThreadLocals.threadLocals.workStealingQueue }, null);
        }
 
        [SecurityCritical]
        internal static IEnumerable GetGloballyQueuedWorkItems() 
        { 
            return EnumerateQueuedWorkItems(null, ThreadPoolGlobals.workQueue.queueTail);
        } 

        private static object[] ToObjectArray(IEnumerable workitems)
        {
            int i = 0; 
            foreach (IThreadPoolWorkItem item in workitems)
            { 
                i++; 
            }
 
            object[] result = new object[i];
            i = 0;
            foreach (IThreadPoolWorkItem item in workitems)
            { 
                if (i < result.Length) //just in case someone calls us while the queues are in motion
                    result[i] = item; 
                i++; 
            }
 
            return result;
        }

        // This is the method the debugger will actually call, if it ends up calling 
        // into ThreadPool directly.  Tests can use this to simulate a debugger, as well.
        [SecurityCritical] 
        internal static object[] GetQueuedWorkItemsForDebugger() 
        {
            return ToObjectArray(GetQueuedWorkItems()); 
        }

        [SecurityCritical]
        internal static object[] GetGloballyQueuedWorkItemsForDebugger() 
        {
            return ToObjectArray(GetGloballyQueuedWorkItems()); 
        } 

        [SecurityCritical] 
        internal static object[] GetLocallyQueuedWorkItemsForDebugger()
        {
            return ToObjectArray(GetLocallyQueuedWorkItems());
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity] 
        internal static extern bool AdjustThreadsInPool(uint QueueLength);

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        unsafe private static extern bool PostQueuedCompletionStatus(NativeOverlapped* overlapped); 
 
        [System.Security.SecurityCritical]  // auto-generated_required
        [CLSCompliant(false)] 
        unsafe public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped)
        {
#if FEATURE_CORECLR
            if(Environment.OSVersion.Platform == PlatformID.MacOSX) 
                throw new NotSupportedException(Environment.GetResourceString("Arg_NotSupportedException"));
            Contract.EndContractBlock(); 
#endif 

            return PostQueuedCompletionStatus(overlapped); 
        }

        [SecurityCritical]
        private static void EnsureVMInitialized() 
        {
            if (!ThreadPoolGlobals.vmTpInitialized) 
            { 
                ThreadPool.InitializeVMTp(ref ThreadPoolGlobals.enableWorkerTracking);
                ThreadPoolGlobals.vmTpInitialized = true; 
            }
        }

        // Native methods: 

#if FEATURE_LEGACY_THREADPOOL 
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool ShouldUseNewWorkerPool();
#endif //FEATURE_LEGACY_THREADPOOL
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads);
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads); 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads); 

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads);
 
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads);

#if FEATURE_LEGACY_THREADPOOL
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity] 
        internal static extern bool CompleteThreadPoolRequest(uint QueueLength);
#endif //FEATURE_LEGACY_THREADPOOL 

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern bool NotifyWorkItemComplete();
 
        [System.Security.SecurityCritical] 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern void ReportThreadStatus(bool isWorking);

        [System.Security.SecuritySafeCritical]
        internal static void NotifyWorkItemProgress() 
        {
            if (!ThreadPoolGlobals.vmTpInitialized) 
                ThreadPool.InitializeVMTp(ref ThreadPoolGlobals.enableWorkerTracking); 
            NotifyWorkItemProgressNative();
        } 

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern void NotifyWorkItemProgressNative();
 
#if FEATURE_LEGACY_THREADPOOL 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool ShouldReturnToVm();
#endif //FEATURE_LEGACY_THREADPOOL 

#if FEATURE_LEGACY_THREADPOOL 
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        internal static extern bool SetAppDomainRequestActive();
#endif //FEATURE_LEGACY_THREADPOOL 

#if FEATURE_LEGACY_THREADPOOL 
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        internal static extern void ClearAppDomainRequestActive();
#endif //FEATURE_LEGACY_THREADPOOL 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool IsThreadPoolHosted(); 

#if FEATURE_LEGACY_THREADPOOL
        [System.Security.SecurityCritical]  // auto-generated
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void SetNativeTpEvent(); 
#endif //FEATURE_LEGACY_THREADPOOL 

#if FEATURE_LEGACY_THREADPOOL 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void UpdateNativeTpCount(uint QueueLength); 
#endif //FEATURE_LEGACY_THREADPOOL
 
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [SuppressUnmanagedCodeSecurity]
        private static extern void InitializeVMTp(ref bool enableWorkerTracking);

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern IntPtr RegisterWaitForSingleObjectNative( 
             WaitHandle             waitHandle,
             Object                 state, 
             uint                   timeOutInterval,
             bool                   executeOnlyOnce,
             RegisteredWaitHandle   registeredWaitHandle,
             ref StackCrawlMark     stackMark, 
             bool                   compressStack
             ); 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated.  Please use ThreadPool.BindHandle(SafeHandle) instead.", false)] 
        [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public static bool BindHandle(
             IntPtr osHandle
             ) 
        {
            return BindIOCompletionCallbackNative(osHandle); 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public static bool BindHandle(SafeHandle osHandle)
        {
            #if FEATURE_CORECLR 
            if(Environment.OSVersion.Platform == PlatformID.MacOSX)
                throw new NotSupportedException(Environment.GetResourceString("Arg_NotSupportedException")); 
            Contract.EndContractBlock(); 
            #endif
 
            if (osHandle == null)
                throw new ArgumentNullException("osHandle");

            bool ret = false; 
            bool mustReleaseSafeHandle = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                osHandle.DangerousAddRef(ref mustReleaseSafeHandle);
                ret = BindIOCompletionCallbackNative(osHandle.DangerousGetHandle()); 
            }
            finally {
                if (mustReleaseSafeHandle)
                    osHandle.DangerousRelease(); 
            }
            return ret; 
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        private static extern bool BindIOCompletionCallbackNative(IntPtr fileHandle); 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK