// Time in ms for which ThreadPoolWorkQueue.Dispatch keeps executing work items before returning to the OS
private const uint DispatchQuantum = 30;
- private static bool GetEnableWorkerTracking()
- {
- bool enableWorkerTracking = false;
- InitializeVMTp(ref enableWorkerTracking);
- return enableWorkerTracking;
- }
+ internal static readonly bool EnableWorkerTracking = GetEnableWorkerTracking();
internal static bool KeepDispatching(int startTickCount)
{
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void NotifyWorkItemProgressNative();
- [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
- private static extern void InitializeVMTp(ref bool enableWorkerTracking);
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern bool GetEnableWorkerTracking();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern IntPtr RegisterWaitForSingleObjectNative(
FCIMPL0(VOID, ThreadPoolNative::NotifyRequestProgress)
{
FCALL_CONTRACT;
+ _ASSERTE(ThreadpoolMgr::IsInitialized()); // can't be here without requesting a thread first
ThreadpoolMgr::NotifyWorkItemCompleted();
FCIMPL0(FC_BOOL_RET, ThreadPoolNative::NotifyRequestComplete)
{
FCALL_CONTRACT;
+ _ASSERTE(ThreadpoolMgr::IsInitialized()); // can't be here without requesting a thread first
ThreadpoolMgr::NotifyWorkItemCompleted();
/*****************************************************************************************************/
-void QCALLTYPE ThreadPoolNative::InitializeVMTp(CLR_BOOL* pEnableWorkerTracking)
+FCIMPL0(FC_BOOL_RET, ThreadPoolNative::GetEnableWorkerTracking)
{
- QCALL_CONTRACT;
+ FCALL_CONTRACT;
- BEGIN_QCALL;
- ThreadpoolMgr::EnsureInitialized();
- *pEnableWorkerTracking = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ThreadPool_EnableWorkerTracking) ? TRUE : FALSE;
- END_QCALL;
+ BOOL result = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ThreadPool_EnableWorkerTracking) ? TRUE : FALSE;
+ FC_RETURN_BOOL(result);
}
+FCIMPLEND
/*****************************************************************************************************/
BEGIN_QCALL;
+ ThreadpoolMgr::EnsureInitialized();
ThreadpoolMgr::SetAppDomainRequestsActive();
res = ThreadpoolMgr::QueueUserWorkItem(NULL,
static FCDECL0(VOID, NotifyRequestProgress);
static FCDECL0(FC_BOOL_RET, NotifyRequestComplete);
- static void QCALLTYPE InitializeVMTp(CLR_BOOL* pEnableWorkerTracking);
+ static FCDECL0(FC_BOOL_RET, GetEnableWorkerTracking);
static FCDECL1(void, ReportThreadStatus, CLR_BOOL isWorking);
FCFuncElement("GetMaxThreadsNative", ThreadPoolNative::CorGetMaxThreads)
FCFuncElement("NotifyWorkItemComplete", ThreadPoolNative::NotifyRequestComplete)
FCFuncElement("NotifyWorkItemProgressNative", ThreadPoolNative::NotifyRequestProgress)
- QCFuncElement("InitializeVMTp", ThreadPoolNative::InitializeVMTp)
+ FCFuncElement("GetEnableWorkerTracking", ThreadPoolNative::GetEnableWorkerTracking)
FCFuncElement("ReportThreadStatus", ThreadPoolNative::ReportThreadStatus)
QCFuncElement("RequestWorkerThread", ThreadPoolNative::RequestWorkerThread)
FCFuncEnd()
{
CONTRACTL
{
- THROWS; // Initialize can throw
+ THROWS; // EnsureInitializedSlow can throw
MODE_ANY;
GC_NOTRIGGER;
}
if (IsInitialized())
return;
+ EnsureInitializedSlow();
+}
+
+NOINLINE void ThreadpoolMgr::EnsureInitializedSlow()
+{
+ CONTRACTL
+ {
+ THROWS; // Initialize can throw
+ MODE_ANY;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
DWORD dwSwitchCount = 0;
retry:
MODE_ANY;
}
CONTRACTL_END;
+
+ _ASSERTE(IsInitialized()); // can't be here without requesting a thread first
_ASSERTE(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ThreadPool_EnableWorkerTracking));
+
while (true)
{
WorkingThreadCounts currentCounts, newCounts;
void ThreadpoolMgr::WaitHandleCleanup(HANDLE hWaitObject)
{
LIMITED_METHOD_CONTRACT;
+ _ASSERTE(IsInitialized()); // cannot call cleanup before first registering
WaitInfo* waitInfo = (WaitInfo*) hWaitObject;
_ASSERTE(waitInfo->refCount > 0);
return entry;
}
+public:
static void EnsureInitialized();
+private:
+ static void EnsureInitializedSlow();
+
+public:
static void InitPlatformVariables();
inline static BOOL IsInitialized()
public static partial class ThreadPool
{
+ internal const bool EnableWorkerTracking = false;
+
internal static void InitializeForThreadPoolThread() { }
public static bool SetMaxThreads(int workerThreads, int completionPortThreads)
//
// Execute the workitem outside of any finally blocks, so that it can be aborted if needed.
//
- if (ThreadPool.s_enableWorkerTracking)
+#pragma warning disable CS0162 // Unreachable code detected. EnableWorkerTracking may be constant false in some runtimes.
+ if (ThreadPool.EnableWorkerTracking)
{
bool reportedStatus = false;
try
ThreadPool.ReportThreadStatus(isWorking: false);
}
}
+#pragma warning restore CS0162
else if (workItem is Task task)
{
// Check for Task first as it's currently faster to type check
public static partial class ThreadPool
{
internal static readonly ThreadPoolWorkQueue s_workQueue = new ThreadPoolWorkQueue();
- internal static readonly bool s_enableWorkerTracking = GetEnableWorkerTracking();
/// <summary>Shim used to invoke <see cref="IAsyncStateMachineBox.MoveNext"/> of the supplied <see cref="IAsyncStateMachineBox"/>.</summary>
internal static readonly Action<object?> s_invokeAsyncStateMachineBox = state =>
{
public static partial class ThreadPool
{
- private static bool GetEnableWorkerTracking() => false;
-
internal static void ReportThreadStatus(bool isWorking)
{
}