summaryrefslogtreecommitdiff
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorMichael Bestas <mkbestas@lineageos.org>2020-03-08 00:00:18 +0200
committerMichael Bestas <mkbestas@lineageos.org>2020-03-08 00:00:18 +0200
commit3010be7cfa594aac6134887b8505b3f1bd619ad4 (patch)
tree867d21a3537efafc20045dc58ffd18104f0ca474 /kernel/workqueue.c
parenta0edb0970a4d09aed24b6f37cd6fd0c545565485 (diff)
parent4db1ebdd40ec0b6ee8fb5744b20274a37aea267d (diff)
Merge branch 'android-4.4-p' of https://android.googlesource.com/kernel/common into lineage-17.1-caf-msm8998
This brings LA.UM.8.4.r1-05200-8x98.0 up to date with https://android.googlesource.com/kernel/common/ android-4.4-p at commit: 4db1ebdd40ec0 FROMLIST: HID: nintendo: add nintendo switch controller driver Conflicts: arch/arm64/boot/Makefile arch/arm64/kernel/psci.c arch/x86/configs/x86_64_cuttlefish_defconfig drivers/md/dm.c drivers/of/Kconfig drivers/thermal/thermal_core.c fs/proc/meminfo.c kernel/locking/spinlock_debug.c kernel/time/hrtimer.c net/wireless/util.c Change-Id: I5b5163497b7c6ab8487ffbb2d036e4cda01ed670
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 595701736334..696f0913ba38 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2329,8 +2329,14 @@ repeat:
*/
if (need_to_create_worker(pool)) {
spin_lock(&wq_mayday_lock);
- get_pwq(pwq);
- list_move_tail(&pwq->mayday_node, &wq->maydays);
+ /*
+ * Queue iff we aren't racing destruction
+ * and somebody else hasn't queued it already.
+ */
+ if (wq->rescuer && list_empty(&pwq->mayday_node)) {
+ get_pwq(pwq);
+ list_add_tail(&pwq->mayday_node, &wq->maydays);
+ }
spin_unlock(&wq_mayday_lock);
}
}
@@ -3983,9 +3989,29 @@ void destroy_workqueue(struct workqueue_struct *wq)
struct pool_workqueue *pwq;
int node;
+ /*
+ * Remove it from sysfs first so that sanity check failure doesn't
+ * lead to sysfs name conflicts.
+ */
+ workqueue_sysfs_unregister(wq);
+
/* drain it before proceeding with destruction */
drain_workqueue(wq);
+ /* kill rescuer, if sanity checks fail, leave it w/o rescuer */
+ if (wq->rescuer) {
+ struct worker *rescuer = wq->rescuer;
+
+ /* this prevents new queueing */
+ spin_lock_irq(&wq_mayday_lock);
+ wq->rescuer = NULL;
+ spin_unlock_irq(&wq_mayday_lock);
+
+ /* rescuer will empty maydays list before exiting */
+ kthread_stop(rescuer->task);
+ kfree(rescuer);
+ }
+
/* sanity checks */
mutex_lock(&wq->mutex);
for_each_pwq(pwq, wq) {
@@ -4015,11 +4041,6 @@ void destroy_workqueue(struct workqueue_struct *wq)
list_del_rcu(&wq->list);
mutex_unlock(&wq_pool_mutex);
- workqueue_sysfs_unregister(wq);
-
- if (wq->rescuer)
- kthread_stop(wq->rescuer->task);
-
if (!(wq->flags & WQ_UNBOUND)) {
/*
* The base ref is never dropped on per-cpu pwqs. Directly
@@ -4296,7 +4317,8 @@ static void show_pwq(struct pool_workqueue *pwq)
pr_info(" pwq %d:", pool->id);
pr_cont_pool_info(pool);
- pr_cont(" active=%d/%d%s\n", pwq->nr_active, pwq->max_active,
+ pr_cont(" active=%d/%d refcnt=%d%s\n",
+ pwq->nr_active, pwq->max_active, pwq->refcnt,
!list_empty(&pwq->mayday_node) ? " MAYDAY" : "");
hash_for_each(pool->busy_hash, bkt, worker, hentry) {