From 50ac467f03157a46ebac3a14a692f000bf8973cf Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 3 Feb 2017 08:44:48 -0500 Subject: [PATCH] Allow Dequeue to avoid TrySteal if there's nothing to steal Commit migrated from https://github.com/dotnet/coreclr/commit/b185fe7e76a4bbef989dc69f9cec29e40d9f6f13 --- .../mscorlib/src/System/Threading/ThreadPool.cs | 67 +++++++++++----------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/coreclr/src/mscorlib/src/System/Threading/ThreadPool.cs b/src/coreclr/src/mscorlib/src/System/Threading/ThreadPool.cs index 70e2fd4..9a7965e 100644 --- a/src/coreclr/src/mscorlib/src/System/Threading/ThreadPool.cs +++ b/src/coreclr/src/mscorlib/src/System/Threading/ThreadPool.cs @@ -332,48 +332,51 @@ namespace System.Threading } } + public bool CanSteal => m_headIndex < m_tailIndex; + public IThreadPoolWorkItem TrySteal(ref bool missedSteal) { while (true) { - if (m_headIndex >= m_tailIndex) - return null; - - bool taken = false; - try + if (CanSteal) { - m_foreignLock.TryEnter(ref taken); - if (taken) + bool taken = false; + try { - // 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) + m_foreignLock.TryEnter(ref taken); + if (taken) { - int idx = head & m_mask; - IThreadPoolWorkItem obj = Volatile.Read(ref m_array[idx]); + // Increment head, and ensure read of tail doesn't move before it (fence). + int head = m_headIndex; + Interlocked.Exchange(ref m_headIndex, head + 1); - // Check for nulls in the array. - if (obj == null) continue; + if (head < m_tailIndex) + { + int idx = head & m_mask; + IThreadPoolWorkItem obj = Volatile.Read(ref m_array[idx]); - m_array[idx] = null; - return obj; - } - else - { - // Failed, restore head. - m_headIndex = head; + // Check for nulls in the array. + if (obj == null) continue; + + m_array[idx] = null; + return obj; + } + else + { + // Failed, restore head. + m_headIndex = head; + } } } - } - finally - { - if (taken) - m_foreignLock.Exit(useMemoryBarrier:false); + finally + { + if (taken) + m_foreignLock.Exit(useMemoryBarrier:false); + } + + missedSteal = true; } - missedSteal = true; return null; } } @@ -462,10 +465,10 @@ namespace System.Threading public IThreadPoolWorkItem Dequeue(ThreadPoolWorkQueueThreadLocals tl, ref bool missedSteal) { - WorkStealingQueue wsq = tl.workStealingQueue; + WorkStealingQueue localWsq = tl.workStealingQueue; IThreadPoolWorkItem callback; - if (!wsq.LocalPop(out callback) && // first try the local queue + if (!localWsq.LocalPop(out callback) && // first try the local queue !workItems.TryDequeue(out callback)) // then try the global queue { // finally try to steal from another thread's local queue @@ -478,7 +481,7 @@ namespace System.Threading { i = (i < maxIndex) ? i + 1 : 0; WorkStealingQueue otherQueue = queues[i]; - if (otherQueue != wsq) + if (otherQueue != localWsq && otherQueue.CanSteal) { callback = otherQueue.TrySteal(ref missedSteal); if (callback != null) -- 2.7.4