aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2014-05-20 05:46:27 -0400
committerTejun Heo <tj@kernel.org>2014-05-20 10:59:30 -0400
commit9625ab1727743f6a164df26b7b1eeeced7380b42 (patch)
treed3da8ffc218ca3077ebbc140eb7f345a2bae38f1
parentcf416171e7e1d966111f53bdae82f51af05e7bf8 (diff)
workqueue: use manager lock only to protect worker_idr
worker_idr is highly bound to managers and is always/only accessed in manager lock context. So we don't need pool->lock for it. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--kernel/workqueue.c34
1 files changed, 6 insertions, 28 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c8411085466f..910d963f6b76 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -124,8 +124,7 @@ enum {
124 * cpu or grabbing pool->lock is enough for read access. If 124 * cpu or grabbing pool->lock is enough for read access. If
125 * POOL_DISASSOCIATED is set, it's identical to L. 125 * POOL_DISASSOCIATED is set, it's identical to L.
126 * 126 *
127 * MG: pool->manager_mutex and pool->lock protected. Writes require both 127 * M: pool->manager_mutex protected.
128 * locks. Reads can happen under either lock.
129 * 128 *
130 * PL: wq_pool_mutex protected. 129 * PL: wq_pool_mutex protected.
131 * 130 *
@@ -164,7 +163,7 @@ struct worker_pool {
164 /* see manage_workers() for details on the two manager mutexes */ 163 /* see manage_workers() for details on the two manager mutexes */
165 struct mutex manager_arb; /* manager arbitration */ 164 struct mutex manager_arb; /* manager arbitration */
166 struct mutex manager_mutex; /* manager exclusion */ 165 struct mutex manager_mutex; /* manager exclusion */
167 struct idr worker_idr; /* MG: worker IDs and iteration */ 166 struct idr worker_idr; /* M: worker IDs and iteration */
168 167
169 struct workqueue_attrs *attrs; /* I: worker attributes */ 168 struct workqueue_attrs *attrs; /* I: worker attributes */
170 struct hlist_node hash_node; /* PL: unbound_pool_hash node */ 169 struct hlist_node hash_node; /* PL: unbound_pool_hash node */
@@ -340,16 +339,6 @@ static void copy_workqueue_attrs(struct workqueue_attrs *to,
340 lockdep_is_held(&wq->mutex), \ 339 lockdep_is_held(&wq->mutex), \
341 "sched RCU or wq->mutex should be held") 340 "sched RCU or wq->mutex should be held")
342 341
343#ifdef CONFIG_LOCKDEP
344#define assert_manager_or_pool_lock(pool) \
345 WARN_ONCE(debug_locks && \
346 !lockdep_is_held(&(pool)->manager_mutex) && \
347 !lockdep_is_held(&(pool)->lock), \
348 "pool->manager_mutex or ->lock should be held")
349#else
350#define assert_manager_or_pool_lock(pool) do { } while (0)
351#endif
352
353#define for_each_cpu_worker_pool(pool, cpu) \ 342#define for_each_cpu_worker_pool(pool, cpu) \
354 for ((pool) = &per_cpu(cpu_worker_pools, cpu)[0]; \ 343 for ((pool) = &per_cpu(cpu_worker_pools, cpu)[0]; \
355 (pool) < &per_cpu(cpu_worker_pools, cpu)[NR_STD_WORKER_POOLS]; \ 344 (pool) < &per_cpu(cpu_worker_pools, cpu)[NR_STD_WORKER_POOLS]; \
@@ -378,14 +367,14 @@ static void copy_workqueue_attrs(struct workqueue_attrs *to,
378 * @wi: integer used for iteration 367 * @wi: integer used for iteration
379 * @pool: worker_pool to iterate workers of 368 * @pool: worker_pool to iterate workers of
380 * 369 *
381 * This must be called with either @pool->manager_mutex or ->lock held. 370 * This must be called with @pool->manager_mutex.
382 * 371 *
383 * The if/else clause exists only for the lockdep assertion and can be 372 * The if/else clause exists only for the lockdep assertion and can be
384 * ignored. 373 * ignored.
385 */ 374 */
386#define for_each_pool_worker(worker, wi, pool) \ 375#define for_each_pool_worker(worker, wi, pool) \
387 idr_for_each_entry(&(pool)->worker_idr, (worker), (wi)) \ 376 idr_for_each_entry(&(pool)->worker_idr, (worker), (wi)) \
388 if (({ assert_manager_or_pool_lock((pool)); false; })) { } \ 377 if (({ lockdep_assert_held(&pool->manager_mutex); false; })) { } \
389 else 378 else
390 379
391/** 380/**
@@ -1725,13 +1714,7 @@ static struct worker *create_worker(struct worker_pool *pool)
1725 * ID is needed to determine kthread name. Allocate ID first 1714 * ID is needed to determine kthread name. Allocate ID first
1726 * without installing the pointer. 1715 * without installing the pointer.
1727 */ 1716 */
1728 idr_preload(GFP_KERNEL); 1717 id = idr_alloc(&pool->worker_idr, NULL, 0, 0, GFP_KERNEL);
1729 spin_lock_irq(&pool->lock);
1730
1731 id = idr_alloc(&pool->worker_idr, NULL, 0, 0, GFP_NOWAIT);
1732
1733 spin_unlock_irq(&pool->lock);
1734 idr_preload_end();
1735 if (id < 0) 1718 if (id < 0)
1736 goto fail; 1719 goto fail;
1737 1720
@@ -1773,18 +1756,13 @@ static struct worker *create_worker(struct worker_pool *pool)
1773 worker->flags |= WORKER_UNBOUND; 1756 worker->flags |= WORKER_UNBOUND;
1774 1757
1775 /* successful, commit the pointer to idr */ 1758 /* successful, commit the pointer to idr */
1776 spin_lock_irq(&pool->lock);
1777 idr_replace(&pool->worker_idr, worker, worker->id); 1759 idr_replace(&pool->worker_idr, worker, worker->id);
1778 spin_unlock_irq(&pool->lock);
1779 1760
1780 return worker; 1761 return worker;
1781 1762
1782fail: 1763fail:
1783 if (id >= 0) { 1764 if (id >= 0)
1784 spin_lock_irq(&pool->lock);
1785 idr_remove(&pool->worker_idr, id); 1765 idr_remove(&pool->worker_idr, id);
1786 spin_unlock_irq(&pool->lock);
1787 }
1788 kfree(worker); 1766 kfree(worker);
1789 return NULL; 1767 return NULL;
1790} 1768}