Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Threading / ThreadPool.cs / 4 / ThreadPool.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: ThreadPool ** ** ** Purpose: Class for creating and managing a threadpool ** ** =============================================================================*/ /* * 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 assertt full trust and can call any code they want regardless * of the previous stack information. */ namespace System.Threading { using System.Security; using System.Threading; 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; internal static class ThreadPoolGlobals { //Per-appDomain quantum (in ms) for which the thread keeps processing //requests in the current domain. public static uint tpQuantum = 2; public static int tpWarmupCount = GetProcessorCount() * 2; public static bool tpHosted = ThreadPool.IsThreadPoolHosted(); public static bool vmTpInitialized; public static ThreadPoolRequestQueue tpQueue = new ThreadPoolRequestQueue(); [EnvironmentPermissionAttribute(SecurityAction.Assert, Read="NUMBER_OF_PROCESSORS")] internal static int GetProcessorCount() { return Environment.ProcessorCount; } } internal sealed class ThreadPoolRequestQueue { private _ThreadPoolWaitCallback tpHead; private _ThreadPoolWaitCallback tpTail; //The dummy object used to synchronize thread pool queue access. private Object tpSync; //The number of work-items in thread pool queue. private uint tpCount; public ThreadPoolRequestQueue() { tpSync = new Object(); } public uint EnQueue(_ThreadPoolWaitCallback tpcallBack) { uint count = 0; bool tookLock = false; bool setNativeTpEvent = false; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.Enter(tpSync); tookLock = true; } catch(Exception) { } 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; } public _ThreadPoolWaitCallback DeQueue() { bool tookLock = false; _ThreadPoolWaitCallback tpWaitCallBack = null; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.Enter(tpSync); tookLock = true; } catch(Exception) { } if (tookLock) { _ThreadPoolWaitCallback head = tpHead; if ( head != null) { tpWaitCallBack = head; tpHead = head._next; tpCount--; if(tpCount == 0) { BCLDebug.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); } } return tpWaitCallBack; } public uint GetQueueCount() { return tpCount; } } internal sealed class RegisteredWaitHandleSafe : CriticalFinalizerObject { private static readonly IntPtr InvalidHandle = 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; } [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); } } } [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); } ~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 race 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 race // 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); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void WaitHandleCleanupNative(IntPtr handle); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool UnregisterWaitNative(IntPtr handle, SafeHandle waitObject); } [System.Runtime.InteropServices.ComVisible(true)] public sealed class RegisteredWaitHandle : MarshalByRefObject { private RegisteredWaitHandleSafe internalRegisteredWait; internal RegisteredWaitHandle() { internalRegisteredWait = new RegisteredWaitHandleSafe(); } internal void SetHandle(IntPtr handle) { internalRegisteredWait.SetHandle(handle); } internal void SetWaitObject(WaitHandle waitObject) { internalRegisteredWait.SetWaitObject(waitObject); } [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 { 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- 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); } 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.ClearSyncContext(_executionContext); } } // 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. static internal void PerformWaitCallback(Object state) { int totTime=0; _ThreadPoolWaitCallback tpWaitCallBack = null; int startTime = Environment.TickCount; do { tpWaitCallBack = ThreadPoolGlobals.tpQueue.DeQueue(); 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(ThreadPoolGlobals.tpQueue.GetQueueCount()); 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); } 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); } } }; 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); 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.ClearSyncContext(_executionContext); } } 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 static internal void PerformWaitOrTimerCallback(Object state, bool timedOut) { _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state; BCLDebug.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 { if (timedOut) ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccbt, helper); else ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccbf, helper); } } }; [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 { [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public static bool SetMaxThreads(int workerThreads, int completionPortThreads) { return SetMaxThreadsNative(workerThreads, completionPortThreads); } public static void GetMaxThreads(out int workerThreads, out int completionPortThreads) { GetMaxThreadsNative(out workerThreads, out completionPortThreads); } [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] public static bool SetMinThreads(int workerThreads, int completionPortThreads) { // We only alert the unmanaged thread up for up to 'tpWarmupCount' work items // which is NumProcs * 2. This means that if you set the MinThreads higher // than that we don't [....] up quickly. To fix this we bump up tpWarmupCount // to be the max of the MinThreads and NumProcs * 2. This is a tatical fix // (meaning there are better, but more invasive fixes). ThreadPoolGlobals.tpWarmupCount = Math.Max(ThreadPoolGlobals.GetProcessorCount() * 2, workerThreads); return SetMinThreadsNative(workerThreads, completionPortThreads); } public static void GetMinThreads(out int workerThreads, out int completionPortThreads) { GetMinThreadsNative(out workerThreads, out completionPortThreads); } public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads) { GetAvailableThreadsNative(out workerThreads, out completionPortThreads); } [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 // ) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); } [CLSCompliant(false), SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] [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 // ) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false); } private static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException WaitHandle waitObject, WaitOrTimerCallback callBack, Object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce, // ref StackCrawlMark stackMark, bool compressStack ) { if (RemotingServices.IsTransparentProxy(waitObject)) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy")); 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; } [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 // ) { if (millisecondsTimeOutInterval < -1) throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); } [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] [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 // ) { if (millisecondsTimeOutInterval < -1) throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,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, long millisecondsTimeOutInterval, bool executeOnlyOnce // ) { if (millisecondsTimeOutInterval < -1) throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true); } [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] [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 // ) { if (millisecondsTimeOutInterval < -1) throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false); } [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); } [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] [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); } [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static bool QueueUserWorkItem( WaitCallback callBack, // Object state ) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack,state,ref stackMark,true); } [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static bool QueueUserWorkItem( WaitCallback callBack // ) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return QueueUserWorkItemHelper(callBack,null,ref stackMark,true); } [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static bool UnsafeQueueUserWorkItem( WaitCallback callBack, // 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. 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. _ThreadPoolWaitCallback tpcallBack = new _ThreadPoolWaitCallback(callBack, state, compressStack, ref stackMark); if(!ThreadPoolGlobals.vmTpInitialized) { ThreadPool.InitializeVMTp(); ThreadPoolGlobals.vmTpInitialized = true; } uint queueCount; 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(ThreadPoolGlobals.tpQueue.GetQueueCount()); } else { UpdateNativeTpCount(ThreadPoolGlobals.tpQueue.GetQueueCount()); } return success; } else { throw new ArgumentNullException("WaitCallback"); } } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool AdjustThreadsInPool(uint QueueLength); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void UpdateNativeTpCount(uint QueueLength); [MethodImplAttribute(MethodImplOptions.InternalCall)] unsafe private static extern bool PostQueuedCompletionStatus(NativeOverlapped* overlapped); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void InitializeVMTp(); [CLSCompliant(false)] [SecurityPermissionAttribute( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)] unsafe public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) { return PostQueuedCompletionStatus(overlapped); } // Native methods: [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void CompleteThreadPoolRequest(uint QueueLength); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool ShouldReturnToVm(); [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static extern bool SetAppDomainRequestActive(); [MethodImplAttribute(MethodImplOptions.InternalCall)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal static extern void ClearAppDomainRequestActive(); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsThreadPoolHosted(); [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void SetNativeTpEvent(); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern IntPtr RegisterWaitForSingleObjectNative( WaitHandle waitHandle, Object state, uint timeOutInterval, bool executeOnlyOnce, RegisteredWaitHandle registeredWaitHandle, ref StackCrawlMark stackMark, bool compressStack ); [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); } [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] public static bool BindHandle(SafeHandle osHandle) { 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; } [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. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CharEntityEncoderFallback.cs
- FormViewCommandEventArgs.cs
- SqlDataSourceSelectingEventArgs.cs
- ContextMarshalException.cs
- PeerApplication.cs
- SqlNotificationRequest.cs
- CodeCompileUnit.cs
- SequentialUshortCollection.cs
- CustomValidator.cs
- ModuleConfigurationInfo.cs
- PolyQuadraticBezierSegmentFigureLogic.cs
- XsltLoader.cs
- EntityParameter.cs
- ReferenceSchema.cs
- _Semaphore.cs
- ProcessHostServerConfig.cs
- UserPreferenceChangedEventArgs.cs
- AttachedAnnotationChangedEventArgs.cs
- FreezableOperations.cs
- DockPanel.cs
- XmlSchemaSimpleContentRestriction.cs
- ReservationNotFoundException.cs
- MemoryPressure.cs
- WebHttpDispatchOperationSelector.cs
- WindowsScrollBar.cs
- Animatable.cs
- IriParsingElement.cs
- InvalidDataException.cs
- AutomationPatternInfo.cs
- X500Name.cs
- Drawing.cs
- RepeatBehavior.cs
- ClientSettingsStore.cs
- RIPEMD160Managed.cs
- StrokeCollectionConverter.cs
- AdditionalEntityFunctions.cs
- ErasingStroke.cs
- MarginCollapsingState.cs
- OneToOneMappingSerializer.cs
- Ipv6Element.cs
- Opcode.cs
- LayoutTable.cs
- AnnotationResourceChangedEventArgs.cs
- StrongBox.cs
- TypeValidationEventArgs.cs
- Animatable.cs
- FieldCollectionEditor.cs
- ImageListImageEditor.cs
- ContentElement.cs
- MenuScrollingVisibilityConverter.cs
- ToolstripProfessionalRenderer.cs
- SqlDataSourceCommandEventArgs.cs
- XPathException.cs
- DataBoundControl.cs
- StringToken.cs
- GZipStream.cs
- ConfigurationElement.cs
- Update.cs
- ProviderConnectionPoint.cs
- CapabilitiesUse.cs
- StreamGeometry.cs
- StructuredTypeEmitter.cs
- MutexSecurity.cs
- BasicCellRelation.cs
- SimpleType.cs
- WCFServiceClientProxyGenerator.cs
- EditingCommands.cs
- AppDomainProtocolHandler.cs
- DictionaryContent.cs
- HostTimeoutsElement.cs
- RegistryKey.cs
- DecoderExceptionFallback.cs
- SortQuery.cs
- CompilerScopeManager.cs
- WorkerRequest.cs
- EntityEntry.cs
- SqlMethodTransformer.cs
- ReflectionUtil.cs
- StringFormat.cs
- documentation.cs
- UrlMappingCollection.cs
- EnvelopedSignatureTransform.cs
- ControlBuilderAttribute.cs
- ProviderCommandInfoUtils.cs
- WebBrowserContainer.cs
- RoutedUICommand.cs
- Helpers.cs
- HtmlElementErrorEventArgs.cs
- TypeToTreeConverter.cs
- SchemaImporterExtensionsSection.cs
- CatalogZoneBase.cs
- __ComObject.cs
- Propagator.Evaluator.cs
- IPPacketInformation.cs
- XmlLoader.cs
- EmbeddedMailObject.cs
- XmlSchemaCollection.cs
- ScrollBar.cs
- HGlobalSafeHandle.cs
- MeasurementDCInfo.cs