summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-01-17 17:18:16 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-01-17 17:18:16 -0800
commit8f796906dea53c746182d3f19942ed9896500883 (patch)
tree641870cb66bc0717abb87e8aa3e639a7f368f107 /kernel
parentcaa1907eb3f489ce584a917ba424cf19779035c2 (diff)
parentd1f21a7e9c9ac92a7b6bf11874af6b421f144d92 (diff)
Merge "workqueue: fix possible livelock with concurrent mod_delayed_work()"
Diffstat (limited to 'kernel')
-rw-r--r--kernel/workqueue.c7
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;
}