[threadpool] Decrement max_working when worker times out (mono/mono#17927)
[threadpool] Decrement max_working when worker times out
The corresponding code in CoreCLR:
https://github.com/dotnet/runtime/blob/mono/mono@
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
Commit migrated from https://github.com/mono/mono/commit/
b6a351c330836dd59f1458beecda62de6cbee3e5