diff options
author | Koundinya Veluri <kouvel@microsoft.com> | 2017-09-29 10:48:22 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2017-09-29 17:33:57 +0300 |
commit | d354a5fabb06cfeacb9c4bccc77c67ee15ec144f (patch) | |
tree | e5223980e4a35cd1255e8705edfac7476e413677 | |
parent | 18eab6069612f6664483865d3df8d1b3a565b573 (diff) |
Revert a change to thread requests that was reverted in CoreCLR
CoreCLR revert commit: b8dda0cbf7eae770fc685378ad7c542e2468a209
One of the two commits that were reverted in the commit above was merged into this PR. It was causing issues with a missing thread request.
-rw-r--r-- | src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs | 82 |
1 files changed, 19 insertions, 63 deletions
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs index 2c382076c..e1db16f85 100644 --- a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs +++ b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs @@ -58,12 +58,6 @@ namespace System.Threading public static WorkStealingQueue[] Queues => _queues; - // Track whether the WorkStealingQueueList is empty - // Three states simplifies race conditions. They may be considered. - // Now Active --> Maybe Inactive -> Confirmed Inactive - public const int WsqNowActive = 2; - public static int wsqActive; - public static void Add(WorkStealingQueue queue) { Debug.Assert(queue != null); @@ -386,6 +380,7 @@ namespace System.Threading missedSteal = true; } + return null; } } @@ -451,18 +446,6 @@ namespace System.Threading if (null != tl) { tl.workStealingQueue.LocalPush(callback); - - // We must guarantee wsqActive is set to WsqNowActive after we push - // The ordering must be global because we rely on other threads - // observing in this order - Interlocked.MemoryBarrier(); - - // We do not want to simply write. We want to prevent unnecessary writes - // which would invalidate reader's caches - if (WorkStealingQueueList.wsqActive != WorkStealingQueueList.WsqNowActive) - { - Volatile.Write(ref WorkStealingQueueList.wsqActive, WorkStealingQueueList.WsqNowActive); - } } else { @@ -480,56 +463,33 @@ namespace System.Threading public IThreadPoolWorkItem Dequeue(ThreadPoolWorkQueueThreadLocals tl, ref bool missedSteal) { + WorkStealingQueue localWsq = tl.workStealingQueue; IThreadPoolWorkItem callback; - int wsqActiveObserved = WorkStealingQueueList.wsqActive; - if (wsqActiveObserved > 0) - { - WorkStealingQueue localWsq = tl.workStealingQueue; - if ((callback = localWsq.LocalPop()) == null && // first try the local queue - !workItems.TryDequeue(out callback)) // then try the global queue + if ((callback = localWsq.LocalPop()) == null && // first try the local queue + !workItems.TryDequeue(out callback)) // then try the global queue + { + // finally try to steal from another thread's local queue + WorkStealingQueue[] queues = WorkStealingQueueList.Queues; + int c = queues.Length; + Debug.Assert(c > 0, "There must at least be a queue for this thread."); + int maxIndex = c - 1; + int i = tl.random.Next(c); + while (c > 0) { - // finally try to steal from another thread's local queue - WorkStealingQueue[] queues = WorkStealingQueueList.Queues; - int c = queues.Length; - Debug.Assert(c > 0, "There must at least be a queue for this thread."); - int maxIndex = c - 1; - int i = tl.random.Next(c); - while (c > 0) + i = (i < maxIndex) ? i + 1 : 0; + WorkStealingQueue otherQueue = queues[i]; + if (otherQueue != localWsq && otherQueue.CanSteal) { - i = (i < maxIndex) ? i + 1 : 0; - WorkStealingQueue otherQueue = queues[i]; - if (otherQueue != localWsq && otherQueue.CanSteal) + callback = otherQueue.TrySteal(ref missedSteal); + if (callback != null) { - callback = otherQueue.TrySteal(ref missedSteal); - if (callback != null) - { - break; - } + break; } - c--; - } - if ((callback == null) && !missedSteal) - { - // Only decrement if the value is unchanged since we started looking for work - // This prevents multiple threads decrementing based on overlapping scans. - // - // When we decrement from active, the producer may have inserted a queue item during our scan - // therefore we cannot transition to empty - // - // When we decrement from Maybe Inactive, if the producer inserted a queue item during our scan, - // the producer must write Active. We may transition to empty briefly if we beat the - // producer's write, but the producer will then overwrite us before waking threads. - // So effectively we cannot mark the queue empty when an item is in the queue. - Interlocked.CompareExchange(ref WorkStealingQueueList.wsqActive, wsqActiveObserved - 1, wsqActiveObserved); } + c--; } } - else - { - // We only need to look at the global queue since WorkStealingQueueList is inactive - workItems.TryDequeue(out callback); - } return callback; } @@ -642,7 +602,6 @@ namespace System.Threading } } - // Simple random number generator. We don't need great randomness, we just need a little and for it to be fast. internal struct FastRandom // xorshift prng { @@ -668,14 +627,12 @@ namespace System.Threading } } - // Holds a WorkStealingQueue, and remmoves it from the list when this object is no longer referened. internal sealed class ThreadPoolWorkQueueThreadLocals { [ThreadStatic] public static ThreadPoolWorkQueueThreadLocals threadLocals; - public readonly ThreadPoolWorkQueue workQueue; public readonly ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue; public FastRandom random = new FastRandom(Environment.CurrentManagedThreadId); // mutable struct, do not copy or make readonly @@ -802,7 +759,6 @@ namespace System.Threading } } - internal sealed class QueueUserWorkItemCallbackDefaultContext : IThreadPoolWorkItem { private WaitCallback callback; |