[PATCH 1/2] vhost: Reduce vhost_work_flush() wakeup latency

Bart Van Assche
2013-08-14T07:02:33Z

If the TIF_NEED_RESCHED task flag is set, wake up any vhost_work_flush()
waiters before rescheduling instead of after rescheduling.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Asias He <asias@redhat.com>
---
drivers/vhost/vhost.c | 42 +++++++++++++++++++-----------------------
1 file changed, 19 insertions(+), 23 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index e58cf00..e7ffc10 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -201,47 +201,43 @@ static void vhost_vq_reset(struct vhost_dev *dev,
static int vhost_worker(void *data)
{
struct vhost_dev *dev = data;
- struct vhost_work *work = NULL;
- unsigned uninitialized_var(seq);
+ struct vhost_work *work;
+ unsigned seq;
mm_segment_t oldfs = get_fs();

set_fs(USER_DS);
use_mm(dev->mm);

- for (;;) {
+ spin_lock_irq(&dev->work_lock);
+ while (!kthread_should_stop()) {
/* mb paired w/ kthread_stop */
set_current_state(TASK_INTERRUPTIBLE);
-
- spin_lock_irq(&dev->work_lock);
- if (work) {
- work->done_seq = seq;
- if (work->flushing)
- wake_up_all(&work->done);
- }
-
- if (kthread_should_stop()) {
- spin_unlock_irq(&dev->work_lock);
- __set_current_state(TASK_RUNNING);
- break;
- }
if (!list_empty(&dev->work_list)) {
work = list_first_entry(&dev->work_list,
struct vhost_work, node);
list_del_init(&work->node);
seq = work->queue_seq;
- } else
- work = NULL;
- spin_unlock_irq(&dev->work_lock);
+ spin_unlock_irq(&dev->work_lock);

- if (work) {
__set_current_state(TASK_RUNNING);
work->fn(work);
- if (need_resched())
- schedule();
- } else
+
+ spin_lock_irq(&dev->work_lock);
+ work->done_seq = seq;
+ if (work->flushing)
+ wake_up_all(&work->done);
+ }
+ if (list_empty(&dev->work_list) || need_resched()) {
+ spin_unlock_irq(&dev->work_lock);
+
schedule();

+ spin_lock_irq(&dev->work_lock);
+ }
}
+ spin_unlock_irq(&dev->work_lock);
+
+ __set_current_state(TASK_RUNNING);
unuse_mm(dev->mm);
set_fs(oldfs);
return 0;
--
1.7.10.4