diff options
author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2014-05-20 05:46:32 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-05-20 10:59:31 -0400 |
commit | 7cda9aae0596d871a8d7a6888d7b447c60e5ab30 (patch) | |
tree | 5d450fd3e3fa5ea46d888543731bd027074e2961 /kernel/workqueue.c | |
parent | da028469ba173e9c634b6ecf80bb0c69c7d1024d (diff) |
workqueue: convert worker_idr to worker_ida
We no longer iterate workers via worker_idr and worker_idr is used
only for allocating/freeing ID, so we can convert it to worker_ida.
By using ida_simple_get/remove(), worker_ida doesn't require external
synchronization, so we don't need manager_mutex to protect it and the
ID-removal code is allowed to be moved out from
worker_detach_from_pool().
In a later patch, worker_detach_from_pool() will be used in rescuers
which don't have IDs, so we move the ID-removal code out from
worker_detach_from_pool() into worker_thread().
tj: Minor description updates.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 20 |
1 files changed, 8 insertions, 12 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a6c38b717957..092f2098746d 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -161,10 +161,11 @@ struct worker_pool { | |||
161 | /* see manage_workers() for details on the two manager mutexes */ | 161 | /* see manage_workers() for details on the two manager mutexes */ |
162 | struct mutex manager_arb; /* manager arbitration */ | 162 | struct mutex manager_arb; /* manager arbitration */ |
163 | struct mutex manager_mutex; /* manager exclusion */ | 163 | struct mutex manager_mutex; /* manager exclusion */ |
164 | struct idr worker_idr; /* M: worker IDs */ | ||
165 | struct list_head workers; /* M: attached workers */ | 164 | struct list_head workers; /* M: attached workers */ |
166 | struct completion *detach_completion; /* all workers detached */ | 165 | struct completion *detach_completion; /* all workers detached */ |
167 | 166 | ||
167 | struct ida worker_ida; /* worker IDs for task name */ | ||
168 | |||
168 | struct workqueue_attrs *attrs; /* I: worker attributes */ | 169 | struct workqueue_attrs *attrs; /* I: worker attributes */ |
169 | struct hlist_node hash_node; /* PL: unbound_pool_hash node */ | 170 | struct hlist_node hash_node; /* PL: unbound_pool_hash node */ |
170 | int refcnt; /* PL: refcnt for unbound pools */ | 171 | int refcnt; /* PL: refcnt for unbound pools */ |
@@ -1696,7 +1697,6 @@ static void worker_detach_from_pool(struct worker *worker, | |||
1696 | struct completion *detach_completion = NULL; | 1697 | struct completion *detach_completion = NULL; |
1697 | 1698 | ||
1698 | mutex_lock(&pool->manager_mutex); | 1699 | mutex_lock(&pool->manager_mutex); |
1699 | idr_remove(&pool->worker_idr, worker->id); | ||
1700 | list_del(&worker->node); | 1700 | list_del(&worker->node); |
1701 | if (list_empty(&pool->workers)) | 1701 | if (list_empty(&pool->workers)) |
1702 | detach_completion = pool->detach_completion; | 1702 | detach_completion = pool->detach_completion; |
@@ -1727,11 +1727,8 @@ static struct worker *create_worker(struct worker_pool *pool) | |||
1727 | 1727 | ||
1728 | lockdep_assert_held(&pool->manager_mutex); | 1728 | lockdep_assert_held(&pool->manager_mutex); |
1729 | 1729 | ||
1730 | /* | 1730 | /* ID is needed to determine kthread name */ |
1731 | * ID is needed to determine kthread name. Allocate ID first | 1731 | id = ida_simple_get(&pool->worker_ida, 0, 0, GFP_KERNEL); |
1732 | * without installing the pointer. | ||
1733 | */ | ||
1734 | id = idr_alloc(&pool->worker_idr, NULL, 0, 0, GFP_KERNEL); | ||
1735 | if (id < 0) | 1732 | if (id < 0) |
1736 | goto fail; | 1733 | goto fail; |
1737 | 1734 | ||
@@ -1772,8 +1769,6 @@ static struct worker *create_worker(struct worker_pool *pool) | |||
1772 | if (pool->flags & POOL_DISASSOCIATED) | 1769 | if (pool->flags & POOL_DISASSOCIATED) |
1773 | worker->flags |= WORKER_UNBOUND; | 1770 | worker->flags |= WORKER_UNBOUND; |
1774 | 1771 | ||
1775 | /* successful, commit the pointer to idr */ | ||
1776 | idr_replace(&pool->worker_idr, worker, worker->id); | ||
1777 | /* successful, attach the worker to the pool */ | 1772 | /* successful, attach the worker to the pool */ |
1778 | list_add_tail(&worker->node, &pool->workers); | 1773 | list_add_tail(&worker->node, &pool->workers); |
1779 | 1774 | ||
@@ -1781,7 +1776,7 @@ static struct worker *create_worker(struct worker_pool *pool) | |||
1781 | 1776 | ||
1782 | fail: | 1777 | fail: |
1783 | if (id >= 0) | 1778 | if (id >= 0) |
1784 | idr_remove(&pool->worker_idr, id); | 1779 | ida_simple_remove(&pool->worker_ida, id); |
1785 | kfree(worker); | 1780 | kfree(worker); |
1786 | return NULL; | 1781 | return NULL; |
1787 | } | 1782 | } |
@@ -2250,6 +2245,7 @@ woke_up: | |||
2250 | worker->task->flags &= ~PF_WQ_WORKER; | 2245 | worker->task->flags &= ~PF_WQ_WORKER; |
2251 | 2246 | ||
2252 | set_task_comm(worker->task, "kworker/dying"); | 2247 | set_task_comm(worker->task, "kworker/dying"); |
2248 | ida_simple_remove(&pool->worker_ida, worker->id); | ||
2253 | worker_detach_from_pool(worker, pool); | 2249 | worker_detach_from_pool(worker, pool); |
2254 | kfree(worker); | 2250 | kfree(worker); |
2255 | return 0; | 2251 | return 0; |
@@ -3486,9 +3482,9 @@ static int init_worker_pool(struct worker_pool *pool) | |||
3486 | 3482 | ||
3487 | mutex_init(&pool->manager_arb); | 3483 | mutex_init(&pool->manager_arb); |
3488 | mutex_init(&pool->manager_mutex); | 3484 | mutex_init(&pool->manager_mutex); |
3489 | idr_init(&pool->worker_idr); | ||
3490 | INIT_LIST_HEAD(&pool->workers); | 3485 | INIT_LIST_HEAD(&pool->workers); |
3491 | 3486 | ||
3487 | ida_init(&pool->worker_ida); | ||
3492 | INIT_HLIST_NODE(&pool->hash_node); | 3488 | INIT_HLIST_NODE(&pool->hash_node); |
3493 | pool->refcnt = 1; | 3489 | pool->refcnt = 1; |
3494 | 3490 | ||
@@ -3503,7 +3499,7 @@ static void rcu_free_pool(struct rcu_head *rcu) | |||
3503 | { | 3499 | { |
3504 | struct worker_pool *pool = container_of(rcu, struct worker_pool, rcu); | 3500 | struct worker_pool *pool = container_of(rcu, struct worker_pool, rcu); |
3505 | 3501 | ||
3506 | idr_destroy(&pool->worker_idr); | 3502 | ida_destroy(&pool->worker_ida); |
3507 | free_workqueue_attrs(pool->attrs); | 3503 | free_workqueue_attrs(pool->attrs); |
3508 | kfree(pool); | 3504 | kfree(pool); |
3509 | } | 3505 | } |