diff options
| author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2014-05-20 05:46:27 -0400 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2014-05-20 10:59:30 -0400 |
| commit | 9625ab1727743f6a164df26b7b1eeeced7380b42 (patch) | |
| tree | d3da8ffc218ca3077ebbc140eb7f345a2bae38f1 | |
| parent | cf416171e7e1d966111f53bdae82f51af05e7bf8 (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.c | 34 |
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 | ||
| 1782 | fail: | 1763 | fail: |
| 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 | } |
