MINOR: clock: measure the total boot time

Some huge configs take a significant amount of time to start and this
can cause some trouble (e.g. health checks getting delayed and grouped,
process not responding to the CLI etc). For example, some configs might
start fast in certain environments and slowly in other ones just due to
the use of a wrong DNS server that delays all libc's resolutions. Let's
first start by measuring it by keeping a copy of the most recently known
ready date, once before calling check_config_validity() and then refine
it when leaving this function. A last call is finally performed just
before deciding to split between master and worker processes, and it covers
the whole boot. It's trivial to collect and even allows to get rid of a
call to clock_update_date() in function check_config_validity() that was
used in hope to better schedule future events.

(cherry picked from commit da4aa6905c5524a30709eb4cdf25e22fc63eb86e)
[cf: ctx adjustment]]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 2d0bff4f0a10f017786345edc9b42b7a6ffacb34)
[wt: ctx adjustment: no start_time in 2.6]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit a2e5d62d58d44be3a7fc4cfc355c8ed9a11bf815)
[wt: moved patches to time.{c,h}; s/clock_update_date/tv_update_date]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/cfgparse.c b/src/cfgparse.c
index f8c3f76..01014c0 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2651,9 +2651,6 @@
 	 * Now, check for the integrity of all that we have collected.
 	 */
 
-	/* will be needed further to delay some tasks */
-	tv_update_date(0,1);
-
 	if (!global.tune.max_http_hdr)
 		global.tune.max_http_hdr = MAX_HTTP_HDR;
 
diff --git a/src/haproxy.c b/src/haproxy.c
index 03dab81..13085d9 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1959,7 +1959,19 @@
 	/* defaults sections are not needed anymore */
 	proxy_destroy_all_defaults();
 
+	/* update the ready date that will be used to count the startup time
+	 * during config checks (e.g. to schedule certain tasks if needed)
+	 */
+	tv_update_date(0, 1);
+	ready_date = date;
+
+	/* Note: global.nbthread will be initialized as part of this call */
 	err_code |= check_config_validity();
+
+	/* update the ready date to also account for the check time */
+	tv_update_date(0, 1);
+	ready_date = date;
+
 	for (px = proxies_list; px; px = px->next) {
 		struct server *srv;
 		struct post_proxy_check_fct *ppcf;
@@ -3166,6 +3178,10 @@
 				 global.maxsock);
 	}
 
+	/* update the ready date a last time to also account for final setup time */
+	tv_update_date(0, 1);
+	ready_date = date;
+
 	if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
 		struct proxy *px;
 		struct peers *curpeers;
diff --git a/src/time.c b/src/time.c
index d9accae..6335dc4 100644
--- a/src/time.c
+++ b/src/time.c
@@ -18,12 +18,14 @@
 #include <haproxy/ticks.h>
 #include <haproxy/tools.h>
 
+struct timeval start_date;                   /* the process's start date */
+struct timeval ready_date;                   /* date when the process was considered ready */
+
 THREAD_LOCAL unsigned int   now_ms;          /* internal date in milliseconds (may wrap) */
 THREAD_LOCAL unsigned int   samp_time;       /* total elapsed time over current sample */
 THREAD_LOCAL unsigned int   idle_time;       /* total idle time over current sample */
 THREAD_LOCAL struct timeval now;             /* internal date is a monotonic function of real clock */
 THREAD_LOCAL struct timeval date;            /* the real current date */
-struct timeval start_date;      /* the process's start date */
 THREAD_LOCAL struct timeval before_poll;     /* system date before calling poll() */
 THREAD_LOCAL struct timeval after_poll;      /* system date after leaving poll() */