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

[Xen-changelog] [xen-unstable] xenstored: Fairly round-robin schedule work across all connections.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1185285050 -3600
# Node ID 2f22450e716d037aa654e0486f4fe7722ad6b2bb
# Parent  eff24408830c5356b130318565c4e7f8abf16070
xenstored: Fairly round-robin schedule work across all connections.
Avoids total starvation under some workloads.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/xenstore/talloc.c         |   18 ++++++-
 tools/xenstore/xenstored_core.c |   98 ++++++++++++++++++++--------------------
 2 files changed, 66 insertions(+), 50 deletions(-)

diff -r eff24408830c -r 2f22450e716d tools/xenstore/talloc.c
--- a/tools/xenstore/talloc.c   Tue Jul 24 14:50:05 2007 +0100
+++ b/tools/xenstore/talloc.c   Tue Jul 24 14:50:50 2007 +0100
@@ -97,6 +97,7 @@ struct talloc_chunk {
        struct talloc_chunk *next, *prev;
        struct talloc_chunk *parent, *child;
        struct talloc_reference_handle *refs;
+       unsigned int null_refs; /* references from null_context */
        talloc_destructor_t destructor;
        const char *name;
        size_t size;
@@ -189,6 +190,7 @@ void *_talloc(const void *context, size_
        tc->child = NULL;
        tc->name = NULL;
        tc->refs = NULL;
+       tc->null_refs = 0;
 
        if (context) {
                struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
@@ -225,7 +227,11 @@ void talloc_set_destructor(const void *p
 */
 void talloc_increase_ref_count(const void *ptr)
 {
-       talloc_reference(null_context, ptr);
+       struct talloc_chunk *tc;
+       if (ptr == NULL) return;
+
+       tc = talloc_chunk_from_ptr(ptr);
+       tc->null_refs++;
 }
 
 /*
@@ -285,6 +291,11 @@ static int talloc_unreference(const void
 
        if (context == NULL) {
                context = null_context;
+       }
+
+       if ((context == null_context) && tc->null_refs) {
+               tc->null_refs--;
+               return 0;
        }
 
        for (h=tc->refs;h;h=h->next) {
@@ -538,6 +549,11 @@ int talloc_free(void *ptr)
        }
 
        tc = talloc_chunk_from_ptr(ptr);
+
+       if (tc->null_refs) {
+               tc->null_refs--;
+               return -1;
+       }
 
        if (tc->refs) {
                talloc_reference_destructor(tc->refs);
diff -r eff24408830c -r 2f22450e716d tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c   Tue Jul 24 14:50:05 2007 +0100
+++ b/tools/xenstore/xenstored_core.c   Tue Jul 24 14:50:50 2007 +0100
@@ -299,10 +299,14 @@ static void set_fd(int fd, fd_set *set, 
 }
 
 
-static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
-{
-       struct connection *i;
+static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock,
+                         struct timeval **ptimeout)
+{
+       static struct timeval zero_timeout = { 0 };
+       struct connection *conn;
        int max = -1;
+
+       *ptimeout = NULL;
 
        FD_ZERO(inset);
        FD_ZERO(outset);
@@ -314,13 +318,19 @@ static int initialize_set(fd_set *inset,
        if (xce_handle != -1)
                set_fd(xc_evtchn_fd(xce_handle), inset, &max);
 
-       list_for_each_entry(i, &connections, list) {
-               if (i->domain)
-                       continue;
-               set_fd(i->fd, inset, &max);
-               if (!list_empty(&i->out_list))
-                       FD_SET(i->fd, outset);
-       }
+       list_for_each_entry(conn, &connections, list) {
+               if (conn->domain) {
+                       if (domain_can_read(conn) ||
+                           (domain_can_write(conn) &&
+                            !list_empty(&conn->out_list)))
+                               *ptimeout = &zero_timeout;
+               } else {
+                       set_fd(conn->fd, inset, &max);
+                       if (!list_empty(&conn->out_list))
+                               FD_SET(conn->fd, outset);
+               }
+       }
+
        return max;
 }
 
@@ -1709,6 +1719,7 @@ int main(int argc, char *argv[])
        bool no_domain_init = false;
        const char *pidfile = NULL;
        int evtchn_fd = -1;
+       struct timeval *timeout;
 
        while ((opt = getopt_long(argc, argv, "DE:F:HNPS:t:T:RLVW:", options,
                                  NULL)) != -1) {
@@ -1850,17 +1861,16 @@ int main(int argc, char *argv[])
                evtchn_fd = xc_evtchn_fd(xce_handle);
 
        /* Get ready to listen to the tools. */
-       max = initialize_set(&inset, &outset, *sock, *ro_sock);
+       max = initialize_set(&inset, &outset, *sock, *ro_sock, &timeout);
 
        /* Tell the kernel we're up and running. */
        xenbus_notify_running();
 
        /* Main loop. */
-       /* FIXME: Rewrite so noone can starve. */
        for (;;) {
-               struct connection *i;
-
-               if (select(max+1, &inset, &outset, NULL, NULL) < 0) {
+               struct connection *conn, *old_conn;
+
+               if (select(max+1, &inset, &outset, NULL, timeout) < 0) {
                        if (errno == EINTR)
                                continue;
                        barf_perror("Select failed");
@@ -1882,41 +1892,31 @@ int main(int argc, char *argv[])
                if (evtchn_fd != -1 && FD_ISSET(evtchn_fd, &inset))
                        handle_event();
 
-               list_for_each_entry(i, &connections, list) {
-                       if (i->domain)
-                               continue;
-
-                       /* Operations can delete themselves or others
-                        * (xs_release): list is not safe after input,
-                        * so break. */
-                       if (FD_ISSET(i->fd, &inset)) {
-                               handle_input(i);
-                               break;
+               conn = list_entry(connections.next, typeof(*conn), list);
+               while (&conn->list != &connections) {
+                       talloc_increase_ref_count(conn);
+
+                       if (conn->domain) {
+                               if (domain_can_read(conn))
+                                       handle_input(conn);
+                               if (domain_can_write(conn) &&
+                                   !list_empty(&conn->out_list))
+                                       handle_output(conn);
+                       } else {
+                               if (FD_ISSET(conn->fd, &inset))
+                                       handle_input(conn);
+                               if (FD_ISSET(conn->fd, &outset))
+                                       handle_output(conn);
                        }
-                       if (FD_ISSET(i->fd, &outset)) {
-                               handle_output(i);
-                               break;
-                       }
-               }
-
-               /* Handle all possible I/O for domain connections. */
-       more:
-               list_for_each_entry(i, &connections, list) {
-                       if (!i->domain)
-                               continue;
-
-                       if (domain_can_read(i)) {
-                               handle_input(i);
-                               goto more;
-                       }
-
-                       if (domain_can_write(i) && !list_empty(&i->out_list)) {
-                               handle_output(i);
-                               goto more;
-                       }
-               }
-
-               max = initialize_set(&inset, &outset, *sock, *ro_sock);
+
+                       old_conn = conn;
+                       conn = list_entry(old_conn->list.next,
+                                         typeof(*conn), list);
+                       talloc_free(old_conn);
+               }
+
+               max = initialize_set(&inset, &outset, *sock, *ro_sock,
+                                    &timeout);
        }
 }
 

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


 


Rackspace

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