From: Lai Jiangshan <[email protected]>
There is no point for the newly created worker entering and leaving
idle in the same pool->lock held region and checking WORKER_DIE
because it has not added to idle_list before the lock.
Avoid the code in the starting of the newly created worker and move
those code to the end of the worker_thread().
Signed-off-by: Lai Jiangshan <[email protected]>
---
kernel/workqueue.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index afe62649fb3a..64dc1833d11a 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2383,31 +2383,16 @@ static int worker_thread(void *__worker)
raw_spin_lock_irq(&pool->lock);
worker->pool->nr_workers++;
- worker_enter_idle(worker);
complete(&pool->created);
-woke_up:
-
- /* am I supposed to die? */
- if (unlikely(worker->flags & WORKER_DIE)) {
- raw_spin_unlock_irq(&pool->lock);
- WARN_ON_ONCE(!list_empty(&worker->entry));
-
- set_task_comm(worker->task, "kworker/dying");
- ida_free(&pool->worker_ida, worker->id);
- worker_detach_from_pool(worker);
- kfree(worker);
- return 0;
- }
- worker_leave_idle(worker);
-recheck:
+loop:
/* no more worker necessary? */
if (!need_more_worker(pool))
goto sleep;
/* do we need to manage? */
if (unlikely(!may_start_working(pool)) && manage_workers(worker))
- goto recheck;
+ goto loop;
/*
* ->scheduled list can only be filled while a worker is
@@ -2457,7 +2442,21 @@ static int worker_thread(void *__worker)
raw_spin_unlock_irq(&pool->lock);
schedule();
raw_spin_lock_irq(&pool->lock);
- goto woke_up;
+
+ /* am I supposed to die? */
+ if (unlikely(worker->flags & WORKER_DIE)) {
+ raw_spin_unlock_irq(&pool->lock);
+ WARN_ON_ONCE(!list_empty(&worker->entry));
+
+ set_task_comm(worker->task, "kworker/dying");
+ ida_free(&pool->worker_ida, worker->id);
+ worker_detach_from_pool(worker);
+ kfree(worker);
+ return 0;
+ }
+
+ worker_leave_idle(worker);
+ goto loop;
}
/**
--
2.19.1.6.gb485710b