Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for time-sensitive work when worker thread starvation is ongoing #61930

Merged
merged 1 commit into from
Nov 23, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ public int Count
}

internal bool loggingEnabled;
private bool _dispatchTimeSensitiveWorkFirst;
internal readonly ConcurrentQueue<object> workItems = new ConcurrentQueue<object>(); // SOS's ThreadPool command depends on this name
internal readonly ConcurrentQueue<IThreadPoolWorkItem>? timeSensitiveWorkQueue =
ThreadPool.SupportsTimeSensitiveWorkItems ? new ConcurrentQueue<IThreadPoolWorkItem>() : null;
Expand Down Expand Up @@ -594,27 +595,46 @@ internal static bool Dispatch()
// Before dequeuing the first work item, acknowledge that the thread request has been satisfied
workQueue.MarkThreadRequestSatisfied();

object? workItem;
object? workItem = null;
{
bool missedSteal = false;
workItem = workQueue.Dequeue(tl, ref missedSteal);
#pragma warning disable CS0162 // Unreachable code detected. SupportsTimeSensitiveWorkItems may be a constant in some runtimes.
if (ThreadPool.SupportsTimeSensitiveWorkItems)
{
// Alternate between checking for time-sensitive work or other work first, that way both sets of work items
// get a chance to run in situations where worker threads are starved and work items that run also take over
// the thread, sustaining starvation. For example, if time-sensitive work is always checked last here, timer
// callbacks may not run when worker threads are continually starved.
bool dispatchTimeSensitiveWorkFirst = workQueue._dispatchTimeSensitiveWorkFirst;
workQueue._dispatchTimeSensitiveWorkFirst = !dispatchTimeSensitiveWorkFirst;
if (dispatchTimeSensitiveWorkFirst)
{
workItem = workQueue.TryDequeueTimeSensitiveWorkItem();
kouvel marked this conversation as resolved.
Show resolved Hide resolved
}
}
#pragma warning restore CS0162

if (workItem == null)
{
//
// No work.
// 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. 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.
//
if (missedSteal)
bool missedSteal = false;
workItem = workQueue.Dequeue(tl, ref missedSteal);

if (workItem == null)
{
workQueue.EnsureThreadRequested();
}
//
// No work.
// 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. 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.
//
if (missedSteal)
{
workQueue.EnsureThreadRequested();
}

// Tell the VM we're returning normally, not because Hill Climbing asked us to return.
return true;
// Tell the VM we're returning normally, not because Hill Climbing asked us to return.
return true;
}
}

// A work item was successfully dequeued, and there may be more work items to process. Request a thread to
Expand Down