aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/workqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r--kernel/workqueue.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 362b50d092e2..a2dccfca03ba 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -941,6 +941,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
941 struct global_cwq *gcwq; 941 struct global_cwq *gcwq;
942 struct cpu_workqueue_struct *cwq; 942 struct cpu_workqueue_struct *cwq;
943 struct list_head *worklist; 943 struct list_head *worklist;
944 unsigned int work_flags;
944 unsigned long flags; 945 unsigned long flags;
945 946
946 debug_work_activate(work); 947 debug_work_activate(work);
@@ -990,14 +991,17 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
990 BUG_ON(!list_empty(&work->entry)); 991 BUG_ON(!list_empty(&work->entry));
991 992
992 cwq->nr_in_flight[cwq->work_color]++; 993 cwq->nr_in_flight[cwq->work_color]++;
994 work_flags = work_color_to_flags(cwq->work_color);
993 995
994 if (likely(cwq->nr_active < cwq->max_active)) { 996 if (likely(cwq->nr_active < cwq->max_active)) {
995 cwq->nr_active++; 997 cwq->nr_active++;
996 worklist = gcwq_determine_ins_pos(gcwq, cwq); 998 worklist = gcwq_determine_ins_pos(gcwq, cwq);
997 } else 999 } else {
1000 work_flags |= WORK_STRUCT_DELAYED;
998 worklist = &cwq->delayed_works; 1001 worklist = &cwq->delayed_works;
1002 }
999 1003
1000 insert_work(cwq, work, worklist, work_color_to_flags(cwq->work_color)); 1004 insert_work(cwq, work, worklist, work_flags);
1001 1005
1002 spin_unlock_irqrestore(&gcwq->lock, flags); 1006 spin_unlock_irqrestore(&gcwq->lock, flags);
1003} 1007}
@@ -1666,6 +1670,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
1666 struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); 1670 struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq);
1667 1671
1668 move_linked_works(work, pos, NULL); 1672 move_linked_works(work, pos, NULL);
1673 __clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
1669 cwq->nr_active++; 1674 cwq->nr_active++;
1670} 1675}
1671 1676
@@ -1673,6 +1678,7 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
1673 * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight 1678 * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight
1674 * @cwq: cwq of interest 1679 * @cwq: cwq of interest
1675 * @color: color of work which left the queue 1680 * @color: color of work which left the queue
1681 * @delayed: for a delayed work
1676 * 1682 *
1677 * A work either has completed or is removed from pending queue, 1683 * A work either has completed or is removed from pending queue,
1678 * decrement nr_in_flight of its cwq and handle workqueue flushing. 1684 * decrement nr_in_flight of its cwq and handle workqueue flushing.
@@ -1680,19 +1686,22 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
1680 * CONTEXT: 1686 * CONTEXT:
1681 * spin_lock_irq(gcwq->lock). 1687 * spin_lock_irq(gcwq->lock).
1682 */ 1688 */
1683static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color) 1689static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color,
1690 bool delayed)
1684{ 1691{
1685 /* ignore uncolored works */ 1692 /* ignore uncolored works */
1686 if (color == WORK_NO_COLOR) 1693 if (color == WORK_NO_COLOR)
1687 return; 1694 return;
1688 1695
1689 cwq->nr_in_flight[color]--; 1696 cwq->nr_in_flight[color]--;
1690 cwq->nr_active--;
1691 1697
1692 if (!list_empty(&cwq->delayed_works)) { 1698 if (!delayed) {
1693 /* one down, submit a delayed one */ 1699 cwq->nr_active--;
1694 if (cwq->nr_active < cwq->max_active) 1700 if (!list_empty(&cwq->delayed_works)) {
1695 cwq_activate_first_delayed(cwq); 1701 /* one down, submit a delayed one */
1702 if (cwq->nr_active < cwq->max_active)
1703 cwq_activate_first_delayed(cwq);
1704 }
1696 } 1705 }
1697 1706
1698 /* is flush in progress and are we at the flushing tip? */ 1707 /* is flush in progress and are we at the flushing tip? */
@@ -1823,7 +1832,7 @@ __acquires(&gcwq->lock)
1823 hlist_del_init(&worker->hentry); 1832 hlist_del_init(&worker->hentry);
1824 worker->current_work = NULL; 1833 worker->current_work = NULL;
1825 worker->current_cwq = NULL; 1834 worker->current_cwq = NULL;
1826 cwq_dec_nr_in_flight(cwq, work_color); 1835 cwq_dec_nr_in_flight(cwq, work_color, false);
1827} 1836}
1828 1837
1829/** 1838/**
@@ -2388,7 +2397,8 @@ static int try_to_grab_pending(struct work_struct *work)
2388 debug_work_deactivate(work); 2397 debug_work_deactivate(work);
2389 list_del_init(&work->entry); 2398 list_del_init(&work->entry);
2390 cwq_dec_nr_in_flight(get_work_cwq(work), 2399 cwq_dec_nr_in_flight(get_work_cwq(work),
2391 get_work_color(work)); 2400 get_work_color(work),
2401 *work_data_bits(work) & WORK_STRUCT_DELAYED);
2392 ret = 1; 2402 ret = 1;
2393 } 2403 }
2394 } 2404 }