aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2012-09-10 13:03:33 -0400
committerTejun Heo <tj@kernel.org>2012-09-10 13:04:54 -0400
commit552a37e9360a293cd20e7f8ff1fb326a244c5f1e (patch)
tree00d89d5778d4ab8320f6bf24d81e33a290f9fcb1
parentec58815ab0409a921a7c9744eb4ca44866b14d71 (diff)
workqueue: restore POOL_MANAGING_WORKERS
This patch restores POOL_MANAGING_WORKERS which was replaced by pool->manager_mutex by 6037315269 "workqueue: use mutex for global_cwq manager exclusion". There's a subtle idle worker depletion bug across CPU hotplug events and we need to distinguish an actual manager and CPU hotplug preventing management. POOL_MANAGING_WORKERS will be used for the former and manager_mutex the later. This patch just lays POOL_MANAGING_WORKERS on top of the existing manager_mutex and doesn't introduce any synchronization changes. The next patch will update it. Note that this patch fixes a non-critical anomaly where too_many_workers() may return %true spuriously while CPU hotplug is in progress. While the issue could schedule idle timer spuriously, it didn't trigger any actual misbehavior. tj: Rewrote patch description. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--kernel/workqueue.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index dc7b8458e275..383548ed0b54 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -66,6 +66,7 @@ enum {
66 66
67 /* pool flags */ 67 /* pool flags */
68 POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ 68 POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */
69 POOL_MANAGING_WORKERS = 1 << 1, /* managing workers */
69 70
70 /* worker flags */ 71 /* worker flags */
71 WORKER_STARTED = 1 << 0, /* started */ 72 WORKER_STARTED = 1 << 0, /* started */
@@ -652,7 +653,7 @@ static bool need_to_manage_workers(struct worker_pool *pool)
652/* Do we have too many workers and should some go away? */ 653/* Do we have too many workers and should some go away? */
653static bool too_many_workers(struct worker_pool *pool) 654static bool too_many_workers(struct worker_pool *pool)
654{ 655{
655 bool managing = mutex_is_locked(&pool->manager_mutex); 656 bool managing = pool->flags & POOL_MANAGING_WORKERS;
656 int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ 657 int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
657 int nr_busy = pool->nr_workers - nr_idle; 658 int nr_busy = pool->nr_workers - nr_idle;
658 659
@@ -1827,6 +1828,7 @@ static bool manage_workers(struct worker *worker)
1827 if (!mutex_trylock(&pool->manager_mutex)) 1828 if (!mutex_trylock(&pool->manager_mutex))
1828 return ret; 1829 return ret;
1829 1830
1831 pool->flags |= POOL_MANAGING_WORKERS;
1830 pool->flags &= ~POOL_MANAGE_WORKERS; 1832 pool->flags &= ~POOL_MANAGE_WORKERS;
1831 1833
1832 /* 1834 /*
@@ -1836,6 +1838,7 @@ static bool manage_workers(struct worker *worker)
1836 ret |= maybe_destroy_workers(pool); 1838 ret |= maybe_destroy_workers(pool);
1837 ret |= maybe_create_worker(pool); 1839 ret |= maybe_create_worker(pool);
1838 1840
1841 pool->flags &= ~POOL_MANAGING_WORKERS;
1839 mutex_unlock(&pool->manager_mutex); 1842 mutex_unlock(&pool->manager_mutex);
1840 return ret; 1843 return ret;
1841} 1844}