Commit ccdec921 authored by Xuewen Yan's avatar Xuewen Yan Committed by Tejun Heo

workqueue: Control intensive warning threshold through cmdline

When CONFIG_WQ_CPU_INTENSIVE_REPORT is set, the kernel will report
the work functions which violate the intensive_threshold_us repeatedly.
And now, only when the violate times exceed 4 and is a power of 2,
the kernel warning could be triggered.

However, sometimes, even if a long work execution time occurs only once,
it may cause other work to be delayed for a long time. This may also
cause some problems sometimes.

In order to freely control the threshold of warninging, a boot argument
is added so that the user can control the warning threshold to be printed.
At the same time, keep the exponential backoff to prevent reporting too much.

By default, the warning threshold is 4.

tj: Updated kernel-parameters.txt description.
Signed-off-by: default avatarXuewen Yan <xuewen.yan@unisoc.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent bccdc1fa
...@@ -7219,6 +7219,15 @@ ...@@ -7219,6 +7219,15 @@
threshold repeatedly. They are likely good threshold repeatedly. They are likely good
candidates for using WQ_UNBOUND workqueues instead. candidates for using WQ_UNBOUND workqueues instead.
workqueue.cpu_intensive_warning_thresh=<uint>
If CONFIG_WQ_CPU_INTENSIVE_REPORT is set, the kernel
will report the work functions which violate the
intensive_threshold_us repeatedly. In order to prevent
spurious warnings, start printing only after a work
function has violated this threshold number of times.
The default is 4 times. 0 disables the warning.
workqueue.power_efficient workqueue.power_efficient
Per-cpu workqueues are generally preferred because Per-cpu workqueues are generally preferred because
they show better performance thanks to cache they show better performance thanks to cache
......
...@@ -409,6 +409,10 @@ static const char *wq_affn_names[WQ_AFFN_NR_TYPES] = { ...@@ -409,6 +409,10 @@ static const char *wq_affn_names[WQ_AFFN_NR_TYPES] = {
*/ */
static unsigned long wq_cpu_intensive_thresh_us = ULONG_MAX; static unsigned long wq_cpu_intensive_thresh_us = ULONG_MAX;
module_param_named(cpu_intensive_thresh_us, wq_cpu_intensive_thresh_us, ulong, 0644); module_param_named(cpu_intensive_thresh_us, wq_cpu_intensive_thresh_us, ulong, 0644);
#ifdef CONFIG_WQ_CPU_INTENSIVE_REPORT
static unsigned int wq_cpu_intensive_warning_thresh = 4;
module_param_named(cpu_intensive_warning_thresh, wq_cpu_intensive_warning_thresh, uint, 0644);
#endif
/* see the comment above the definition of WQ_POWER_EFFICIENT */ /* see the comment above the definition of WQ_POWER_EFFICIENT */
static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT); static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT);
...@@ -1327,11 +1331,13 @@ static void wq_cpu_intensive_report(work_func_t func) ...@@ -1327,11 +1331,13 @@ static void wq_cpu_intensive_report(work_func_t func)
u64 cnt; u64 cnt;
/* /*
* Start reporting from the fourth time and back off * Start reporting from the warning_thresh and back off
* exponentially. * exponentially.
*/ */
cnt = atomic64_inc_return_relaxed(&ent->cnt); cnt = atomic64_inc_return_relaxed(&ent->cnt);
if (cnt >= 4 && is_power_of_2(cnt)) if (wq_cpu_intensive_warning_thresh &&
cnt >= wq_cpu_intensive_warning_thresh &&
is_power_of_2(cnt + 1 - wq_cpu_intensive_warning_thresh))
printk_deferred(KERN_WARNING "workqueue: %ps hogged CPU for >%luus %llu times, consider switching to WQ_UNBOUND\n", printk_deferred(KERN_WARNING "workqueue: %ps hogged CPU for >%luus %llu times, consider switching to WQ_UNBOUND\n",
ent->func, wq_cpu_intensive_thresh_us, ent->func, wq_cpu_intensive_thresh_us,
atomic64_read(&ent->cnt)); atomic64_read(&ent->cnt));
...@@ -1360,10 +1366,12 @@ static void wq_cpu_intensive_report(work_func_t func) ...@@ -1360,10 +1366,12 @@ static void wq_cpu_intensive_report(work_func_t func)
ent = &wci_ents[wci_nr_ents++]; ent = &wci_ents[wci_nr_ents++];
ent->func = func; ent->func = func;
atomic64_set(&ent->cnt, 1); atomic64_set(&ent->cnt, 0);
hash_add_rcu(wci_hash, &ent->hash_node, (unsigned long)func); hash_add_rcu(wci_hash, &ent->hash_node, (unsigned long)func);
raw_spin_unlock(&wci_lock); raw_spin_unlock(&wci_lock);
goto restart;
} }
#else /* CONFIG_WQ_CPU_INTENSIVE_REPORT */ #else /* CONFIG_WQ_CPU_INTENSIVE_REPORT */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment