[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 09/23] mini-os: remove per-fd evtchn limit



From: Alex Zeffertt <alex.zeffertt@xxxxxxxxxxxxx>

This changes the minios evtchn implementation to use a list instead of
an array which ahis allows it to grow as necessary to support any number
of ports, only limited by Xen (NR_EVS is 1024, should be enough for now).

Signed-off-by: Diego Ongaro <diego.ongaro@xxxxxxxxxx>
Signed-off-by: Alex Zeffertt <alex.zeffertt@xxxxxxxxxxxxx>
Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 extras/mini-os/include/lib.h |   16 +++---
 tools/libxc/xc_minios.c      |  139 ++++++++++++++++++++++--------------------
 2 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h
index bd3eeaf..12070c3 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -53,6 +53,7 @@
 #include <xen/xen.h>
 #include <xen/event_channel.h>
 #include "gntmap.h"
+#include "list.h"
 
 #ifdef HAVE_LIBC
 #include <stdio.h>
@@ -143,7 +144,12 @@ enum fd_type {
     FTYPE_SAVEFILE,
 };
 
-#define MAX_EVTCHN_PORTS 16
+struct evtchn_port_info {
+        struct minios_list_head list;
+        evtchn_port_t port;
+        unsigned long pending;
+        int bound;
+};
 
 extern struct file {
     enum fd_type type;
@@ -158,13 +164,7 @@ extern struct file {
            off_t offset;
        } file;
        struct {
-            /* To each event channel FD is associated a series of ports which
-             * wakes select for this FD. */
-            struct {
-                evtchn_port_t port;
-                unsigned long pending;
-                int bound;
-            } ports[MAX_EVTCHN_PORTS];
+           struct minios_list_head ports;
        } evtchn;
        struct gntmap gntmap;
        struct {
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 8bbfd18..29cce63 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -210,15 +210,34 @@ static struct xc_osdep_ops minios_privcmd_ops = {
     },
 };
 
+
+/* XXX Note: This is not threadsafe */
+static struct evtchn_port_info* port_alloc(int fd) {
+    struct evtchn_port_info *port_info;
+    port_info = malloc(sizeof(struct evtchn_port_info));
+    if (port_info == NULL)
+        return NULL;
+    port_info->pending = 0;
+    port_info->port = -1;
+    port_info->bound = 0;
+
+    minios_list_add(&port_info->list, &files[fd].evtchn.ports);
+    return port_info;
+}
+
+static void port_dealloc(struct evtchn_port_info *port_info) {
+    if (port_info->bound)
+        unbind_evtchn(port_info->port);
+    minios_list_del(&port_info->list);
+    free(port_info);
+}
+
 static xc_osdep_handle minios_evtchn_open(xc_evtchn *xce)
 {
-    int fd = alloc_fd(FTYPE_EVTCHN), i;
+    int fd = alloc_fd(FTYPE_EVTCHN);
     if ( fd == -1 )
         return XC_OSDEP_OPEN_ERROR;
-    for (i = 0; i < MAX_EVTCHN_PORTS; i++) {
-       files[fd].evtchn.ports[i].port = -1;
-        files[fd].evtchn.ports[i].bound = 0;
-    }
+    MINIOS_INIT_LIST_HEAD(&files[fd].evtchn.ports);
     printf("evtchn_open() -> %d\n", fd);
     return (xc_osdep_handle)fd;
 }
@@ -231,10 +250,10 @@ static int minios_evtchn_close(xc_evtchn *xce, 
xc_osdep_handle h)
 
 void minios_evtchn_close_fd(int fd)
 {
-    int i;
-    for (i = 0; i < MAX_EVTCHN_PORTS; i++)
-        if (files[fd].evtchn.ports[i].bound)
-            unbind_evtchn(files[fd].evtchn.ports[i].port);
+    struct evtchn_port_info *port_info, *tmp;
+    minios_list_for_each_entry_safe(port_info, tmp, &files[fd].evtchn.ports, 
list)
+        port_dealloc(port_info);
+
     files[fd].type = FTYPE_NONE;
 }
 
@@ -256,35 +275,21 @@ static int minios_evtchn_notify(xc_evtchn *xce, 
xc_osdep_handle h, evtchn_port_t
     return ret;
 }
 
-/* XXX Note: This is not threadsafe */
-static int port_alloc(int fd) {
-    int i;
-    for (i= 0; i < MAX_EVTCHN_PORTS; i++)
-       if (files[fd].evtchn.ports[i].port == -1)
-           break;
-    if (i == MAX_EVTCHN_PORTS) {
-       printf("Too many ports in xc handle\n");
-       errno = EMFILE;
-       return -1;
-    }
-    files[fd].evtchn.ports[i].pending = 0;
-    return i;
-}
-
 static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void 
*data)
 {
     int fd = (int)(intptr_t)data;
-    int i;
+    struct evtchn_port_info *port_info;
     assert(files[fd].type == FTYPE_EVTCHN);
     mask_evtchn(port);
-    for (i= 0; i < MAX_EVTCHN_PORTS; i++)
-       if (files[fd].evtchn.ports[i].port == port)
-           break;
-    if (i == MAX_EVTCHN_PORTS) {
-       printk("Unknown port for handle %d\n", fd);
-       return;
+    minios_list_for_each_entry(port_info, &files[fd].evtchn.ports, list) {
+        if (port_info->port == port)
+            goto found;
     }
-    files[fd].evtchn.ports[i].pending = 1;
+    printk("Unknown port for handle %d\n", fd);
+    return;
+
+ found:
+    port_info->pending = 1;
     files[fd].read = 1;
     wake_up(&event_queue);
 }
@@ -292,12 +297,13 @@ static void evtchn_handler(evtchn_port_t port, struct 
pt_regs *regs, void *data)
 static evtchn_port_or_error_t minios_evtchn_bind_unbound_port(xc_evtchn *xce, 
xc_osdep_handle h, int domid)
 {
     int fd = (int)h;
-    int ret, i;
+    struct evtchn_port_info *port_info;
+    int ret;
     evtchn_port_t port;
 
     assert(get_current() == main_thread);
-    i = port_alloc(fd);
-    if (i == -1)
+    port_info = port_alloc(fd);
+    if (port_info == NULL)
        return -1;
 
     printf("xc_evtchn_bind_unbound_port(%d)", domid);
@@ -305,11 +311,12 @@ static evtchn_port_or_error_t 
minios_evtchn_bind_unbound_port(xc_evtchn *xce, xc
     printf(" = %d\n", ret);
 
     if (ret < 0) {
+       port_dealloc(port_info);
        errno = -ret;
        return -1;
     }
-    files[fd].evtchn.ports[i].bound = 1;
-    files[fd].evtchn.ports[i].port = port;
+    port_info->bound = 1;
+    port_info->port = port;
     unmask_evtchn(port);
     return port;
 }
@@ -318,12 +325,13 @@ static evtchn_port_or_error_t 
minios_evtchn_bind_interdomain(xc_evtchn *xce, xc_
     evtchn_port_t remote_port)
 {
     int fd = (int)h;
+    struct evtchn_port_info *port_info;
     evtchn_port_t local_port;
-    int ret, i;
+    int ret;
 
     assert(get_current() == main_thread);
-    i = port_alloc(fd);
-    if (i == -1)
+    port_info = port_alloc(fd);
+    if (port_info == NULL)
        return -1;
 
     printf("xc_evtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port);
@@ -331,11 +339,12 @@ static evtchn_port_or_error_t 
minios_evtchn_bind_interdomain(xc_evtchn *xce, xc_
     printf(" = %d\n", ret);
 
     if (ret < 0) {
+       port_dealloc(port_info);
        errno = -ret;
        return -1;
     }
-    files[fd].evtchn.ports[i].bound = 1;
-    files[fd].evtchn.ports[i].port = local_port;
+    port_info->bound = 1;
+    port_info->port = local_port;
     unmask_evtchn(local_port);
     return local_port;
 }
@@ -343,42 +352,40 @@ static evtchn_port_or_error_t 
minios_evtchn_bind_interdomain(xc_evtchn *xce, xc_
 static int minios_evtchn_unbind(xc_evtchn *xce, xc_osdep_handle h, 
evtchn_port_t port)
 {
     int fd = (int)h;
-    int i;
-    for (i = 0; i < MAX_EVTCHN_PORTS; i++)
-       if (files[fd].evtchn.ports[i].port == port) {
-           files[fd].evtchn.ports[i].port = -1;
-           break;
-       }
-    if (i == MAX_EVTCHN_PORTS) {
-       printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", 
port, fd);
-       errno = -EINVAL;
-       return -1;
+    struct evtchn_port_info *port_info;
+
+    minios_list_for_each_entry(port_info, &files[fd].evtchn.ports, list) {
+        if (port_info->port == port) {
+            port_dealloc(port_info);
+            return 0;
+        }
     }
-    files[fd].evtchn.ports[i].bound = 0;
-    unbind_evtchn(port);
-    return 0;
+    printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, 
fd);
+    errno = -EINVAL;
+    return -1;
 }
 
 static evtchn_port_or_error_t minios_evtchn_bind_virq(xc_evtchn *xce, 
xc_osdep_handle h, unsigned int virq)
 {
     int fd = (int)h;
+    struct evtchn_port_info *port_info;
     evtchn_port_t port;
-    int i;
 
     assert(get_current() == main_thread);
-    i = port_alloc(fd);
-    if (i == -1)
+    port_info = port_alloc(fd);
+    if (port_info == NULL)
        return -1;
 
     printf("xc_evtchn_bind_virq(%d)", virq);
     port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)fd);
 
     if (port < 0) {
+       port_dealloc(port_info);
        errno = -port;
        return -1;
     }
-    files[fd].evtchn.ports[i].bound = 1;
-    files[fd].evtchn.ports[i].port = port;
+    port_info->bound = 1;
+    port_info->port = port;
     unmask_evtchn(port);
     return port;
 }
@@ -386,18 +393,18 @@ static evtchn_port_or_error_t 
minios_evtchn_bind_virq(xc_evtchn *xce, xc_osdep_h
 static evtchn_port_or_error_t minios_evtchn_pending(xc_evtchn *xce, 
xc_osdep_handle h)
 {
     int fd = (int)h;
-    int i;
+    struct evtchn_port_info *port_info;
     unsigned long flags;
     evtchn_port_t ret = -1;
 
     local_irq_save(flags);
     files[fd].read = 0;
-    for (i = 0; i < MAX_EVTCHN_PORTS; i++) {
-        evtchn_port_t port = files[fd].evtchn.ports[i].port;
-        if (port != -1 && files[fd].evtchn.ports[i].pending) {
+
+    minios_list_for_each_entry(port_info, &files[fd].evtchn.ports, list) {
+        if (port_info->port != -1 && port_info->pending) {
             if (ret == -1) {
-                ret = port;
-                files[fd].evtchn.ports[i].pending = 0;
+                ret = port_info->port;
+                port_info->pending = 0;
             } else {
                 files[fd].read = 1;
                 break;
-- 
1.7.7.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.