aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-10-11 05:51:57 -0400
committerTejun Heo <tj@kernel.org>2010-10-11 06:09:30 -0400
commit30310045dd20a286cf3800f063f79b468e132fb1 (patch)
tree535dd3273332f18b245afd6a4142fcc49ada8e61
parentcdadf0097cdca06c497ffaeb5982e028c6e4ed38 (diff)
workqueue: fix HIGHPRI handling in keep_working()
The policy function keep_working() didn't check GCWQ_HIGHPRI_PENDING and could return %false with highpri work pending. This could lead to late execution of a highpri work which was delayed due to @max_active throttling if other works are actively consuming CPU cycles. For example, the following could happen. 1. Work W0 which burns CPU cycles. 2. Two works W1 and W2 are queued to a highpri wq w/ @max_active of 1. 3. W1 starts executing and W2 is put to delayed queue. W0 and W1 are both runnable. 4. W1 finishes which puts W2 to pending queue but keep_working() incorrectly returns %false and the worker goes to sleep. 5. W0 finishes and W2 starts execution. With this patch applied, W2 starts execution as soon as W1 finishes. Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--kernel/workqueue.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index cb2ccfbed0c6..b57a8babdec3 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -604,7 +604,9 @@ static bool keep_working(struct global_cwq *gcwq)
604{ 604{
605 atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu); 605 atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu);
606 606
607 return !list_empty(&gcwq->worklist) && atomic_read(nr_running) <= 1; 607 return !list_empty(&gcwq->worklist) &&
608 (atomic_read(nr_running) <= 1 ||
609 gcwq->flags & GCWQ_HIGHPRI_PENDING);
608} 610}
609 611
610/* Do we need a new worker? Called from manager. */ 612/* Do we need a new worker? Called from manager. */