|
@@ -977,10 +977,9 @@ static void move_linked_works(struct work_struct *work, struct list_head *head,
|
|
*nextp = n;
|
|
*nextp = n;
|
|
}
|
|
}
|
|
|
|
|
|
-static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
|
|
|
|
|
|
+static void cwq_activate_delayed_work(struct work_struct *work)
|
|
{
|
|
{
|
|
- struct work_struct *work = list_first_entry(&cwq->delayed_works,
|
|
|
|
- struct work_struct, entry);
|
|
|
|
|
|
+ struct cpu_workqueue_struct *cwq = get_work_cwq(work);
|
|
|
|
|
|
trace_workqueue_activate_work(work);
|
|
trace_workqueue_activate_work(work);
|
|
move_linked_works(work, &cwq->pool->worklist, NULL);
|
|
move_linked_works(work, &cwq->pool->worklist, NULL);
|
|
@@ -988,6 +987,14 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
|
|
cwq->nr_active++;
|
|
cwq->nr_active++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
|
|
|
|
+{
|
|
|
|
+ struct work_struct *work = list_first_entry(&cwq->delayed_works,
|
|
|
|
+ struct work_struct, entry);
|
|
|
|
+
|
|
|
|
+ cwq_activate_delayed_work(work);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* cwq_dec_nr_in_flight - decrement cwq's nr_in_flight
|
|
* cwq_dec_nr_in_flight - decrement cwq's nr_in_flight
|
|
* @cwq: cwq of interest
|
|
* @cwq: cwq of interest
|
|
@@ -1106,6 +1113,18 @@ static int try_to_grab_pending(struct work_struct *work, bool is_dwork,
|
|
smp_rmb();
|
|
smp_rmb();
|
|
if (gcwq == get_work_gcwq(work)) {
|
|
if (gcwq == get_work_gcwq(work)) {
|
|
debug_work_deactivate(work);
|
|
debug_work_deactivate(work);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * A delayed work item cannot be grabbed directly
|
|
|
|
+ * because it might have linked NO_COLOR work items
|
|
|
|
+ * which, if left on the delayed_list, will confuse
|
|
|
|
+ * cwq->nr_active management later on and cause
|
|
|
|
+ * stall. Make sure the work item is activated
|
|
|
|
+ * before grabbing.
|
|
|
|
+ */
|
|
|
|
+ if (*work_data_bits(work) & WORK_STRUCT_DELAYED)
|
|
|
|
+ cwq_activate_delayed_work(work);
|
|
|
|
+
|
|
list_del_init(&work->entry);
|
|
list_del_init(&work->entry);
|
|
cwq_dec_nr_in_flight(get_work_cwq(work),
|
|
cwq_dec_nr_in_flight(get_work_cwq(work),
|
|
get_work_color(work),
|
|
get_work_color(work),
|