[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


 


Rackspace

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