[MEDIUM] poll: add a measurement of idle vs work time

We now measure the work and idle times in order to report the idle
time in the stats. It's expected that we'll be able to use it at
other places later.
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 5dcd8c4..ebfb179 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1605,6 +1605,7 @@
 				     "MaxConnRate: %d\n"
 				     "Tasks: %d\n"
 				     "Run_queue: %d\n"
+				     "Idle_pct: %d\n"
 				     "node: %s\n"
 				     "description: %s\n"
 				     "",
@@ -1618,7 +1619,7 @@
 				     global.maxsock, global.maxconn, global.hardmaxconn, global.maxpipes,
 				     actconn, pipes_used, pipes_free,
 				     read_freq_ctr(&global.conn_per_sec), global.cps_lim, global.cps_max,
-				     nb_tasks_cur, run_queue_cur,
+				     nb_tasks_cur, run_queue_cur, idle_pct,
 				     global.node, global.desc?global.desc:""
 				     );
 			if (buffer_feed_chunk(si->ib, &msg) >= 0)
@@ -1934,7 +1935,7 @@
 			     "<b>system limits:</b> memmax = %s%s; ulimit-n = %d<br>\n"
 			     "<b>maxsock = </b> %d; <b>maxconn = </b> %d; <b>maxpipes = </b> %d<br>\n"
 			     "current conns = %d; current pipes = %d/%d; conn rate = %d/sec<br>\n"
-			     "Running tasks: %d/%d<br>\n"
+			     "Running tasks: %d/%d; idle = %d %%<br>\n"
 			     "</td><td align=\"center\" nowrap>\n"
 			     "<table class=\"lgd\"><tr>\n"
 			     "<td class=\"active3\">&nbsp;</td><td class=\"noborder\">active UP </td>"
@@ -1967,7 +1968,7 @@
 			     global.rlimit_nofile,
 			     global.maxsock, global.maxconn, global.maxpipes,
 			     actconn, pipes_used, pipes_used+pipes_free, read_freq_ctr(&global.conn_per_sec),
-			     run_queue_cur, nb_tasks_cur
+			     run_queue_cur, nb_tasks_cur, idle_pct
 			     );
 
 			if (si->applet.ctx.stats.flags & STAT_HIDE_DOWN)
diff --git a/src/ev_epoll.c b/src/ev_epoll.c
index 958c4e6..bc7493b 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -236,8 +236,10 @@
 	}
 
 	fd = MIN(maxfd, global.tune.maxpollevents);
+	gettimeofday(&before_poll, NULL);
 	status = epoll_wait(epoll_fd, epoll_events, fd, wait_time);
 	tv_update_date(wait_time, status);
+	measure_idle();
 
 	for (count = 0; count < status; count++) {
 		fd = epoll_events[count].data.fd;
diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c
index e167984..b43533a 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -126,6 +126,7 @@
 	}
 
 	fd = MIN(maxfd, global.tune.maxpollevents);
+	gettimeofday(&before_poll, NULL);
 	status = kevent(kqueue_fd, // int kq
 			NULL,      // const struct kevent *changelist
 			0,         // int nchanges
@@ -133,6 +134,7 @@
 			fd,        // int nevents
 			&timeout); // const struct timespec *timeout
 	tv_update_date(delta_ms, status);
+	measure_idle();
 
 	for (count = 0; count < status; count++) {
 		fd = kev[count].ident;
diff --git a/src/ev_poll.c b/src/ev_poll.c
index f5d011e..ec18863 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -137,8 +137,10 @@
 			wait_time = MAX_DELAY_MS;
 	}
 
+	gettimeofday(&before_poll, NULL);
 	status = poll(poll_events, nbfd, wait_time);
 	tv_update_date(wait_time, status);
+	measure_idle();
 
 	for (count = 0; status > 0 && count < nbfd; count++) {
 		fd = poll_events[count].fd;
diff --git a/src/ev_select.c b/src/ev_select.c
index 5a87282..0924e3f 100644
--- a/src/ev_select.c
+++ b/src/ev_select.c
@@ -125,6 +125,7 @@
 	//	    
 	//	}
 
+	gettimeofday(&before_poll, NULL);
 	status = select(maxfd,
 			readnotnull ? tmp_evts[DIR_RD] : NULL,
 			writenotnull ? tmp_evts[DIR_WR] : NULL,
@@ -132,6 +133,7 @@
 			&delta);
       
 	tv_update_date(delta_ms, status);
+	measure_idle();
 
 	if (status <= 0)
 		return;
diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c
index c9c5978..a7fb64c 100644
--- a/src/ev_sepoll.c
+++ b/src/ev_sepoll.c
@@ -475,8 +475,10 @@
 	/* we want to detect if an accept() will create new speculative FDs here */
 	fd_created = 0;
 	spec_processed = 0;
+	gettimeofday(&before_poll, NULL);
 	status = epoll_wait(epoll_fd, epoll_events, fd, wait_time);
 	tv_update_date(wait_time, status);
+	measure_idle();
 
 	for (count = 0; count < status; count++) {
 		int e = epoll_events[count].events;
diff --git a/src/time.c b/src/time.c
index 1b0f72c..4c41239 100644
--- a/src/time.c
+++ b/src/time.c
@@ -1,7 +1,7 @@
 /*
  * Time calculation functions.
  *
- * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -19,9 +19,14 @@
 unsigned int   curr_sec_ms;      /* millisecond of current second (0..999) */
 unsigned int   curr_sec_ms_scaled;  /* millisecond of current second (0..2^32-1) */
 unsigned int   now_ms;          /* internal date in milliseconds (may wrap) */
+unsigned int   samp_time;       /* total elapsed time over current sample */
+unsigned int   idle_time;       /* total idle time over current sample */
+unsigned int   idle_pct;        /* idle to total ratio over last sample (percent) */
 struct timeval now;             /* internal date is a monotonic function of real clock */
 struct timeval date;            /* the real current date */
 struct timeval start_date;      /* the process's start date */
+struct timeval before_poll;     /* system date before calling poll() */
+struct timeval after_poll;      /* system date after leaving poll() */
 
 /*
  * adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv>
@@ -165,6 +170,9 @@
 	if (unlikely(max_wait < 0)) {
 		tv_zero(&tv_offset);
 		adjusted = date;
+		after_poll = date;
+		samp_time = idle_time = 0;
+		idle_pct = 100;
 		goto to_ms;
 	}
 	__tv_add(&adjusted, &date, &tv_offset);