[threadpool] Decrement max_working when worker times out (#17927)
commitb6a351c330836dd59f1458beecda62de6cbee3e5
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Wed, 27 Nov 2019 21:06:17 +0000 (27 16:06 -0500)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 27 Nov 2019 21:06:17 +0000 (27 22:06 +0100)
tree29380e04a849fd4f87e48254c044b35591f964c9
parent3e369ba8c9a456d26679405e96d01ab285f697d9
[threadpool] Decrement max_working when worker times out (#17927)

[threadpool] Decrement max_working when worker times out

The corresponding code in CoreCLR:
https://github.com/dotnet/runtime/blob/bf88f146412d1e2d41779422337184a802f186c9/src/coreclr/src/vm/win32threadpool.cpp#L2156-L2164

The issue is that counter._.max_working is only ever changed by:
1. the monitor_thread when it detects starvation (increment by 1).
2. the hill climbing algorithm (increment or decrement).

Creating a periodic load of creating many workers at once followed by a minute
or more of quiescence increases the variable worker.counters._.max_working in
monitor_thread(). Once that counter matches worker.limit_worker_max,
monitor_thread() keeps looping without unparking or creating a thread, even
though the actual number of threads/workers is small. If the existing threads
are all waiting on work that needs a new thread, then a deadlock occurs.

With this change, when a parked worker times out, it will lower max_working to
the number of active (working + parked + starting) threads minus itself (but no
less than limit_worker_min). As a result, monitor_thread will only increment
max_working as long as none of the already running workers are timing out.

Attempt to address https://github.com/mono/mono/issues/17833

---

Also allow monitor_thread to start workers if there aren't enough active, even if the max worker limit has been reached.

Work around a pathological condition where the work_item_count is non-zero, and
the max_working limit has been reached, but the number of active threads is
still below the max.  In that case, unpark some workers and start some new
threads.

May address http://work.azdo.io/827206
mono/metadata/threadpool-worker-default.c