diff options
| author | Tejun Heo <tj@kernel.org> | 2012-09-17 19:07:34 -0400 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2012-09-17 19:09:09 -0400 |
| commit | 6c1423ba5dbdab45bcd8c1bc3bc6e07fe3f6a470 (patch) | |
| tree | 3c7899ba9eee94f408faf483622faa23cbdbfed2 /kernel/workqueue.c | |
| parent | 136b5721d75a62a8f02c601c89122e32c1a85a84 (diff) | |
| parent | 960bd11bf2daf669d0d910428fd9ef5a15c3d7cb (diff) | |
Merge branch 'for-3.6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq into for-3.7
This merge is necessary as Lai's CPU hotplug restructuring series
depends on the CPU hotplug bug fixes in for-3.6-fixes.
The merge creates one trivial conflict between the following two
commits.
96e65306b8 "workqueue: UNBOUND -> REBIND morphing in rebind_workers() should be atomic"
e2b6a6d570 "workqueue: use system_highpri_wq for highpri workers in rebind_workers()"
Both add local variable definitions to the same block and can be
merged in any order.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 122 |
1 files changed, 99 insertions, 23 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 039d0fae171a..31d8a4586d4c 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 */ |
| @@ -682,7 +683,7 @@ static bool need_to_manage_workers(struct worker_pool *pool) | |||
| 682 | /* Do we have too many workers and should some go away? */ | 683 | /* Do we have too many workers and should some go away? */ |
| 683 | static bool too_many_workers(struct worker_pool *pool) | 684 | static bool too_many_workers(struct worker_pool *pool) |
| 684 | { | 685 | { |
| 685 | bool managing = mutex_is_locked(&pool->manager_mutex); | 686 | bool managing = pool->flags & POOL_MANAGING_WORKERS; |
| 686 | int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ | 687 | int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ |
| 687 | int nr_busy = pool->nr_workers - nr_idle; | 688 | int nr_busy = pool->nr_workers - nr_idle; |
| 688 | 689 | ||
| @@ -1632,6 +1633,15 @@ static void idle_worker_rebind(struct worker *worker) | |||
| 1632 | 1633 | ||
| 1633 | /* we did our part, wait for rebind_workers() to finish up */ | 1634 | /* we did our part, wait for rebind_workers() to finish up */ |
| 1634 | wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND)); | 1635 | wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND)); |
| 1636 | |||
| 1637 | /* | ||
| 1638 | * rebind_workers() shouldn't finish until all workers passed the | ||
| 1639 | * above WORKER_REBIND wait. Tell it when done. | ||
| 1640 | */ | ||
| 1641 | spin_lock_irq(&worker->pool->gcwq->lock); | ||
| 1642 | if (!--worker->idle_rebind->cnt) | ||
| 1643 | complete(&worker->idle_rebind->done); | ||
| 1644 | spin_unlock_irq(&worker->pool->gcwq->lock); | ||
| 1635 | } | 1645 | } |
| 1636 | 1646 | ||
| 1637 | /* | 1647 | /* |
| @@ -1645,8 +1655,16 @@ static void busy_worker_rebind_fn(struct work_struct *work) | |||
| 1645 | struct worker *worker = container_of(work, struct worker, rebind_work); | 1655 | struct worker *worker = container_of(work, struct worker, rebind_work); |
| 1646 | struct global_cwq *gcwq = worker->pool->gcwq; | 1656 | struct global_cwq *gcwq = worker->pool->gcwq; |
| 1647 | 1657 | ||
| 1648 | if (worker_maybe_bind_and_lock(worker)) | 1658 | worker_maybe_bind_and_lock(worker); |
| 1649 | worker_clr_flags(worker, WORKER_REBIND); | 1659 | |
| 1660 | /* | ||
| 1661 | * %WORKER_REBIND must be cleared even if the above binding failed; | ||
| 1662 | * otherwise, we may confuse the next CPU_UP cycle or oops / get | ||
| 1663 | * stuck by calling idle_worker_rebind() prematurely. If CPU went | ||
| 1664 | * down again inbetween, %WORKER_UNBOUND would be set, so clearing | ||
| 1665 | * %WORKER_REBIND is always safe. | ||
| 1666 | */ | ||
| 1667 | worker_clr_flags(worker, WORKER_REBIND); | ||
| 1650 | 1668 | ||
| 1651 | spin_unlock_irq(&gcwq->lock); | 1669 | spin_unlock_irq(&gcwq->lock); |
| 1652 | } | 1670 | } |
| @@ -1702,12 +1720,15 @@ retry: | |||
| 1702 | /* set REBIND and kick idle ones, we'll wait for these later */ | 1720 | /* set REBIND and kick idle ones, we'll wait for these later */ |
| 1703 | for_each_worker_pool(pool, gcwq) { | 1721 | for_each_worker_pool(pool, gcwq) { |
| 1704 | list_for_each_entry(worker, &pool->idle_list, entry) { | 1722 | list_for_each_entry(worker, &pool->idle_list, entry) { |
| 1723 | unsigned long worker_flags = worker->flags; | ||
| 1724 | |||
| 1705 | if (worker->flags & WORKER_REBIND) | 1725 | if (worker->flags & WORKER_REBIND) |
| 1706 | continue; | 1726 | continue; |
| 1707 | 1727 | ||
| 1708 | /* morph UNBOUND to REBIND */ | 1728 | /* morph UNBOUND to REBIND atomically */ |
| 1709 | worker->flags &= ~WORKER_UNBOUND; | 1729 | worker_flags &= ~WORKER_UNBOUND; |
| 1710 | worker->flags |= WORKER_REBIND; | 1730 | worker_flags |= WORKER_REBIND; |
| 1731 | ACCESS_ONCE(worker->flags) = worker_flags; | ||
| 1711 | 1732 | ||
| 1712 | idle_rebind.cnt++; | 1733 | idle_rebind.cnt++; |
| 1713 | worker->idle_rebind = &idle_rebind; | 1734 | worker->idle_rebind = &idle_rebind; |
| @@ -1725,26 +1746,16 @@ retry: | |||
| 1725 | goto retry; | 1746 | goto retry; |
| 1726 | } | 1747 | } |
| 1727 | 1748 | ||
| 1728 | /* | 1749 | /* all idle workers are rebound, rebind busy workers */ |
| 1729 | * All idle workers are rebound and waiting for %WORKER_REBIND to | ||
| 1730 | * be cleared inside idle_worker_rebind(). Clear and release. | ||
| 1731 | * Clearing %WORKER_REBIND from this foreign context is safe | ||
| 1732 | * because these workers are still guaranteed to be idle. | ||
| 1733 | */ | ||
| 1734 | for_each_worker_pool(pool, gcwq) | ||
| 1735 | list_for_each_entry(worker, &pool->idle_list, entry) | ||
| 1736 | worker->flags &= ~WORKER_REBIND; | ||
| 1737 | |||
| 1738 | wake_up_all(&gcwq->rebind_hold); | ||
| 1739 | |||
| 1740 | /* rebind busy workers */ | ||
| 1741 | for_each_busy_worker(worker, i, pos, gcwq) { | 1750 | for_each_busy_worker(worker, i, pos, gcwq) { |
| 1751 | unsigned long worker_flags = worker->flags; | ||
| 1742 | struct work_struct *rebind_work = &worker->rebind_work; | 1752 | struct work_struct *rebind_work = &worker->rebind_work; |
| 1743 | struct workqueue_struct *wq; | 1753 | struct workqueue_struct *wq; |
| 1744 | 1754 | ||
| 1745 | /* morph UNBOUND to REBIND */ | 1755 | /* morph UNBOUND to REBIND atomically */ |
| 1746 | worker->flags &= ~WORKER_UNBOUND; | 1756 | worker_flags &= ~WORKER_UNBOUND; |
| 1747 | worker->flags |= WORKER_REBIND; | 1757 | worker_flags |= WORKER_REBIND; |
| 1758 | ACCESS_ONCE(worker->flags) = worker_flags; | ||
| 1748 | 1759 | ||
| 1749 | if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, | 1760 | if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, |
| 1750 | work_data_bits(rebind_work))) | 1761 | work_data_bits(rebind_work))) |
| @@ -1765,6 +1776,34 @@ retry: | |||
| 1765 | worker->scheduled.next, | 1776 | worker->scheduled.next, |
| 1766 | work_color_to_flags(WORK_NO_COLOR)); | 1777 | work_color_to_flags(WORK_NO_COLOR)); |
| 1767 | } | 1778 | } |
| 1779 | |||
| 1780 | /* | ||
| 1781 | * All idle workers are rebound and waiting for %WORKER_REBIND to | ||
| 1782 | * be cleared inside idle_worker_rebind(). Clear and release. | ||
| 1783 | * Clearing %WORKER_REBIND from this foreign context is safe | ||
| 1784 | * because these workers are still guaranteed to be idle. | ||
| 1785 | * | ||
| 1786 | * We need to make sure all idle workers passed WORKER_REBIND wait | ||
| 1787 | * in idle_worker_rebind() before returning; otherwise, workers can | ||
| 1788 | * get stuck at the wait if hotplug cycle repeats. | ||
| 1789 | */ | ||
| 1790 | idle_rebind.cnt = 1; | ||
| 1791 | INIT_COMPLETION(idle_rebind.done); | ||
| 1792 | |||
| 1793 | for_each_worker_pool(pool, gcwq) { | ||
| 1794 | list_for_each_entry(worker, &pool->idle_list, entry) { | ||
| 1795 | worker->flags &= ~WORKER_REBIND; | ||
| 1796 | idle_rebind.cnt++; | ||
| 1797 | } | ||
| 1798 | } | ||
| 1799 | |||
| 1800 | wake_up_all(&gcwq->rebind_hold); | ||
| 1801 | |||
| 1802 | if (--idle_rebind.cnt) { | ||
| 1803 | spin_unlock_irq(&gcwq->lock); | ||
| 1804 | wait_for_completion(&idle_rebind.done); | ||
| 1805 | spin_lock_irq(&gcwq->lock); | ||
| 1806 | } | ||
| 1768 | } | 1807 | } |
| 1769 | 1808 | ||
| 1770 | static struct worker *alloc_worker(void) | 1809 | static struct worker *alloc_worker(void) |
| @@ -2110,9 +2149,45 @@ static bool manage_workers(struct worker *worker) | |||
| 2110 | struct worker_pool *pool = worker->pool; | 2149 | struct worker_pool *pool = worker->pool; |
| 2111 | bool ret = false; | 2150 | bool ret = false; |
| 2112 | 2151 | ||
| 2113 | if (!mutex_trylock(&pool->manager_mutex)) | 2152 | if (pool->flags & POOL_MANAGING_WORKERS) |
| 2114 | return ret; | 2153 | return ret; |
| 2115 | 2154 | ||
| 2155 | pool->flags |= POOL_MANAGING_WORKERS; | ||
| 2156 | |||
| 2157 | /* | ||
| 2158 | * To simplify both worker management and CPU hotplug, hold off | ||
| 2159 | * management while hotplug is in progress. CPU hotplug path can't | ||
| 2160 | * grab %POOL_MANAGING_WORKERS to achieve this because that can | ||
| 2161 | * lead to idle worker depletion (all become busy thinking someone | ||
| 2162 | * else is managing) which in turn can result in deadlock under | ||
| 2163 | * extreme circumstances. Use @pool->manager_mutex to synchronize | ||
| 2164 | * manager against CPU hotplug. | ||
| 2165 | * | ||
| 2166 | * manager_mutex would always be free unless CPU hotplug is in | ||
| 2167 | * progress. trylock first without dropping @gcwq->lock. | ||
| 2168 | */ | ||
| 2169 | if (unlikely(!mutex_trylock(&pool->manager_mutex))) { | ||
| 2170 | spin_unlock_irq(&pool->gcwq->lock); | ||
| 2171 | mutex_lock(&pool->manager_mutex); | ||
| 2172 | /* | ||
| 2173 | * CPU hotplug could have happened while we were waiting | ||
| 2174 | * for manager_mutex. Hotplug itself can't handle us | ||
| 2175 | * because manager isn't either on idle or busy list, and | ||
| 2176 | * @gcwq's state and ours could have deviated. | ||
| 2177 | * | ||
| 2178 | * As hotplug is now excluded via manager_mutex, we can | ||
| 2179 | * simply try to bind. It will succeed or fail depending | ||
| 2180 | * on @gcwq's current state. Try it and adjust | ||
| 2181 | * %WORKER_UNBOUND accordingly. | ||
| 2182 | */ | ||
| 2183 | if (worker_maybe_bind_and_lock(worker)) | ||
| 2184 | worker->flags &= ~WORKER_UNBOUND; | ||
| 2185 | else | ||
| 2186 | worker->flags |= WORKER_UNBOUND; | ||
| 2187 | |||
| 2188 | ret = true; | ||
| 2189 | } | ||
| 2190 | |||
| 2116 | pool->flags &= ~POOL_MANAGE_WORKERS; | 2191 | pool->flags &= ~POOL_MANAGE_WORKERS; |
| 2117 | 2192 | ||
| 2118 | /* | 2193 | /* |
| @@ -2122,6 +2197,7 @@ static bool manage_workers(struct worker *worker) | |||
| 2122 | ret |= maybe_destroy_workers(pool); | 2197 | ret |= maybe_destroy_workers(pool); |
| 2123 | ret |= maybe_create_worker(pool); | 2198 | ret |= maybe_create_worker(pool); |
| 2124 | 2199 | ||
| 2200 | pool->flags &= ~POOL_MANAGING_WORKERS; | ||
| 2125 | mutex_unlock(&pool->manager_mutex); | 2201 | mutex_unlock(&pool->manager_mutex); |
| 2126 | return ret; | 2202 | return ret; |
| 2127 | } | 2203 | } |
