diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-01-17 17:18:16 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-01-17 17:18:16 -0800 |
commit | 8f796906dea53c746182d3f19942ed9896500883 (patch) | |
tree | 641870cb66bc0717abb87e8aa3e639a7f368f107 /kernel | |
parent | caa1907eb3f489ce584a917ba424cf19779035c2 (diff) | |
parent | d1f21a7e9c9ac92a7b6bf11874af6b421f144d92 (diff) |
Merge "workqueue: fix possible livelock with concurrent mod_delayed_work()"
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/workqueue.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 316b316c7528..c0ab232e3abd 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -49,6 +49,7 @@ #include <linux/moduleparam.h> #include <linux/uaccess.h> #include <linux/bug.h> +#include <linux/delay.h> #include "workqueue_internal.h" @@ -1285,6 +1286,12 @@ fail: if (work_is_canceling(work)) return -ENOENT; cpu_relax(); + /* + * The queueing is in progress in another context. If we keep + * taking the pool->lock in a busy loop, the other context may + * never get the lock. Give 1 usec delay to avoid this contention. + */ + udelay(1); return -EAGAIN; } |