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.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -66,6 +66,7 @@ enum { · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | /* pool flags */ |
| 68 | 68 | POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ |
| 69 | + POOL_MANAGING_WORKERS = 1 << 1, /* managing workers */ | |
| 69 | 70 | |
| 70 | 71 | /* worker flags */ |
| 71 | 72 | WORKER_STARTED = 1 << 0, /* started */ |
| @@ -652,7 +653,7 @@ static bool need_to_manage_workers(struct worker_pool *pool) · 580 unmodified lines | ||
| 652 | 653 | /* Do we have too many workers and should some go away? */ |
| 653 | 654 | static 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 | 657 | int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ |
| 657 | 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 | 1828 | if (!mutex_trylock(&pool->manager_mutex)) |
| 1828 | 1829 | return ret; |
| 1829 | 1830 | |
| 1831 | + pool->flags |= POOL_MANAGING_WORKERS; | |
| 1830 | 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 | 1838 | ret |= maybe_destroy_workers(pool); |
| 1837 | 1839 | ret |= maybe_create_worker(pool); |
| 1838 | 1840 | |
| 1841 | + pool->flags &= ~POOL_MANAGING_WORKERS; | |
| 1839 | 1842 | mutex_unlock(&pool->manager_mutex); |
| 1840 | 1843 | return ret; |
| 1841 | 1844 | } |