aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2014-05-20 05:46:28 -0400
committerTejun Heo <tj@kernel.org>2014-05-20 10:59:30 -0400
commit73eb7fe73ae303996187fff38b1c162f1df0e9d1 (patch)
treeeef7c9e2ff094ba4052e3062fbbe975c69f90914 /kernel
parent9625ab1727743f6a164df26b7b1eeeced7380b42 (diff)
workqueue: destroy_worker() should destroy idle workers only
We used to have the CPU online failure path where a worker is created and then destroyed without being started. A worker was created for the CPU coming online and if the online operation failed the created worker was shut down without being started. But this behavior was changed. The first worker is created and started at the same time for the CPU coming online. It means that we had already ensured in the code that destroy_worker() destroys only idle workers and we don't want to allow it to destroy any non-idle worker in the future. Otherwise, it may be buggy and it may be extremely hard to check. We should force destroy_worker() to destroy only idle workers explicitly. Since destroy_worker() destroys only idle workers, this patch does not change any functionality. We just need to update the comments and the sanity check code. In the sanity check code, we will refuse to destroy the worker if !(worker->flags & WORKER_IDLE). If the worker entered idle which means it is already started, so we remove the check of "worker->flags & WORKER_STARTED", after this removal, WORKER_STARTED is totally unneeded, so we remove WORKER_STARTED too. In the comments for create_worker(), "Create a new worker which is bound..." is changed to "... which is attached..." due to we change the name of this behavior to attaching. tj: Minor description / comment updates. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/workqueue.c19
1 files changed, 8 insertions, 11 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 910d963f6b76..189d79be8091 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -73,7 +73,6 @@ enum {
73 POOL_FREEZING = 1 << 3, /* freeze in progress */ 73 POOL_FREEZING = 1 << 3, /* freeze in progress */
74 74
75 /* worker flags */ 75 /* worker flags */
76 WORKER_STARTED = 1 << 0, /* started */
77 WORKER_DIE = 1 << 1, /* die die die */ 76 WORKER_DIE = 1 << 1, /* die die die */
78 WORKER_IDLE = 1 << 2, /* is idle */ 77 WORKER_IDLE = 1 << 2, /* is idle */
79 WORKER_PREP = 1 << 3, /* preparing to run works */ 78 WORKER_PREP = 1 << 3, /* preparing to run works */
@@ -1692,9 +1691,8 @@ static struct worker *alloc_worker(void)
1692 * create_worker - create a new workqueue worker 1691 * create_worker - create a new workqueue worker
1693 * @pool: pool the new worker will belong to 1692 * @pool: pool the new worker will belong to
1694 * 1693 *
1695 * Create a new worker which is bound to @pool. The returned worker 1694 * Create a new worker which is attached to @pool. The new worker must be
1696 * can be started by calling start_worker() or destroyed using 1695 * started by start_worker().
1697 * destroy_worker().
1698 * 1696 *
1699 * CONTEXT: 1697 * CONTEXT:
1700 * Might sleep. Does GFP_KERNEL allocations. 1698 * Might sleep. Does GFP_KERNEL allocations.
@@ -1778,7 +1776,6 @@ fail:
1778 */ 1776 */
1779static void start_worker(struct worker *worker) 1777static void start_worker(struct worker *worker)
1780{ 1778{
1781 worker->flags |= WORKER_STARTED;
1782 worker->pool->nr_workers++; 1779 worker->pool->nr_workers++;
1783 worker_enter_idle(worker); 1780 worker_enter_idle(worker);
1784 wake_up_process(worker->task); 1781 wake_up_process(worker->task);
@@ -1814,7 +1811,8 @@ static int create_and_start_worker(struct worker_pool *pool)
1814 * destroy_worker - destroy a workqueue worker 1811 * destroy_worker - destroy a workqueue worker
1815 * @worker: worker to be destroyed 1812 * @worker: worker to be destroyed
1816 * 1813 *
1817 * Destroy @worker and adjust @pool stats accordingly. 1814 * Destroy @worker and adjust @pool stats accordingly. The worker should
1815 * be idle.
1818 * 1816 *
1819 * CONTEXT: 1817 * CONTEXT:
1820 * spin_lock_irq(pool->lock) which is released and regrabbed. 1818 * spin_lock_irq(pool->lock) which is released and regrabbed.
@@ -1828,13 +1826,12 @@ static void destroy_worker(struct worker *worker)
1828 1826
1829 /* sanity check frenzy */ 1827 /* sanity check frenzy */
1830 if (WARN_ON(worker->current_work) || 1828 if (WARN_ON(worker->current_work) ||
1831 WARN_ON(!list_empty(&worker->scheduled))) 1829 WARN_ON(!list_empty(&worker->scheduled)) ||
1830 WARN_ON(!(worker->flags & WORKER_IDLE)))
1832 return; 1831 return;
1833 1832
1834 if (worker->flags & WORKER_STARTED) 1833 pool->nr_workers--;
1835 pool->nr_workers--; 1834 pool->nr_idle--;
1836 if (worker->flags & WORKER_IDLE)
1837 pool->nr_idle--;
1838 1835
1839 /* 1836 /*
1840 * Once WORKER_DIE is set, the kworker may destroy itself at any 1837 * Once WORKER_DIE is set, the kworker may destroy itself at any