History

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.

Lai Jiangshan committed 14 years ago

Commit 552a37e1 parent ec588151 file · +4 −1Browse files

Showing the changes to kernel/workqueue.c (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+4−1
@@ -66,6 +66,7 @@ enum { · 65 unmodified lines
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) · 580 unmodified lines
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) · 1168 unmodified lines
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) · 3 unmodified lines
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}