Skip to contentSkip to conversation

wake iothread on virtio kick / flush_coalesced_mmio smp_wmb

PATCH Applied Marcelo Tosatti 8 participants 33 messages Feb 22, 2010 – Mar 26, 2010 KVM

lore
Share & tools
lore
#0 lore raw

cover wake iothread on virtio kick / flush_coalesced_mmio smp_wmb

See individual patches for details.

#1 lore raw

PATCH 1/2 virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

VIRTIO_PCI_QUEUE_NOTIFY is used to inform availability of new buffers, so wakeup the iothread to process that information immediately.

hw/virtio-pci.c +1 -0
Index: qemu/hw/virtio-pci.c
===================================================================
@@ -204,6 +204,7 @@ static void virtio_ioport_write(void *op
         break;
     case VIRTIO_PCI_QUEUE_NOTIFY:
         virtio_queue_notify(vdev, val);
+        qemu_notify_event();
         break;
     case VIRTIO_PCI_STATUS:
         vdev->status = val & 0xFF;
#2 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 11 lines · Marcelo Tosatti

VIRTIO_PCI_QUEUE_NOTIFY is used to inform availability of new buffers, so wakeup the iothread to process that information immediately.

Index: qemu/hw/virtio-pci.c
===================================================================

hw/virtio-pci.c static void virtio_ioport_write(void *op · line 209

Quoted 6 lines
hw/virtio-pci.c +1 -0
@@ -204,6 +204,7 @@ static void virtio_ioport_write(void *op
          break;
      case VIRTIO_PCI_QUEUE_NOTIFY:
          virtio_queue_notify(vdev, val);
+        qemu_notify_event();
          break;
 

virtio_queue_notify() will call ->handle_output(), which should either do what's needed to be done, or wake up some iothread itself.

Signature · 1 line
error compiling committee.c: too many arguments to function
#3 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 7 lines · Avi Kivity
Quoted 6 lines · Marcelo Tosatti

VIRTIO_PCI_QUEUE_NOTIFY is used to inform availability of new buffers, so wakeup the iothread to process that information immediately.

Quoted 13 lines

hw/virtio-pci.c static void virtio_ioport_write(void *op · line 208

Quoted 10 lines

Index: qemu/hw/virtio-pci.c
===================================================================

hw/virtio-pci.c +1 -0
@@ -204,6 +204,7 @@ static void virtio_ioport_write(void *op
         break;
     case VIRTIO_PCI_QUEUE_NOTIFY:
         virtio_queue_notify(vdev, val);
+        qemu_notify_event();
         break;

virtio_queue_notify() will call ->handle_output(), which should either do what's needed to be done, or wake up some iothread itself.

kick is used to inform either output processing, in which case ->handle_output() does what its supposed to.

But its also used to inform availability of new buffers, which is common to all virtio devices. So what is the point pushing this to ->handle_output?

Are you concerned about spurious wakeups?

#4 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 24 lines · Marcelo Tosatti
Quoted 8 lines · Avi Kivity
Quoted 6 lines · Marcelo Tosatti

VIRTIO_PCI_QUEUE_NOTIFY is used to inform availability of new buffers, so wakeup the iothread to process that information immediately.

Quoted 14 lines

hw/virtio-pci.c static void virtio_ioport_write(void *op · line 209

Quoted 11 lines

Index: qemu/hw/virtio-pci.c
===================================================================

hw/virtio-pci.c +1 -0
@@ -204,6 +204,7 @@ static void virtio_ioport_write(void *op
          break;
      case VIRTIO_PCI_QUEUE_NOTIFY:
          virtio_queue_notify(vdev, val);
+        qemu_notify_event();
          break;
 

virtio_queue_notify() will call ->handle_output(), which should either do what's needed to be done, or wake up some iothread itself.

Quoted 7 lines

kick is used to inform either output processing, in which case ->handle_output() does what its supposed to.

But its also used to inform availability of new buffers, which is common to all virtio devices. So what is the point pushing this to ->handle_output?

I don't understand what this means. ->handle_output() _is_ informing the device model of new buffers. What more is needed?

Quoted 2 lines

Are you concerned about spurious wakeups?

Yes. Also, qemu_notify_event() is an undirected notification (wakes up all iothreads, and all devices), whereas ->handle_output() is directed (wakes up exactly what is needed).

What's the underlying problem? A new input buffer has become available, and we need to re-poll the incoming file descriptor? If so, that's best done from ->handle_output() (either by waking the iothread or calling read() itself and perhaps receiving -EAGAIN).

Signature · 1 line
error compiling committee.c: too many arguments to function
#5 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 33 lines · Avi Kivity
Quoted 20 lines · Marcelo Tosatti
Quoted 7 lines · Avi Kivity
Quoted 6 lines · Marcelo Tosatti

VIRTIO_PCI_QUEUE_NOTIFY is used to inform availability of new buffers, so wakeup the iothread to process that information immediately.

Quoted 12 lines

hw/virtio-pci.c static void virtio_ioport_write(void *op · line 208

Quoted 10 lines

Index: qemu/hw/virtio-pci.c
===================================================================

hw/virtio-pci.c +1 -0
@@ -204,6 +204,7 @@ static void virtio_ioport_write(void *op
         break;
     case VIRTIO_PCI_QUEUE_NOTIFY:
         virtio_queue_notify(vdev, val);
+        qemu_notify_event();
         break;

virtio_queue_notify() will call ->handle_output(), which should either do what's needed to be done, or wake up some iothread itself.

Quoted 6 lines

kick is used to inform either output processing, in which case ->handle_output() does what its supposed to.

But its also used to inform availability of new buffers, which is common to all virtio devices. So what is the point pushing this to ->handle_output?

I don't understand what this means. ->handle_output() _is_ informing the device model of new buffers. What more is needed?

Quoted 1 line

Are you concerned about spurious wakeups?

Quoted 8 lines

Yes. Also, qemu_notify_event() is an undirected notification (wakes up all iothreads, and all devices), whereas ->handle_output() is directed (wakes up exactly what is needed).

What's the underlying problem? A new input buffer has become available, and we need to re-poll the incoming file descriptor? If so, that's best done from ->handle_output() (either by waking the iothread or calling read() itself and perhaps receiving -EAGAIN).

Yes. Sure, perhaps calling read() itself is appropriate, and i see your point that >handle_output contains more context for a smarter decision.

But one can argue thats an improvement on top of a dumb wakeup.

#6 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 11 lines · Marcelo Tosatti
Quoted 11 lines
Quoted 2 lines

Are you concerned about spurious wakeups?

Yes. Also, qemu_notify_event() is an undirected notification (wakes up all iothreads, and all devices), whereas ->handle_output() is directed (wakes up exactly what is needed).

What's the underlying problem? A new input buffer has become available, and we need to re-poll the incoming file descriptor? If so, that's best done from ->handle_output() (either by waking the iothread or calling read() itself and perhaps receiving -EAGAIN).

Quoted 6 lines

Yes. Sure, perhaps calling read() itself is appropriate, and i see your point that>handle_output contains more context for a smarter decision.

But one can argue thats an improvement on top of a dumb wakeup.

Spurious calls to qemu_notify_event() also make it difficult to tell when it's actually necessary to call qemu_notify_event() vs. when it's just something that doesn't hurt.

Regards,

Anthony Liguori

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 10 lines · Anthony Liguori
Quoted 9 lines · Marcelo Tosatti
Quoted 9 lines
Quoted 1 line

Are you concerned about spurious wakeups?

Yes. Also, qemu_notify_event() is an undirected notification (wakes up all iothreads, and all devices), whereas ->handle_output() is directed (wakes up exactly what is needed).

What's the underlying problem? A new input buffer has become available, and we need to re-poll the incoming file descriptor? If so, that's best done from ->handle_output() (either by waking the iothread or calling read() itself and perhaps receiving -EAGAIN).

Quoted 7 lines
Quoted 5 lines

Yes. Sure, perhaps calling read() itself is appropriate, and i see your point that>handle_output contains more context for a smarter decision.

But one can argue thats an improvement on top of a dumb wakeup.

Spurious calls to qemu_notify_event() also make it difficult to tell when it's actually necessary to call qemu_notify_event() vs. when it's just something that doesn't hurt.

One improvement in this area would be to add a context parameter (which eventually resolves to the underlying thread). Currently we'd ignore it since we have just one iothread, but it would serve to document what's being polled, and later direct the wakeup to the correct thread.

Signature · 1 line
error compiling committee.c: too many arguments to function
#8 lore raw

Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 15 lines · Avi Kivity
Quoted 14 lines · Anthony Liguori
Quoted 13 lines · Marcelo Tosatti
Quoted 9 lines
Quoted 1 line

Are you concerned about spurious wakeups?

Yes. Also, qemu_notify_event() is an undirected notification (wakes up all iothreads, and all devices), whereas ->handle_output() is directed (wakes up exactly what is needed).

What's the underlying problem? A new input buffer has become available, and we need to re-poll the incoming file descriptor? If so, that's best done from ->handle_output() (either by waking the iothread or calling read() itself and perhaps receiving -EAGAIN).

Yes. Sure, perhaps calling read() itself is appropriate, and i see your point that>handle_output contains more context for a smarter decision.

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

But one can argue thats an improvement on top of a dumb wakeup.

Spurious calls to qemu_notify_event() also make it difficult to tell when it's actually necessary to call qemu_notify_event() vs. when it's just something that doesn't hurt.

One improvement in this area would be to add a context parameter (which eventually resolves to the underlying thread). Currently we'd ignore it since we have just one iothread, but it would serve to document what's being polled, and later direct the wakeup to the correct thread.

Ends up looking a lot like a condition. It's not necessarily a bad thing to model.

Regards,

Anthony Liguori

#9 lore raw

Re: [Qemu-devel] Re: [patch uq/master 1/2] virtio-pci: wake up iothread on VIRTIO_PCI_QUEUE_NOTIFY

Quoted 7 lines · Anthony Liguori
Quoted 3 lines
Quoted 1 line

Spurious calls to qemu_notify_event() also make it difficult to tell when it's actually necessary to call qemu_notify_event() vs. when it's just something that doesn't hurt.

One improvement in this area would be to add a context parameter (which eventually resolves to the underlying thread). Currently we'd ignore it since we have just one iothread, but it would serve to document what's being polled, and later direct the wakeup to the correct thread.

Ends up looking a lot like a condition. It's not necessarily a bad thing to model.

But the implementation is very different - condition variables sleep in pthread_cond_wait, the iothread sleeps in poll().

qemu_notify_event() is really requesting iothread t to re-add file fd to its poll set. Maybe we should make this a CharDriverState method.

Signature · 1 line
error compiling committee.c: too many arguments to function
#11 lore raw

PATCH 1/2 Pass QEMUIOWorker to qemu_notify_event

This can be used later to introduce generic iothread workers.

async.c +1 -1
Index: qemu-ioworker/async.c
===================================================================
@@ -180,7 +180,7 @@ void qemu_bh_schedule(QEMUBH *bh)
     bh->scheduled = 1;
     bh->idle = 0; 
     /* stop the currently executing CPU to execute the BH ASAP */
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void qemu_bh_cancel(QEMUBH *bh)
hw/mac_dbdma.c +1 -1
Index: qemu-ioworker/hw/mac_dbdma.c
===================================================================
@@ -655,7 +655,7 @@ void DBDMA_register_channel(void *dbdma,
 
 void DBDMA_schedule(void)
 {
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 static void
hw/virtio-net.c +1 -1
Index: qemu-ioworker/hw/virtio-net.c
===================================================================
@@ -359,7 +359,7 @@ static void virtio_net_handle_rx(VirtIOD
 
     /* We now have RX buffers, signal to the IO thread to break out of the
      * select to re-poll the tap file descriptor */
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 static int virtio_net_can_receive(VLANClientState *nc)
qemu-common.h +7 -1
Index: qemu-ioworker/qemu-common.h
===================================================================
@@ -234,11 +234,17 @@ typedef uint64_t pcibus_t;
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
+typedef struct QEMUIOWorker {
+    void *opaque;
+} QEMUIOWorker;
+
 /* Force QEMU to stop what it's doing and service IO */
 void qemu_service_io(void);
 
 /* Force QEMU to process pending events */
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
+
+extern QEMUIOWorker *main_io_worker;
 
 /* Unblock cpu */
 void qemu_cpu_kick(void *env);
vl.c +12 -9
Index: qemu-ioworker/vl.c
===================================================================
@@ -274,6 +274,9 @@ uint8_t qemu_uuid[16];
 static QEMUBootSetHandler *boot_set_handler;
 static void *boot_set_opaque;
 
+QEMUIOWorker iothread_worker;
+QEMUIOWorker *main_io_worker = &iothread_worker;
+
 #ifdef SIGRTMIN
 #define SIG_IPI (SIGRTMIN+4)
 #else
@@ -885,7 +888,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64
         }
         /* Interrupt execution to force deadline recalculation.  */
         if (use_icount)
-            qemu_notify_event();
+            qemu_notify_event(main_io_worker);
     }
 }
 
@@ -1062,7 +1065,7 @@ static void host_alarm_handler(int host_
         }
 #endif
         timer_alarm_pending = 1;
-        qemu_notify_event();
+        qemu_notify_event(main_io_worker);
     }
 }
 
@@ -2928,7 +2931,7 @@ static int ram_load(QEMUFile *f, void *o
 
 void qemu_service_io(void)
 {
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 /***********************************************************/
@@ -3180,26 +3183,26 @@ void qemu_system_reset_request(void)
     } else {
         reset_requested = 1;
     }
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void qemu_system_shutdown_request(void)
 {
     shutdown_requested = 1;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void qemu_system_powerdown_request(void)
 {
     powerdown_requested = 1;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 #ifdef CONFIG_IOTHREAD
 static void qemu_system_vmstop_request(int reason)
 {
     vmstop_requested = reason;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 #endif
 
@@ -3341,7 +3344,7 @@ void qemu_cpu_kick(void *env)
     return;
 }
 
-void qemu_notify_event(void)
+void qemu_notify_event(QEMUIOWorker *worker)
 {
     CPUState *env = cpu_single_env;
 
@@ -3727,7 +3730,7 @@ void qemu_init_vcpu(void *_env)
         tcg_init_vcpu(env);
 }
 
-void qemu_notify_event(void)
+void qemu_notify_event(QEMUIOWorker *worker)
 {
     qemu_event_increment();
 }
#12 lore raw

Re: [Qemu-devel] [patch 1/2] Pass QEMUIOWorker to qemu_notify_event

Quoted 4 lines · Marcelo Tosatti

This can be used later to introduce generic iothread workers.

Could you rebase this? It failed to apply in a strange way that made me nervous...

Regards,

Anthony Liguori

Quoted 158 lines

Index: qemu-ioworker/async.c
===================================================================

async.c +1 -1
@@ -180,7 +180,7 @@ void qemu_bh_schedule(QEMUBH *bh)
      bh->scheduled = 1;
      bh->idle = 0;
      /* stop the currently executing CPU to execute the BH ASAP */
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  void qemu_bh_cancel(QEMUBH *bh)

Index: qemu-ioworker/hw/mac_dbdma.c
===================================================================

hw/mac_dbdma.c +1 -1
@@ -655,7 +655,7 @@ void DBDMA_register_channel(void *dbdma,
 
  void DBDMA_schedule(void)
  {
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  static void

Index: qemu-ioworker/hw/virtio-net.c
===================================================================

hw/virtio-net.c +1 -1
@@ -359,7 +359,7 @@ static void virtio_net_handle_rx(VirtIOD
 
      /* We now have RX buffers, signal to the IO thread to break out of the
       * select to re-poll the tap file descriptor */
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  static int virtio_net_can_receive(VLANClientState *nc)

Index: qemu-ioworker/qemu-common.h
===================================================================

qemu-common.h +7 -1
@@ -234,11 +234,17 @@ typedef uint64_t pcibus_t;
  void cpu_save(QEMUFile *f, void *opaque);
  int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
+typedef struct QEMUIOWorker {
+    void *opaque;
+} QEMUIOWorker;
+
  /* Force QEMU to stop what it's doing and service IO */
  void qemu_service_io(void);
 
  /* Force QEMU to process pending events */
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
+
+extern QEMUIOWorker *main_io_worker;
 
  /* Unblock cpu */
  void qemu_cpu_kick(void *env);

Index: qemu-ioworker/vl.c
===================================================================

vl.c +12 -9
@@ -274,6 +274,9 @@ uint8_t qemu_uuid[16];
  static QEMUBootSetHandler *boot_set_handler;
  static void *boot_set_opaque;
 
+QEMUIOWorker iothread_worker;
+QEMUIOWorker *main_io_worker =&iothread_worker;
+
  #ifdef SIGRTMIN
  #define SIG_IPI (SIGRTMIN+4)
  #else
@@ -885,7 +888,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64
          }
          /* Interrupt execution to force deadline recalculation.  */
          if (use_icount)
-            qemu_notify_event();
+            qemu_notify_event(main_io_worker);
      }
  }
 
@@ -1062,7 +1065,7 @@ static void host_alarm_handler(int host_
          }
  #endif
          timer_alarm_pending = 1;
-        qemu_notify_event();
+        qemu_notify_event(main_io_worker);
      }
  }
 
@@ -2928,7 +2931,7 @@ static int ram_load(QEMUFile *f, void *o
 
  void qemu_service_io(void)
  {
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  /***********************************************************/
@@ -3180,26 +3183,26 @@ void qemu_system_reset_request(void)
      } else {
          reset_requested = 1;
      }
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  void qemu_system_shutdown_request(void)
  {
      shutdown_requested = 1;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  void qemu_system_powerdown_request(void)
  {
      powerdown_requested = 1;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
 
  #ifdef CONFIG_IOTHREAD
  static void qemu_system_vmstop_request(int reason)
  {
      vmstop_requested = reason;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
  }
  #endif
 
@@ -3341,7 +3344,7 @@ void qemu_cpu_kick(void *env)
      return;
  }
 
-void qemu_notify_event(void)
+void qemu_notify_event(QEMUIOWorker *worker)
  {
      CPUState *env = cpu_single_env;
 
@@ -3727,7 +3730,7 @@ void qemu_init_vcpu(void *_env)
          tcg_init_vcpu(env);
  }
 
-void qemu_notify_event(void)
+void qemu_notify_event(QEMUIOWorker *worker)
  {
      qemu_event_increment();
  }
#13 lore raw

cover introduce QEMUIOWorker and wake up iothread on virtio-serial-bus notification (v2)

Rebased to latest qemu.git.

#14 lore raw

PATCH 1/2 Pass QEMUIOWorker to qemu_notify_event

This can be used later to introduce generic iothread workers.

async.c +1 -1
Index: qemu-ioworker/async.c
===================================================================
@@ -180,7 +180,7 @@ void qemu_bh_schedule(QEMUBH *bh)
     bh->scheduled = 1;
     bh->idle = 0;
     /* stop the currently executing CPU to execute the BH ASAP */
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void qemu_bh_cancel(QEMUBH *bh)
hw/mac_dbdma.c +1 -1
Index: qemu-ioworker/hw/mac_dbdma.c
===================================================================
@@ -655,7 +655,7 @@ void DBDMA_register_channel(void *dbdma,
 
 void DBDMA_schedule(void)
 {
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 static void
hw/virtio-net.c +1 -1
Index: qemu-ioworker/hw/virtio-net.c
===================================================================
@@ -360,7 +360,7 @@ static void virtio_net_handle_rx(VirtIOD
 
     /* We now have RX buffers, signal to the IO thread to break out of the
      * select to re-poll the tap file descriptor */
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 static int virtio_net_can_receive(VLANClientState *nc)
qemu-common.h +7 -1
Index: qemu-ioworker/qemu-common.h
===================================================================
@@ -235,11 +235,17 @@ typedef uint64_t pcibus_t;
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
+typedef struct QEMUIOWorker {
+    void *opaque;
+} QEMUIOWorker;
+
 /* Force QEMU to stop what it's doing and service IO */
 void qemu_service_io(void);
 
 /* Force QEMU to process pending events */
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
+
+extern QEMUIOWorker *main_io_worker;
 
 /* Unblock cpu */
 void qemu_cpu_kick(void *env);
vl.c +10 -7
Index: qemu-ioworker/vl.c
===================================================================
@@ -258,6 +258,9 @@ uint8_t qemu_uuid[16];
 static QEMUBootSetHandler *boot_set_handler;
 static void *boot_set_opaque;
 
+QEMUIOWorker iothread_worker;
+QEMUIOWorker *main_io_worker = &iothread_worker;
+
 #ifdef SIGRTMIN
 #define SIG_IPI (SIGRTMIN+4)
 #else
@@ -1884,7 +1887,7 @@ static int ram_load(QEMUFile *f, void *o
 
 void qemu_service_io(void)
 {
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 /***********************************************************/
@@ -2137,19 +2140,19 @@ void qemu_system_reset_request(void)
     } else {
         reset_requested = 1;
     }
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void qemu_system_shutdown_request(void)
 {
     shutdown_requested = 1;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void qemu_system_powerdown_request(void)
 {
     powerdown_requested = 1;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 static int cpu_can_run(CPUState *env)
@@ -2313,7 +2316,7 @@ void qemu_cpu_kick(void *env)
     return;
 }
 
-void qemu_notify_event(void)
+void qemu_notify_event(QEMUIOWorker *worker)
 {
     CPUState *env = cpu_single_env;
 
@@ -2701,7 +2704,7 @@ void qemu_init_vcpu(void *_env)
         tcg_init_vcpu(env);
 }
 
-void qemu_notify_event(void)
+void qemu_notify_event(QEMUIOWorker *worker)
 {
     qemu_event_increment();
 }
@@ -2709,7 +2712,7 @@ void qemu_notify_event(void)
 static void qemu_system_vmstop_request(int reason)
 {
     vmstop_requested = reason;
-    qemu_notify_event();
+    qemu_notify_event(main_io_worker);
 }
 
 void vm_stop(int reason)
qemu-timer.c +2 -2
Index: qemu-ioworker/qemu-timer.c
===================================================================
@@ -547,7 +547,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64
         }
         /* Interrupt execution to force deadline recalculation.  */
         if (use_icount)
-            qemu_notify_event();
+            qemu_notify_event(main_io_worker);
     }
 }
 
@@ -775,7 +775,7 @@ static void host_alarm_handler(int host_
 
         t->expired = alarm_has_dynticks(t);
         t->pending = 1;
-        qemu_notify_event();
+        qemu_notify_event(main_io_worker);
     }
 }
 
#15 lore raw

Re: [Qemu-devel] [patch 1/2] Pass QEMUIOWorker to qemu_notify_event

hw/mac_dbdma.c void DBDMA_register_channel(void *dbdma, · line 659

Quoted 8 lines

/* Force QEMU to process pending events */

hw/mac_dbdma.c +2 -1
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
+    qemu_notify_event(main_io_worker);
 }

This feels completely wrong.

Devices shouldn't know or care about implementation details like this. How is a device supposed to know which worker it should be waking up?

qemu_notify_event is an ugly hack to workaround the fact that our character device API is polled. If shouldn't exist in the first place, instead we should have a proper mechanism for device emulation to notify the CharDriverState when it is ready to recieve more data.

Paul

#16 lore raw

Re: [Qemu-devel] [patch 1/2] Pass QEMUIOWorker to qemu_notify_event

Quoted 9 lines · Paul Brook

hw/mac_dbdma.c void DBDMA_register_channel(void *dbdma, · line 659

Quoted 8 lines

/* Force QEMU to process pending events */

hw/mac_dbdma.c +2 -1
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
+    qemu_notify_event(main_io_worker);
 }
Quoted 4 lines

This feels completely wrong.

Devices shouldn't know or care about implementation details like this. How is a device supposed to know which worker it should be waking up?

Its not. It could use qemu_notify_event(DeviceInfo->worker), and have no knowledge of the internals.

Quoted 4 lines

qemu_notify_event is an ugly hack to workaround the fact that our character device API is polled. If shouldn't exist in the first place, instead we should have a proper mechanism for device emulation to notify the CharDriverState when it is ready to recieve more data.

qemu_notify_event is used to break the main_loop_wait out of select(), to reprocess events that are handled by it (such as ability to receive more data). Perhaps it is appropriate to move that notification to another level, but there are other users of it at device level already.

#17 lore raw

Re: [Qemu-devel] [patch 1/2] Pass QEMUIOWorker to qemu_notify_event

Quoted 12 lines · Paul Brook
Quoted 11 lines

hw/mac_dbdma.c void DBDMA_register_channel(void *dbdma, · line 659

Quoted 8 lines

/* Force QEMU to process pending events */

hw/mac_dbdma.c +2 -1
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
+    qemu_notify_event(main_io_worker);
 }

This feels completely wrong.

Quoted 5 lines
Quoted 2 lines

Devices shouldn't know or care about implementation details like this. How is a device supposed to know which worker it should be waking up?

Its not. It could use qemu_notify_event(DeviceInfo->worker), and have no knowledge of the internals.

In that case I think you're abusing this API.

I'm very wary of introducing random bits of code that allegedly allow future use of threads. Exploiting thread level parallelism is a hard problem that needs proper design. A such I object to this patch, and think we first need to decide what form of concurrency model we want to use in QEMU.

Paul

#18 lore raw

Re: [Qemu-devel] [patch 1/2] Pass QEMUIOWorker to qemu_notify_event

Quoted 19 lines · Paul Brook
Quoted 13 lines · Paul Brook
Quoted 12 lines

hw/mac_dbdma.c void DBDMA_register_channel(void *dbdma, · line 659

Quoted 10 lines

/* Force QEMU to process pending events */

hw/mac_dbdma.c +2 -1
-void qemu_notify_event(void);
+void qemu_notify_event(QEMUIOWorker *worker);
 
  static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
  {
+    qemu_notify_event(main_io_worker);
  }

This feels completely wrong.

Quoted 6 lines
Quoted 3 lines

Devices shouldn't know or care about implementation details like this. How is a device supposed to know which worker it should be waking up?

Its not. It could use qemu_notify_event(DeviceInfo->worker), and have no knowledge of the internals.

Quoted 7 lines

In that case I think you're abusing this API.

I'm very wary of introducing random bits of code that allegedly allow future use of threads. Exploiting thread level parallelism is a hard problem that needs proper design. A such I object to this patch, and think we first need to decide what form of concurrency model we want to use in QEMU.

I agree. There's a lot of context missing from a proposal like this.

Regards,

Anthony Liguori

Quoted 4 lines

Paul

#19 lore raw

PATCH 2/2 virtio-serial-bus: wake up iothread upon guest read notification

In reply to Marcelo Tosatti

Wake up iothread when buffers are consumed.

hw/virtio-serial-bus.c +1 -0
Index: qemu-ioworker/hw/virtio-serial-bus.c
===================================================================
@@ -331,6 +331,7 @@ static void handle_output(VirtIODevice *
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
+    qemu_notify_event(main_io_worker);
 }
 
 static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
#20 lore raw

PATCH 2/2 virtio-serial-bus: wake up iothread upon guest read notification

In reply to Marcelo Tosatti

Wake up iothread when buffers are consumed.

hw/virtio-serial-bus.c +1 -0
Index: qemu-ioworker/hw/virtio-serial-bus.c
===================================================================
@@ -331,6 +331,7 @@ static void handle_output(VirtIODevice *
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
+    qemu_notify_event(main_io_worker);
 }
 
 static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
#21 lore raw

Re: [patch 2/2] virtio-serial-bus: wake up iothread upon guest read notification

Quoted 9 lines · Marcelo Tosatti

Wake up iothread when buffers are consumed.

Index: qemu-ioworker/hw/virtio-serial-bus.c
===================================================================

hw/virtio-serial-bus.c static void handle_output(VirtIODevice * · line 335

Quoted 5 lines
hw/virtio-serial-bus.c +1 -0
@@ -331,6 +331,7 @@ static void handle_output(VirtIODevice *
 
 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
+    qemu_notify_event(main_io_worker);
 }

ACK, the host lets us know buffers are consumed and new buffers have been added to the pool so that we can start sending more data.

Before this patch my tests took 16m18s to run.
After this patch my tests take 1m17s to run.

Both tests done with just one buffer made available in the virtio-queues.

Amit

#22 lore raw

PATCH 2/2 kvm-all.c: define smp_wmb and use it for coalesced mmio

In reply to Marcelo Tosatti
Cc "Michael S. Tsirkin" <[email protected]>
kvm-all.c +4 -1
Index: qemu/kvm-all.c
===================================================================
@@ -718,6 +718,9 @@ static int kvm_handle_io(uint16_t port, 
     return 1;
 }
 
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+
 void kvm_flush_coalesced_mmio_buffer(void)
 {
 #ifdef KVM_CAP_COALESCED_MMIO
@@ -730,7 +733,7 @@ void kvm_flush_coalesced_mmio_buffer(voi
             ent = &ring->coalesced_mmio[ring->first];
 
             cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
-            /* FIXME smp_wmb() */
+            smp_wmb();
             ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
         }
     }
#23 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 8 lines · Marcelo Tosatti
Cc "Michael S. Tsirkin"<[email protected]>

Index: qemu/kvm-all.c
===================================================================

kvm-all.c static int kvm_handle_io(uint16_t port, · line 724

Quoted 7 lines
kvm-all.c +3 -0
@@ -718,6 +718,9 @@ static int kvm_handle_io(uint16_t port,
      return 1;
  }
 
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+
 

sfence? what about other arches?

Signature · 1 line
error compiling committee.c: too many arguments to function
#24 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 12 lines · Avi Kivity
Quoted 11 lines · Marcelo Tosatti
Cc "Michael S. Tsirkin"<[email protected]>

Index: qemu/kvm-all.c
===================================================================

kvm-all.c +0 -0
@@ -718,6 +718,9 @@ static int kvm_handle_io(uint16_t port,
     return 1;
 }
 
Quoted 5 lines

kvm-all.c static int kvm_handle_io(uint16_t port, · line 723

Quoted 3 lines
kvm-all.c +3 -0
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+

sfence?

There is no need (for this case). Older read cannot be reordered with write, writes are not reordered with other writes, writes by a single processor are observed in the same order by all processors.

Quoted 1 line

what about other arches?

They need to be fixed? PPC needs an instruction apparently.

Is there any objection to including this patch?

#25 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 21 lines · Marcelo Tosatti
Quoted 13 lines · Avi Kivity
Quoted 11 lines · Marcelo Tosatti
Cc "Michael S. Tsirkin"<[email protected]>

Index: qemu/kvm-all.c
===================================================================

kvm-all.c +0 -0
@@ -718,6 +718,9 @@ static int kvm_handle_io(uint16_t port,
      return 1;
  }
 
Quoted 6 lines

kvm-all.c static int kvm_handle_io(uint16_t port,

Quoted 4 lines
kvm-all.c +3 -0
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+
 

sfence?

Quoted 4 lines

There is no need (for this case). Older read cannot be reordered with write, writes are not reordered with other writes, writes by a single processor are observed in the same order by all processors.

Well, Linux does use sfence. Perhaps it's only needed for WC writes (movnti and friends), but better be careful here.

Quoted 6 lines
Quoted 2 lines

what about other arches?

They need to be fixed? PPC needs an instruction apparently.

Is there any objection to including this patch?

I imagine all arches need an instruction. For reads as well.

Note, gcc has a __sync_synchronize() builtin that compiles to mfence on x86. We might use that as a baseline for both rmb and wmb, and let each arch override it incrementally.

Signature · 1 line
error compiling committee.c: too many arguments to function
#26 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 22 lines · Avi Kivity
Quoted 21 lines · Marcelo Tosatti
Quoted 19 lines · Avi Kivity
Quoted 8 lines · Marcelo Tosatti
Cc "Michael S. Tsirkin"<[email protected]>

Index: qemu/kvm-all.c
===================================================================

kvm-all.c static int kvm_handle_io(uint16_t port, · line 724

Quoted 7 lines
kvm-all.c +3 -0
@@ -718,6 +718,9 @@ static int kvm_handle_io(uint16_t port,
      return 1;
  }
 
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+
 

sfence?

Quoted 6 lines
Quoted 4 lines

There is no need (for this case). Older read cannot be reordered with write, writes are not reordered with other writes, writes by a single processor are observed in the same order by all processors.

Well, Linux does use sfence.

At least on 64 bit it doesnt.

Quoted 7 lines

Perhaps it's only needed for WC writes
(movnti and friends), but better be careful here.

Quoted 4 lines
Quoted 2 lines

what about other arches?

They need to be fixed? PPC needs an instruction apparently.

Quoted 8 lines
Quoted 2 lines

Is there any objection to including this patch?

I imagine all arches need an instruction. For reads as well.

Note, gcc has a __sync_synchronize() builtin that compiles to mfence on x86. We might use that as a baseline for both rmb and wmb, and let each arch override it incrementally.

This it what my patch did. Note it only works well for recent gcc.

Quoted 2 lines
Signature · 1 line
error compiling committee.c: too many arguments to function
#27 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 11 lines · Michael S. Tsirkin
Quoted 9 lines
Quoted 7 lines

There is no need (for this case). Older read cannot be reordered with write, writes are not reordered with other writes, writes by a single processor are observed in the same order by all processors.

Well, Linux does use sfence.

At least on 64 bit it doesnt.

Right, I was looking at wmb(), not smp_wmb().

Quoted 8 lines
Quoted 6 lines

I imagine all arches need an instruction. For reads as well.

Note, gcc has a __sync_synchronize() builtin that compiles to mfence on x86. We might use that as a baseline for both rmb and wmb, and let each arch override it incrementally.

This it what my patch did. Note it only works well for recent gcc.

Do you know how recent?

Signature · 1 line
error compiling committee.c: too many arguments to function
#28 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 17 lines · Avi Kivity
Quoted 11 lines · Michael S. Tsirkin
Quoted 9 lines
Quoted 7 lines

There is no need (for this case). Older read cannot be reordered with write, writes are not reordered with other writes, writes by a single processor are observed in the same order by all processors.

Well, Linux does use sfence.

At least on 64 bit it doesnt.

Right, I was looking at wmb(), not smp_wmb().

Quoted 2 lines
Quoted 2 lines

I imagine all arches need an instruction. For reads as well.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Note, gcc has a __sync_synchronize() builtin that compiles to mfence on x86. We might use that as a baseline for both rmb and wmb, and let each arch override it incrementally.

This it what my patch did. Note it only works well for recent gcc.

Do you know how recent?

IIRC 4.3 has broken implementation.
4.4 seems OK as far as I can tell.

Quoted 2 lines
Signature · 1 line
error compiling committee.c: too many arguments to function
#29 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

Quoted 9 lines · Michael S. Tsirkin
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

I imagine all arches need an instruction. For reads as well.

Note, gcc has a __sync_synchronize() builtin that compiles to mfence on x86. We might use that as a baseline for both rmb and wmb, and let each arch override it incrementally.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

This it what my patch did. Note it only works well for recent gcc.

Do you know how recent?

IIRC 4.3 has broken implementation.
4.4 seems OK as far as I can tell.

Well, so that idea's down.

Signature · 1 line
error compiling committee.c: too many arguments to function
Acked-by on v1 2/2
#30 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

In reply to Marcelo Tosatti
Quoted 2 lines · Marcelo Tosatti
Cc "Michael S. Tsirkin" <[email protected]>

We'll need implementation for other arches, I'll dust off my patch that adds it and repost, but for now this is better than what we have.

Quoted 24 lines

Index: qemu/kvm-all.c
===================================================================

kvm-all.c +4 -1
@@ -718,6 +718,9 @@ static int kvm_handle_io(uint16_t port, 
     return 1;
 }
 
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+
 void kvm_flush_coalesced_mmio_buffer(void)
 {
 #ifdef KVM_CAP_COALESCED_MMIO
@@ -730,7 +733,7 @@ void kvm_flush_coalesced_mmio_buffer(voi
             ent = &ring->coalesced_mmio[ring->first];
 
             cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
-            /* FIXME smp_wmb() */
+            smp_wmb();
             ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
         }
     }
author Acked-by Michael S. Tsirkin on v1 2/2
#31 lore raw

Re: [patch uq/master 2/2] kvm-all.c: define smp_wmb and use it for coalesced mmio

In reply to Marcelo Tosatti
kvm-all.c +2 -1
Index: qemu/kvm-all.c
===================================================================
@@ -21,6 +21,7 @@
 #include <linux/kvm.h>
 
 #include "qemu-common.h"
+#include "qemu-barrier.h"
 #include "sysemu.h"
 #include "hw/hw.h"
 #include "gdbstub.h"
@@ -730,7 +731,7 @@ void kvm_flush_coalesced_mmio_buffer(voi
             ent = &ring->coalesced_mmio[ring->first];
 
             cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
-            /* FIXME smp_wmb() */
+            smp_wmb();
             ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
         }
     }
qemu-barrier.h new file +7 -0
Index: qemu/qemu-barrier.h
===================================================================
@@ -0,0 +1,7 @@
+#ifndef __QEMU_BARRIER_H
+#define __QEMU_BARRIER_H 1
+
+/* FIXME: arch dependant, x86 version */
+#define smp_wmb()   asm volatile("" ::: "memory")
+
+#endif