ia64/xen-unstable

changeset 15645:2f22450e716d

xenstored: Fairly round-robin schedule work across all connections.
Avoids total starvation under some workloads.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Jul 24 14:50:50 2007 +0100 (2007-07-24)
parents eff24408830c
children cc48264ed647
files tools/xenstore/talloc.c tools/xenstore/xenstored_core.c
line diff
     1.1 --- a/tools/xenstore/talloc.c	Tue Jul 24 14:50:05 2007 +0100
     1.2 +++ b/tools/xenstore/talloc.c	Tue Jul 24 14:50:50 2007 +0100
     1.3 @@ -97,6 +97,7 @@ struct talloc_chunk {
     1.4  	struct talloc_chunk *next, *prev;
     1.5  	struct talloc_chunk *parent, *child;
     1.6  	struct talloc_reference_handle *refs;
     1.7 +	unsigned int null_refs; /* references from null_context */
     1.8  	talloc_destructor_t destructor;
     1.9  	const char *name;
    1.10  	size_t size;
    1.11 @@ -189,6 +190,7 @@ void *_talloc(const void *context, size_
    1.12  	tc->child = NULL;
    1.13  	tc->name = NULL;
    1.14  	tc->refs = NULL;
    1.15 +	tc->null_refs = 0;
    1.16  
    1.17  	if (context) {
    1.18  		struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
    1.19 @@ -225,7 +227,11 @@ void talloc_set_destructor(const void *p
    1.20  */
    1.21  void talloc_increase_ref_count(const void *ptr)
    1.22  {
    1.23 -	talloc_reference(null_context, ptr);
    1.24 +	struct talloc_chunk *tc;
    1.25 +	if (ptr == NULL) return;
    1.26 +
    1.27 +	tc = talloc_chunk_from_ptr(ptr);
    1.28 +	tc->null_refs++;
    1.29  }
    1.30  
    1.31  /*
    1.32 @@ -287,6 +293,11 @@ static int talloc_unreference(const void
    1.33  		context = null_context;
    1.34  	}
    1.35  
    1.36 +	if ((context == null_context) && tc->null_refs) {
    1.37 +		tc->null_refs--;
    1.38 +		return 0;
    1.39 +	}
    1.40 +
    1.41  	for (h=tc->refs;h;h=h->next) {
    1.42  		struct talloc_chunk *p = talloc_parent_chunk(h);
    1.43  		if (p == NULL) {
    1.44 @@ -539,6 +550,11 @@ int talloc_free(void *ptr)
    1.45  
    1.46  	tc = talloc_chunk_from_ptr(ptr);
    1.47  
    1.48 +	if (tc->null_refs) {
    1.49 +		tc->null_refs--;
    1.50 +		return -1;
    1.51 +	}
    1.52 +
    1.53  	if (tc->refs) {
    1.54  		talloc_reference_destructor(tc->refs);
    1.55  		return -1;
     2.1 --- a/tools/xenstore/xenstored_core.c	Tue Jul 24 14:50:05 2007 +0100
     2.2 +++ b/tools/xenstore/xenstored_core.c	Tue Jul 24 14:50:50 2007 +0100
     2.3 @@ -299,11 +299,15 @@ static void set_fd(int fd, fd_set *set, 
     2.4  }
     2.5  
     2.6  
     2.7 -static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
     2.8 +static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock,
     2.9 +			  struct timeval **ptimeout)
    2.10  {
    2.11 -	struct connection *i;
    2.12 +	static struct timeval zero_timeout = { 0 };
    2.13 +	struct connection *conn;
    2.14  	int max = -1;
    2.15  
    2.16 +	*ptimeout = NULL;
    2.17 +
    2.18  	FD_ZERO(inset);
    2.19  	FD_ZERO(outset);
    2.20  
    2.21 @@ -314,13 +318,19 @@ static int initialize_set(fd_set *inset,
    2.22  	if (xce_handle != -1)
    2.23  		set_fd(xc_evtchn_fd(xce_handle), inset, &max);
    2.24  
    2.25 -	list_for_each_entry(i, &connections, list) {
    2.26 -		if (i->domain)
    2.27 -			continue;
    2.28 -		set_fd(i->fd, inset, &max);
    2.29 -		if (!list_empty(&i->out_list))
    2.30 -			FD_SET(i->fd, outset);
    2.31 +	list_for_each_entry(conn, &connections, list) {
    2.32 +		if (conn->domain) {
    2.33 +			if (domain_can_read(conn) ||
    2.34 +			    (domain_can_write(conn) &&
    2.35 +			     !list_empty(&conn->out_list)))
    2.36 +				*ptimeout = &zero_timeout;
    2.37 +		} else {
    2.38 +			set_fd(conn->fd, inset, &max);
    2.39 +			if (!list_empty(&conn->out_list))
    2.40 +				FD_SET(conn->fd, outset);
    2.41 +		}
    2.42  	}
    2.43 +
    2.44  	return max;
    2.45  }
    2.46  
    2.47 @@ -1709,6 +1719,7 @@ int main(int argc, char *argv[])
    2.48  	bool no_domain_init = false;
    2.49  	const char *pidfile = NULL;
    2.50  	int evtchn_fd = -1;
    2.51 +	struct timeval *timeout;
    2.52  
    2.53  	while ((opt = getopt_long(argc, argv, "DE:F:HNPS:t:T:RLVW:", options,
    2.54  				  NULL)) != -1) {
    2.55 @@ -1850,17 +1861,16 @@ int main(int argc, char *argv[])
    2.56  		evtchn_fd = xc_evtchn_fd(xce_handle);
    2.57  
    2.58  	/* Get ready to listen to the tools. */
    2.59 -	max = initialize_set(&inset, &outset, *sock, *ro_sock);
    2.60 +	max = initialize_set(&inset, &outset, *sock, *ro_sock, &timeout);
    2.61  
    2.62  	/* Tell the kernel we're up and running. */
    2.63  	xenbus_notify_running();
    2.64  
    2.65  	/* Main loop. */
    2.66 -	/* FIXME: Rewrite so noone can starve. */
    2.67  	for (;;) {
    2.68 -		struct connection *i;
    2.69 +		struct connection *conn, *old_conn;
    2.70  
    2.71 -		if (select(max+1, &inset, &outset, NULL, NULL) < 0) {
    2.72 +		if (select(max+1, &inset, &outset, NULL, timeout) < 0) {
    2.73  			if (errno == EINTR)
    2.74  				continue;
    2.75  			barf_perror("Select failed");
    2.76 @@ -1882,41 +1892,31 @@ int main(int argc, char *argv[])
    2.77  		if (evtchn_fd != -1 && FD_ISSET(evtchn_fd, &inset))
    2.78  			handle_event();
    2.79  
    2.80 -		list_for_each_entry(i, &connections, list) {
    2.81 -			if (i->domain)
    2.82 -				continue;
    2.83 +		conn = list_entry(connections.next, typeof(*conn), list);
    2.84 +		while (&conn->list != &connections) {
    2.85 +			talloc_increase_ref_count(conn);
    2.86  
    2.87 -			/* Operations can delete themselves or others
    2.88 -			 * (xs_release): list is not safe after input,
    2.89 -			 * so break. */
    2.90 -			if (FD_ISSET(i->fd, &inset)) {
    2.91 -				handle_input(i);
    2.92 -				break;
    2.93 +			if (conn->domain) {
    2.94 +				if (domain_can_read(conn))
    2.95 +					handle_input(conn);
    2.96 +				if (domain_can_write(conn) &&
    2.97 +				    !list_empty(&conn->out_list))
    2.98 +					handle_output(conn);
    2.99 +			} else {
   2.100 +				if (FD_ISSET(conn->fd, &inset))
   2.101 +					handle_input(conn);
   2.102 +				if (FD_ISSET(conn->fd, &outset))
   2.103 +					handle_output(conn);
   2.104  			}
   2.105 -			if (FD_ISSET(i->fd, &outset)) {
   2.106 -				handle_output(i);
   2.107 -				break;
   2.108 -			}
   2.109 +
   2.110 +			old_conn = conn;
   2.111 +			conn = list_entry(old_conn->list.next,
   2.112 +					  typeof(*conn), list);
   2.113 +			talloc_free(old_conn);
   2.114  		}
   2.115  
   2.116 -		/* Handle all possible I/O for domain connections. */
   2.117 -	more:
   2.118 -		list_for_each_entry(i, &connections, list) {
   2.119 -			if (!i->domain)
   2.120 -				continue;
   2.121 -
   2.122 -			if (domain_can_read(i)) {
   2.123 -				handle_input(i);
   2.124 -				goto more;
   2.125 -			}
   2.126 -
   2.127 -			if (domain_can_write(i) && !list_empty(&i->out_list)) {
   2.128 -				handle_output(i);
   2.129 -				goto more;
   2.130 -			}
   2.131 -		}
   2.132 -
   2.133 -		max = initialize_set(&inset, &outset, *sock, *ro_sock);
   2.134 +		max = initialize_set(&inset, &outset, *sock, *ro_sock,
   2.135 +				     &timeout);
   2.136  	}
   2.137  }
   2.138