diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-12-08 05:06:46 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-12-11 00:33:22 +0100 |
commit | e995d5123ed433e37a8d63ac528737c912592e3d (patch) | |
tree | 2e3608cdb19631f901bf40a92adc5e74934cdaf8 /fs/io-wq.c | |
parent | io-wq: remove worker->wait waitqueue (diff) | |
download | linux-e995d5123ed433e37a8d63ac528737c912592e3d.tar.xz linux-e995d5123ed433e37a8d63ac528737c912592e3d.zip |
io-wq: briefly spin for new work after finishing work
To avoid going to sleep only to get woken shortly thereafter, spin
briefly for new work upon completion of work.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/io-wq.c')
-rw-r--r-- | fs/io-wq.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/fs/io-wq.c b/fs/io-wq.c index 6b663ddceb42..90c4978781fb 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -491,26 +491,46 @@ next: } while (1); } +static inline void io_worker_spin_for_work(struct io_wqe *wqe) +{ + int i = 0; + + while (++i < 1000) { + if (io_wqe_run_queue(wqe)) + break; + if (need_resched()) + break; + cpu_relax(); + } +} + static int io_wqe_worker(void *data) { struct io_worker *worker = data; struct io_wqe *wqe = worker->wqe; struct io_wq *wq = wqe->wq; + bool did_work; io_worker_start(wqe, worker); + did_work = false; while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) { set_current_state(TASK_INTERRUPTIBLE); +loop: + if (did_work) + io_worker_spin_for_work(wqe); spin_lock_irq(&wqe->lock); if (io_wqe_run_queue(wqe)) { __set_current_state(TASK_RUNNING); io_worker_handle_work(worker); - continue; + did_work = true; + goto loop; } + did_work = false; /* drops the lock on success, retry */ if (__io_worker_idle(wqe, worker)) { __release(&wqe->lock); - continue; + goto loop; } spin_unlock_irq(&wqe->lock); if (signal_pending(current)) |