Since destroy_worker() doesn't need to sleep nor require manager_mutex, destroy_worker() can be directly called in the idle timeout handler, it helps us remove POOL_MANAGE_WORKERS and maybe_destroy_worker() and simplify the manage_workers() After POOL_MANAGE_WORKERS is removed, worker_thread() doesn't need to test whether it needs to manage after processed works. So we can remove the test branch.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -68,7 +68,6 @@ enum { · 67 unmodified lines | ||
| 68 | 68 | * manager_mutex to avoid changing binding state while |
| 69 | 69 | * create_worker() is in progress. |
| 70 | 70 | */ |
| 71 | − POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ | |
| 72 | 71 | POOL_DISASSOCIATED = 1 << 2, /* cpu can't serve workers */ |
| 73 | 72 | POOL_FREEZING = 1 << 3, /* freeze in progress */ |
| 74 | 73 | |
| @@ -752,13 +751,6 @@ static bool need_to_create_worker(struct worker_pool *pool) · 677 unmodified lines | ||
| 752 | 751 | return need_more_worker(pool) && !may_start_working(pool); |
| 753 | 752 | } |
| 754 | 753 | |
| 755 | −/* Do I need to be the manager? */ | |
| 756 | −static bool need_to_manage_workers(struct worker_pool *pool) | |
| 757 | −{ | |
| 758 | − return need_to_create_worker(pool) || | |
| 759 | − (pool->flags & POOL_MANAGE_WORKERS); | |
| 760 | −} | |
| 761 | − | |
| 762 | 754 | /* Do we have too many workers and should some go away? */ |
| 763 | 755 | static bool too_many_workers(struct worker_pool *pool) |
| 764 | 756 | { |
| @@ -1868,7 +1860,7 @@ static void idle_worker_timeout(unsigned long __pool) · 1103 unmodified lines | ||
| 1868 | 1860 | |
| 1869 | 1861 | spin_lock_irq(&pool->lock); |
| 1870 | 1862 | |
| 1871 | − if (too_many_workers(pool)) { | |
| 1863 | + while (too_many_workers(pool)) { | |
| 1872 | 1864 | struct worker *worker; |
| 1873 | 1865 | unsigned long expires; |
| 1874 | 1866 | |
| @@ -1876,13 +1868,12 @@ static void idle_worker_timeout(unsigned long __pool) · 1 unmodified line | ||
| 1876 | 1868 | worker = list_entry(pool->idle_list.prev, struct worker, entry); |
| 1877 | 1869 | expires = worker->last_active + IDLE_WORKER_TIMEOUT; |
| 1878 | 1870 | |
| 1879 | − if (time_before(jiffies, expires)) | |
| 1871 | + if (time_before(jiffies, expires)) { | |
| 1880 | 1872 | mod_timer(&pool->idle_timer, expires); |
| 1881 | − else { | |
| 1882 | − /* it's been idle for too long, wake up manager */ | |
| 1883 | − pool->flags |= POOL_MANAGE_WORKERS; | |
| 1884 | − wake_up_worker(pool); | |
| 1873 | + break; | |
| 1885 | 1874 | } |
| 1875 | + | |
| 1876 | + destroy_worker(worker); | |
| 1886 | 1877 | } |
| 1887 | 1878 | |
| 1888 | 1879 | spin_unlock_irq(&pool->lock); |
| @@ -2000,44 +1991,6 @@ restart: · 111 unmodified lines | ||
| 2000 | 1991 | return true; |
| 2001 | 1992 | } |
| 2002 | 1993 | |
| 2003 | −/** | |
| 2004 | − * maybe_destroy_worker - destroy workers which have been idle for a while | |
| 2005 | − * @pool: pool to destroy workers for | |
| 2006 | − * | |
| 2007 | − * Destroy @pool workers which have been idle for longer than | |
| 2008 | − * IDLE_WORKER_TIMEOUT. | |
| 2009 | − * | |
| 2010 | − * LOCKING: | |
| 2011 | − * spin_lock_irq(pool->lock) which may be released and regrabbed | |
| 2012 | − * multiple times. Called only from manager. | |
| 2013 | − * | |
| 2014 | − * Return: | |
| 2015 | − * %false if no action was taken and pool->lock stayed locked, %true | |
| 2016 | − * otherwise. | |
| 2017 | − */ | |
| 2018 | −static bool maybe_destroy_workers(struct worker_pool *pool) | |
| 2019 | −{ | |
| 2020 | − bool ret = false; | |
| 2021 | − | |
| 2022 | − while (too_many_workers(pool)) { | |
| 2023 | − struct worker *worker; | |
| 2024 | − unsigned long expires; | |
| 2025 | − | |
| 2026 | − worker = list_entry(pool->idle_list.prev, struct worker, entry); | |
| 2027 | − expires = worker->last_active + IDLE_WORKER_TIMEOUT; | |
| 2028 | − | |
| 2029 | − if (time_before(jiffies, expires)) { | |
| 2030 | − mod_timer(&pool->idle_timer, expires); | |
| 2031 | − break; | |
| 2032 | − } | |
| 2033 | − | |
| 2034 | − destroy_worker(worker); | |
| 2035 | − ret = true; | |
| 2036 | − } | |
| 2037 | − | |
| 2038 | − return ret; | |
| 2039 | −} | |
| 2040 | − | |
| 2041 | 1994 | /** |
| 2042 | 1995 | * manage_workers - manage worker pool |
| 2043 | 1996 | * @worker: self |
| @@ -2101,13 +2054,6 @@ static bool manage_workers(struct worker *worker) · 57 unmodified lines | ||
| 2101 | 2054 | ret = true; |
| 2102 | 2055 | } |
| 2103 | 2056 | |
| 2104 | − pool->flags &= ~POOL_MANAGE_WORKERS; | |
| 2105 | − | |
| 2106 | − /* | |
| 2107 | − * Destroy and then create so that may_start_working() is true | |
| 2108 | − * on return. | |
| 2109 | − */ | |
| 2110 | − ret |= maybe_destroy_workers(pool); | |
| 2111 | 2057 | ret |= maybe_create_worker(pool); |
| 2112 | 2058 | |
| 2113 | 2059 | mutex_unlock(&pool->manager_mutex); |
| @@ -2349,9 +2295,6 @@ recheck: · 235 unmodified lines | ||
| 2349 | 2295 | |
| 2350 | 2296 | worker_set_flags(worker, WORKER_PREP, false); |
| 2351 | 2297 | sleep: |
| 2352 | − if (unlikely(need_to_manage_workers(pool)) && manage_workers(worker)) | |
| 2353 | − goto recheck; | |
| 2354 | − | |
| 2355 | 2298 | /* |
| 2356 | 2299 | * pool->lock is held and there's no work to process and no need to |
| 2357 | 2300 | * manage, sleep. Workers are woken up only while holding |