aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-03-13 22:47:39 -0400
committerTejun Heo <tj@kernel.org>2013-03-13 22:47:39 -0400
commitbc3a1afc92aea46d6df18d38e5d15867b17c69f6 (patch)
tree0436a0916d33ef4b8a9acdaca0584f0a8f935327 /kernel/workqueue.c
parent8425e3d5bdbe8e741d2c73cf3189ed59b4038b84 (diff)
workqueue: rename worker_pool->assoc_mutex to ->manager_mutex
Manager operations are currently governed by two mutexes - pool->manager_arb and ->assoc_mutex. The former is used to decide who gets to be the manager and the latter to exclude the actual manager operations including creation and destruction of workers. Anyone who grabs ->manager_arb must perform manager role; otherwise, the pool might stall. Grabbing ->assoc_mutex blocks everyone else from performing manager operations but doesn't require the holder to perform manager duties as it's merely blocking manager operations without becoming the manager. Because the blocking was necessary when [dis]associating per-cpu workqueues during CPU hotplug events, the latter was named assoc_mutex. The mutex is scheduled to be used for other purposes, so this patch gives it a more fitting generic name - manager_mutex - and updates / adds comments to explain synchronization around the manager role and operations. This patch is pure rename / doc update. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index f37421fb4f35..bc25bdfb4b42 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -60,8 +60,8 @@ enum {
60 * %WORKER_UNBOUND set and concurrency management disabled, and may 60 * %WORKER_UNBOUND set and concurrency management disabled, and may
61 * be executing on any CPU. The pool behaves as an unbound one. 61 * be executing on any CPU. The pool behaves as an unbound one.
62 * 62 *
63 * Note that DISASSOCIATED can be flipped only while holding 63 * Note that DISASSOCIATED should be flipped only while holding
64 * assoc_mutex to avoid changing binding state while 64 * manager_mutex to avoid changing binding state while
65 * create_worker() is in progress. 65 * create_worker() is in progress.
66 */ 66 */
67 POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ 67 POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */
@@ -149,8 +149,9 @@ struct worker_pool {
149 DECLARE_HASHTABLE(busy_hash, BUSY_WORKER_HASH_ORDER); 149 DECLARE_HASHTABLE(busy_hash, BUSY_WORKER_HASH_ORDER);
150 /* L: hash of busy workers */ 150 /* L: hash of busy workers */
151 151
152 /* see manage_workers() for details on the two manager mutexes */
152 struct mutex manager_arb; /* manager arbitration */ 153 struct mutex manager_arb; /* manager arbitration */
153 struct mutex assoc_mutex; /* protect POOL_DISASSOCIATED */ 154 struct mutex manager_mutex; /* manager exclusion */
154 struct ida worker_ida; /* L: for worker IDs */ 155 struct ida worker_ida; /* L: for worker IDs */
155 156
156 struct workqueue_attrs *attrs; /* I: worker attributes */ 157 struct workqueue_attrs *attrs; /* I: worker attributes */
@@ -1635,7 +1636,7 @@ static void rebind_workers(struct worker_pool *pool)
1635 struct worker *worker, *n; 1636 struct worker *worker, *n;
1636 int i; 1637 int i;
1637 1638
1638 lockdep_assert_held(&pool->assoc_mutex); 1639 lockdep_assert_held(&pool->manager_mutex);
1639 lockdep_assert_held(&pool->lock); 1640 lockdep_assert_held(&pool->lock);
1640 1641
1641 /* dequeue and kick idle ones */ 1642 /* dequeue and kick idle ones */
@@ -2022,31 +2023,44 @@ static bool manage_workers(struct worker *worker)
2022 struct worker_pool *pool = worker->pool; 2023 struct worker_pool *pool = worker->pool;
2023 bool ret = false; 2024 bool ret = false;
2024 2025
2026 /*
2027 * Managership is governed by two mutexes - manager_arb and
2028 * manager_mutex. manager_arb handles arbitration of manager role.
2029 * Anyone who successfully grabs manager_arb wins the arbitration
2030 * and becomes the manager. mutex_trylock() on pool->manager_arb
2031 * failure while holding pool->lock reliably indicates that someone
2032 * else is managing the pool and the worker which failed trylock
2033 * can proceed to executing work items. This means that anyone
2034 * grabbing manager_arb is responsible for actually performing
2035 * manager duties. If manager_arb is grabbed and released without
2036 * actual management, the pool may stall indefinitely.
2037 *
2038 * manager_mutex is used for exclusion of actual management
2039 * operations. The holder of manager_mutex can be sure that none
2040 * of management operations, including creation and destruction of
2041 * workers, won't take place until the mutex is released. Because
2042 * manager_mutex doesn't interfere with manager role arbitration,
2043 * it is guaranteed that the pool's management, while may be
2044 * delayed, won't be disturbed by someone else grabbing
2045 * manager_mutex.
2046 */
2025 if (!mutex_trylock(&pool->manager_arb)) 2047 if (!mutex_trylock(&pool->manager_arb))
2026 return ret; 2048 return ret;
2027 2049
2028 /* 2050 /*
2029 * To simplify both worker management and CPU hotplug, hold off 2051 * With manager arbitration won, manager_mutex would be free in
2030 * management while hotplug is in progress. CPU hotplug path can't 2052 * most cases. trylock first without dropping @pool->lock.
2031 * grab @pool->manager_arb to achieve this because that can lead to
2032 * idle worker depletion (all become busy thinking someone else is
2033 * managing) which in turn can result in deadlock under extreme
2034 * circumstances. Use @pool->assoc_mutex to synchronize manager
2035 * against CPU hotplug.
2036 *
2037 * assoc_mutex would always be free unless CPU hotplug is in
2038 * progress. trylock first without dropping @pool->lock.
2039 */ 2053 */
2040 if (unlikely(!mutex_trylock(&pool->assoc_mutex))) { 2054 if (unlikely(!mutex_trylock(&pool->manager_mutex))) {
2041 spin_unlock_irq(&pool->lock); 2055 spin_unlock_irq(&pool->lock);
2042 mutex_lock(&pool->assoc_mutex); 2056 mutex_lock(&pool->manager_mutex);
2043 /* 2057 /*
2044 * CPU hotplug could have happened while we were waiting 2058 * CPU hotplug could have happened while we were waiting
2045 * for assoc_mutex. Hotplug itself can't handle us 2059 * for assoc_mutex. Hotplug itself can't handle us
2046 * because manager isn't either on idle or busy list, and 2060 * because manager isn't either on idle or busy list, and
2047 * @pool's state and ours could have deviated. 2061 * @pool's state and ours could have deviated.
2048 * 2062 *
2049 * As hotplug is now excluded via assoc_mutex, we can 2063 * As hotplug is now excluded via manager_mutex, we can
2050 * simply try to bind. It will succeed or fail depending 2064 * simply try to bind. It will succeed or fail depending
2051 * on @pool's current state. Try it and adjust 2065 * on @pool's current state. Try it and adjust
2052 * %WORKER_UNBOUND accordingly. 2066 * %WORKER_UNBOUND accordingly.
@@ -2068,7 +2082,7 @@ static bool manage_workers(struct worker *worker)
2068 ret |= maybe_destroy_workers(pool); 2082 ret |= maybe_destroy_workers(pool);
2069 ret |= maybe_create_worker(pool); 2083 ret |= maybe_create_worker(pool);
2070 2084
2071 mutex_unlock(&pool->assoc_mutex); 2085 mutex_unlock(&pool->manager_mutex);
2072 mutex_unlock(&pool->manager_arb); 2086 mutex_unlock(&pool->manager_arb);
2073 return ret; 2087 return ret;
2074} 2088}
@@ -3436,7 +3450,7 @@ static int init_worker_pool(struct worker_pool *pool)
3436 (unsigned long)pool); 3450 (unsigned long)pool);
3437 3451
3438 mutex_init(&pool->manager_arb); 3452 mutex_init(&pool->manager_arb);
3439 mutex_init(&pool->assoc_mutex); 3453 mutex_init(&pool->manager_mutex);
3440 ida_init(&pool->worker_ida); 3454 ida_init(&pool->worker_ida);
3441 3455
3442 INIT_HLIST_NODE(&pool->hash_node); 3456 INIT_HLIST_NODE(&pool->hash_node);
@@ -4076,11 +4090,11 @@ static void wq_unbind_fn(struct work_struct *work)
4076 for_each_cpu_worker_pool(pool, cpu) { 4090 for_each_cpu_worker_pool(pool, cpu) {
4077 WARN_ON_ONCE(cpu != smp_processor_id()); 4091 WARN_ON_ONCE(cpu != smp_processor_id());
4078 4092
4079 mutex_lock(&pool->assoc_mutex); 4093 mutex_lock(&pool->manager_mutex);
4080 spin_lock_irq(&pool->lock); 4094 spin_lock_irq(&pool->lock);
4081 4095
4082 /* 4096 /*
4083 * We've claimed all manager positions. Make all workers 4097 * We've blocked all manager operations. Make all workers
4084 * unbound and set DISASSOCIATED. Before this, all workers 4098 * unbound and set DISASSOCIATED. Before this, all workers
4085 * except for the ones which are still executing works from 4099 * except for the ones which are still executing works from
4086 * before the last CPU down must be on the cpu. After 4100 * before the last CPU down must be on the cpu. After
@@ -4095,7 +4109,7 @@ static void wq_unbind_fn(struct work_struct *work)
4095 pool->flags |= POOL_DISASSOCIATED; 4109 pool->flags |= POOL_DISASSOCIATED;
4096 4110
4097 spin_unlock_irq(&pool->lock); 4111 spin_unlock_irq(&pool->lock);
4098 mutex_unlock(&pool->assoc_mutex); 4112 mutex_unlock(&pool->manager_mutex);
4099 } 4113 }
4100 4114
4101 /* 4115 /*
@@ -4152,14 +4166,14 @@ static int __cpuinit workqueue_cpu_up_callback(struct notifier_block *nfb,
4152 case CPU_DOWN_FAILED: 4166 case CPU_DOWN_FAILED:
4153 case CPU_ONLINE: 4167 case CPU_ONLINE:
4154 for_each_cpu_worker_pool(pool, cpu) { 4168 for_each_cpu_worker_pool(pool, cpu) {
4155 mutex_lock(&pool->assoc_mutex); 4169 mutex_lock(&pool->manager_mutex);
4156 spin_lock_irq(&pool->lock); 4170 spin_lock_irq(&pool->lock);
4157 4171
4158 pool->flags &= ~POOL_DISASSOCIATED; 4172 pool->flags &= ~POOL_DISASSOCIATED;
4159 rebind_workers(pool); 4173 rebind_workers(pool);
4160 4174
4161 spin_unlock_irq(&pool->lock); 4175 spin_unlock_irq(&pool->lock);
4162 mutex_unlock(&pool->assoc_mutex); 4176 mutex_unlock(&pool->manager_mutex);
4163 } 4177 }
4164 break; 4178 break;
4165 } 4179 }