[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 09/18] mini-os: remove per-fd evtchn limit
On Thu, 2012-01-12 at 23:35 +0000, Daniel De Graaf wrote: > From: Alex Zeffertt <alex.zeffertt@xxxxxxxxxxxxx> > > Changes the minios evtchn implementation to use a list instead of an array. > This allows it to grow as necessary to support any number of ports. > Unfortunately, it's still limited by NR_EVS in events.c. NR_EVS is 1024 which, IIRC, is the actual ABI limit for a 32 bit domain. In principal we could make this 4096 for a 64 bit stub domain but I guess we only need 1 evtchn per domain plus perhaps a couple of incidental global ones (e.g. console, VIRQ_mumble) and ~1000+ domains is more than enough for any current system. > 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; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |