[Xen-devel] [PATCH 1/3] xen-bus: use a separate fd for each event channel

2019-04-08 Thread Paul Durrant
To better support use of IOThread-s it will be necessary to be able to set
the AioContext for each XenEventChannel and hence it is necessary to open a
separate handle to libxenevtchan for each channel.

This patch stops using NotifierList for event channel callbacks, replacing
that construct by a list of complete XenEventChannel structures. Each of
these now has a xenevtchn_handle pointer in place of the single pointer
previously held in the XenDevice structure. The individual handles are
opened/closed in xen_device_bind/unbind_event_channel(), replacing the
single open/close in xen_device_realize/unrealize().

NOTE: This patch does not add an AioContext parameter to
  xen_device_bind_event_channel(). That will be done in a subsequent
  patch.

Signed-off-by: Paul Durrant 
---
Cc: Stefano Stabellini 
Cc: Anthony Perard 
---
 hw/xen/xen-bus.c | 79 
 include/hw/xen/xen-bus.h |  6 +--
 2 files changed, 42 insertions(+), 43 deletions(-)

diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 49a725e8c7..9e391492ac 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -923,19 +923,22 @@ done:
 }
 
 struct XenEventChannel {
+QLIST_ENTRY(XenEventChannel) list;
+xenevtchn_handle *xeh;
 evtchn_port_t local_port;
 XenEventHandler handler;
 void *opaque;
-Notifier notifier;
 };
 
-static void event_notify(Notifier *n, void *data)
+static void xen_device_event(void *opaque)
 {
-XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
-unsigned long port = (unsigned long)data;
+XenEventChannel *channel = opaque;
+unsigned long port = xenevtchn_pending(channel->xeh);
 
 if (port == channel->local_port) {
 channel->handler(channel->opaque);
+
+xenevtchn_unmask(channel->xeh, port);
 }
 }
 
@@ -947,24 +950,39 @@ XenEventChannel *xen_device_bind_event_channel(XenDevice 
*xendev,
 XenEventChannel *channel = g_new0(XenEventChannel, 1);
 xenevtchn_port_or_error_t local_port;
 
-local_port = xenevtchn_bind_interdomain(xendev->xeh,
+channel->xeh = xenevtchn_open(NULL, 0);
+if (!channel->xeh) {
+error_setg_errno(errp, errno, "failed xenevtchn_open");
+goto fail;
+}
+
+local_port = xenevtchn_bind_interdomain(channel->xeh,
 xendev->frontend_id,
 port);
 if (local_port < 0) {
 error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
-
-g_free(channel);
-return NULL;
+goto fail;
 }
 
 channel->local_port = local_port;
 channel->handler = handler;
 channel->opaque = opaque;
-channel->notifier.notify = event_notify;
 
-notifier_list_add(&xendev->event_notifiers, &channel->notifier);
+qemu_set_fd_handler(xenevtchn_fd(channel->xeh), xen_device_event, NULL,
+channel);
+
+QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
 
 return channel;
+
+fail:
+if (channel->xeh) {
+xenevtchn_close(channel->xeh);
+}
+
+g_free(channel);
+
+return NULL;
 }
 
 void xen_device_notify_event_channel(XenDevice *xendev,
@@ -976,7 +994,7 @@ void xen_device_notify_event_channel(XenDevice *xendev,
 return;
 }
 
-if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) {
+if (xenevtchn_notify(channel->xeh, channel->local_port) < 0) {
 error_setg_errno(errp, errno, "xenevtchn_notify failed");
 }
 }
@@ -990,12 +1008,15 @@ void xen_device_unbind_event_channel(XenDevice *xendev,
 return;
 }
 
-notifier_remove(&channel->notifier);
+QLIST_REMOVE(channel, list);
 
-if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
+qemu_set_fd_handler(xenevtchn_fd(channel->xeh), NULL, NULL, NULL);
+
+if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
 error_setg_errno(errp, errno, "xenevtchn_unbind failed");
 }
 
+xenevtchn_close(channel->xeh);
 g_free(channel);
 }
 
@@ -1004,6 +1025,7 @@ static void xen_device_unrealize(DeviceState *dev, Error 
**errp)
 XenDevice *xendev = XEN_DEVICE(dev);
 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
 const char *type = object_get_typename(OBJECT(xendev));
+XenEventChannel *channel, *next;
 
 if (!xendev->name) {
 return;
@@ -1020,15 +1042,14 @@ static void xen_device_unrealize(DeviceState *dev, 
Error **errp)
 xendev_class->unrealize(xendev, errp);
 }
 
+/* Make sure all event channels are cleaned up */
+QLIST_FOREACH_SAFE(channel, &xendev->event_channels, list, next) {
+xen_device_unbind_event_channel(xendev, channel, NULL);
+}
+
 xen_device_frontend_destroy(xendev);
 xen_device_backend_destroy(xendev);
 
-if (xendev->xeh) {
-qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), NULL, NULL, NULL);
-xenevtchn_close(xendev->xeh);
-xendev->x

Re: [Xen-devel] [PATCH 1/3] xen-bus: use a separate fd for each event channel

2019-04-10 Thread Anthony PERARD
On Mon, Apr 08, 2019 at 04:16:15PM +0100, Paul Durrant wrote:
> To better support use of IOThread-s it will be necessary to be able to set
> the AioContext for each XenEventChannel and hence it is necessary to open a
> separate handle to libxenevtchan for each channel.
> 
> This patch stops using NotifierList for event channel callbacks, replacing
> that construct by a list of complete XenEventChannel structures. Each of
> these now has a xenevtchn_handle pointer in place of the single pointer
> previously held in the XenDevice structure. The individual handles are
> opened/closed in xen_device_bind/unbind_event_channel(), replacing the
> single open/close in xen_device_realize/unrealize().
> 
> NOTE: This patch does not add an AioContext parameter to
>   xen_device_bind_event_channel(). That will be done in a subsequent
>   patch.
> 
> Signed-off-by: Paul Durrant 

Reviewed-by: Anthony PERARD 

There are a few places were I would have like to add an assert, but they
can't be compiled-out in QEMU :-(.

Thanks,

-- 
Anthony PERARD

___
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel