diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 09b685daee3d..beeeac9e0e3e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -1804,8 +1804,8 @@ static void pool_mayday_timeout(unsigned long __pool) | |||
1804 | struct worker_pool *pool = (void *)__pool; | 1804 | struct worker_pool *pool = (void *)__pool; |
1805 | struct work_struct *work; | 1805 | struct work_struct *work; |
1806 | 1806 | ||
1807 | spin_lock_irq(&wq_mayday_lock); /* for wq->maydays */ | 1807 | spin_lock_irq(&pool->lock); |
1808 | spin_lock(&pool->lock); | 1808 | spin_lock(&wq_mayday_lock); /* for wq->maydays */ |
1809 | 1809 | ||
1810 | if (need_to_create_worker(pool)) { | 1810 | if (need_to_create_worker(pool)) { |
1811 | /* | 1811 | /* |
@@ -1818,8 +1818,8 @@ static void pool_mayday_timeout(unsigned long __pool) | |||
1818 | send_mayday(work); | 1818 | send_mayday(work); |
1819 | } | 1819 | } |
1820 | 1820 | ||
1821 | spin_unlock(&pool->lock); | 1821 | spin_unlock(&wq_mayday_lock); |
1822 | spin_unlock_irq(&wq_mayday_lock); | 1822 | spin_unlock_irq(&pool->lock); |
1823 | 1823 | ||
1824 | mod_timer(&pool->mayday_timer, jiffies + MAYDAY_INTERVAL); | 1824 | mod_timer(&pool->mayday_timer, jiffies + MAYDAY_INTERVAL); |
1825 | } | 1825 | } |
@@ -1841,17 +1841,11 @@ static void pool_mayday_timeout(unsigned long __pool) | |||
1841 | * spin_lock_irq(pool->lock) which may be released and regrabbed | 1841 | * spin_lock_irq(pool->lock) which may be released and regrabbed |
1842 | * multiple times. Does GFP_KERNEL allocations. Called only from | 1842 | * multiple times. Does GFP_KERNEL allocations. Called only from |
1843 | * manager. | 1843 | * manager. |
1844 | * | ||
1845 | * Return: | ||
1846 | * %false if no action was taken and pool->lock stayed locked, %true | ||
1847 | * otherwise. | ||
1848 | */ | 1844 | */ |
1849 | static bool maybe_create_worker(struct worker_pool *pool) | 1845 | static void maybe_create_worker(struct worker_pool *pool) |
1850 | __releases(&pool->lock) | 1846 | __releases(&pool->lock) |
1851 | __acquires(&pool->lock) | 1847 | __acquires(&pool->lock) |
1852 | { | 1848 | { |
1853 | if (!need_to_create_worker(pool)) | ||
1854 | return false; | ||
1855 | restart: | 1849 | restart: |
1856 | spin_unlock_irq(&pool->lock); | 1850 | spin_unlock_irq(&pool->lock); |
1857 | 1851 | ||
@@ -1877,7 +1871,6 @@ restart: | |||
1877 | */ | 1871 | */ |
1878 | if (need_to_create_worker(pool)) | 1872 | if (need_to_create_worker(pool)) |
1879 | goto restart; | 1873 | goto restart; |
1880 | return true; | ||
1881 | } | 1874 | } |
1882 | 1875 | ||
1883 | /** | 1876 | /** |
@@ -1897,16 +1890,14 @@ restart: | |||
1897 | * multiple times. Does GFP_KERNEL allocations. | 1890 | * multiple times. Does GFP_KERNEL allocations. |
1898 | * | 1891 | * |
1899 | * Return: | 1892 | * Return: |
1900 | * %false if the pool don't need management and the caller can safely start | 1893 | * %false if the pool doesn't need management and the caller can safely |
1901 | * processing works, %true indicates that the function released pool->lock | 1894 | * start processing works, %true if management function was performed and |
1902 | * and reacquired it to perform some management function and that the | 1895 | * the conditions that the caller verified before calling the function may |
1903 | * conditions that the caller verified while holding the lock before | 1896 | * no longer be true. |
1904 | * calling the function might no longer be true. | ||
1905 | */ | 1897 | */ |
1906 | static bool manage_workers(struct worker *worker) | 1898 | static bool manage_workers(struct worker *worker) |
1907 | { | 1899 | { |
1908 | struct worker_pool *pool = worker->pool; | 1900 | struct worker_pool *pool = worker->pool; |
1909 | bool ret = false; | ||
1910 | 1901 | ||
1911 | /* | 1902 | /* |
1912 | * Anyone who successfully grabs manager_arb wins the arbitration | 1903 | * Anyone who successfully grabs manager_arb wins the arbitration |
@@ -1919,12 +1910,12 @@ static bool manage_workers(struct worker *worker) | |||
1919 | * actual management, the pool may stall indefinitely. | 1910 | * actual management, the pool may stall indefinitely. |
1920 | */ | 1911 | */ |
1921 | if (!mutex_trylock(&pool->manager_arb)) | 1912 | if (!mutex_trylock(&pool->manager_arb)) |
1922 | return ret; | 1913 | return false; |
1923 | 1914 | ||
1924 | ret |= maybe_create_worker(pool); | 1915 | maybe_create_worker(pool); |
1925 | 1916 | ||
1926 | mutex_unlock(&pool->manager_arb); | 1917 | mutex_unlock(&pool->manager_arb); |
1927 | return ret; | 1918 | return true; |
1928 | } | 1919 | } |
1929 | 1920 | ||
1930 | /** | 1921 | /** |
@@ -2248,12 +2239,30 @@ repeat: | |||
2248 | * Slurp in all works issued via this workqueue and | 2239 | * Slurp in all works issued via this workqueue and |
2249 | * process'em. | 2240 | * process'em. |
2250 | */ | 2241 | */ |
2251 | WARN_ON_ONCE(!list_empty(&rescuer->scheduled)); | 2242 | WARN_ON_ONCE(!list_empty(scheduled)); |
2252 | list_for_each_entry_safe(work, n, &pool->worklist, entry) | 2243 | list_for_each_entry_safe(work, n, &pool->worklist, entry) |
2253 | if (get_work_pwq(work) == pwq) | 2244 | if (get_work_pwq(work) == pwq) |
2254 | move_linked_works(work, scheduled, &n); | 2245 | move_linked_works(work, scheduled, &n); |
2255 | 2246 | ||
2256 | process_scheduled_works(rescuer); | 2247 | if (!list_empty(scheduled)) { |
2248 | process_scheduled_works(rescuer); | ||
2249 | |||
2250 | /* | ||
2251 | * The above execution of rescued work items could | ||
2252 | * have created more to rescue through | ||
2253 | * pwq_activate_first_delayed() or chained | ||
2254 | * queueing. Let's put @pwq back on mayday list so | ||
2255 | * that such back-to-back work items, which may be | ||
2256 | * being used to relieve memory pressure, don't | ||
2257 | * incur MAYDAY_INTERVAL delay inbetween. | ||
2258 | */ | ||
2259 | if (need_to_create_worker(pool)) { | ||
2260 | spin_lock(&wq_mayday_lock); | ||
2261 | get_pwq(pwq); | ||
2262 | list_move_tail(&pwq->mayday_node, &wq->maydays); | ||
2263 | spin_unlock(&wq_mayday_lock); | ||
2264 | } | ||
2265 | } | ||
2257 | 2266 | ||
2258 | /* | 2267 | /* |
2259 | * Put the reference grabbed by send_mayday(). @pool won't | 2268 | * Put the reference grabbed by send_mayday(). @pool won't |