MEDIUM: threads/server: Make connection list (priv/idle/safe) thread-safe

For now, we have a list of each type per thread. So there is no need to lock
them. This is the easiest solution for now, but not the best one because there
is no sharing between threads. An idle connection on a thread will not be able
be used by a stream on another thread. So it could be a good idea to rework this
patch later.
diff --git a/include/types/server.h b/include/types/server.h
index 69397c1..ecf04d7 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -207,9 +207,9 @@
 
 	struct list pendconns;			/* pending connections */
 	struct list actconns;			/* active connections */
-	struct list priv_conns;			/* private idle connections attached to stream interfaces */
-	struct list idle_conns;			/* sharable idle connections attached or not to a stream interface */
-	struct list safe_conns;			/* safe idle connections attached to stream interfaces, shared */
+	struct list *priv_conns;		/* private idle connections attached to stream interfaces */
+	struct list *idle_conns;		/* sharable idle connections attached or not to a stream interface */
+	struct list *safe_conns;		/* safe idle connections attached to stream interfaces, shared */
 	struct task *warmup;                    /* the task dedicated to the warmup when slowstart is set */
 
 	struct conn_src conn_src;               /* connection source settings */
diff --git a/src/backend.c b/src/backend.c
index 475efa3..5e51f39 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1066,20 +1066,19 @@
 		 *  idle|  -  |  1  |    idle|  -  |  1  |   idle|  2  |  1  |
 		 *  ----+-----+-----+    ----+-----+-----+   ----+-----+-----+
 		 */
-
-		if (!LIST_ISEMPTY(&srv->idle_conns) &&
+		if (srv->idle_conns && !LIST_ISEMPTY(&srv->idle_conns[tid]) &&
 		    ((s->be->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR &&
 		     s->txn && (s->txn->flags & TX_NOT_FIRST))) {
-			srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
+			srv_conn = LIST_ELEM(srv->idle_conns[tid].n, struct connection *, list);
 		}
-		else if (!LIST_ISEMPTY(&srv->safe_conns) &&
+		else if (srv->safe_conns && !LIST_ISEMPTY(&srv->safe_conns[tid]) &&
 			 ((s->txn && (s->txn->flags & TX_NOT_FIRST)) ||
 			  (s->be->options & PR_O_REUSE_MASK) >= PR_O_REUSE_AGGR)) {
-			srv_conn = LIST_ELEM(srv->safe_conns.n, struct connection *, list);
+			srv_conn = LIST_ELEM(srv->safe_conns[tid].n, struct connection *, list);
 		}
-		else if (!LIST_ISEMPTY(&srv->idle_conns) &&
+		else if (srv->idle_conns && !LIST_ISEMPTY(&srv->idle_conns[tid]) &&
 			 (s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS) {
-			srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
+			srv_conn = LIST_ELEM(srv->idle_conns[tid].n, struct connection *, list);
 		}
 
 		/* If we've picked a connection from the pool, we now have to
diff --git a/src/hlua.c b/src/hlua.c
index 137117c..36b1b3f 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -7666,9 +7666,9 @@
 	socket_tcp.obj_type = OBJ_TYPE_SERVER;
 	LIST_INIT(&socket_tcp.actconns);
 	LIST_INIT(&socket_tcp.pendconns);
-	LIST_INIT(&socket_tcp.priv_conns);
-	LIST_INIT(&socket_tcp.idle_conns);
-	LIST_INIT(&socket_tcp.safe_conns);
+	socket_tcp.priv_conns = NULL;
+	socket_tcp.idle_conns = NULL;
+	socket_tcp.safe_conns = NULL;
 	socket_tcp.next_state = SRV_ST_RUNNING; /* early server setup */
 	socket_tcp.last_change = 0;
 	socket_tcp.id = "LUA-TCP-CONN";
@@ -7712,9 +7712,9 @@
 	socket_ssl.obj_type = OBJ_TYPE_SERVER;
 	LIST_INIT(&socket_ssl.actconns);
 	LIST_INIT(&socket_ssl.pendconns);
-	LIST_INIT(&socket_ssl.priv_conns);
-	LIST_INIT(&socket_ssl.idle_conns);
-	LIST_INIT(&socket_ssl.safe_conns);
+	socket_tcp.priv_conns = NULL;
+	socket_tcp.idle_conns = NULL;
+	socket_tcp.safe_conns = NULL;
 	socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */
 	socket_ssl.last_change = 0;
 	socket_ssl.id = "LUA-SSL-CONN";
diff --git a/src/proto_http.c b/src/proto_http.c
index cfc0e72..cf1cc7a 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -4348,15 +4348,15 @@
 		if (!srv)
 			si_idle_conn(&s->si[1], NULL);
 		else if (srv_conn->flags & CO_FL_PRIVATE)
-			si_idle_conn(&s->si[1], &srv->priv_conns);
+			si_idle_conn(&s->si[1], (srv->priv_conns ? &srv->priv_conns[tid] : NULL));
 		else if (prev_flags & TX_NOT_FIRST)
 			/* note: we check the request, not the connection, but
 			 * this is valid for strategies SAFE and AGGR, and in
 			 * case of ALWS, we don't care anyway.
 			 */
-			si_idle_conn(&s->si[1], &srv->safe_conns);
+			si_idle_conn(&s->si[1], (srv->safe_conns ? &srv->safe_conns[tid] : NULL));
 		else
-			si_idle_conn(&s->si[1], &srv->idle_conns);
+			si_idle_conn(&s->si[1], (srv->idle_conns ? &srv->idle_conns[tid] : NULL));
 	}
 	s->req.analysers = strm_li(s) ? strm_li(s)->analysers : 0;
 	s->res.analysers = 0;
diff --git a/src/server.c b/src/server.c
index 01a7d9b..4c70ac4 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1511,6 +1511,7 @@
 static struct server *new_server(struct proxy *proxy)
 {
 	struct server *srv;
+	int i;
 
 	srv = calloc(1, sizeof *srv);
 	if (!srv)
@@ -1520,9 +1521,20 @@
 	srv->proxy = proxy;
 	LIST_INIT(&srv->actconns);
 	LIST_INIT(&srv->pendconns);
-	LIST_INIT(&srv->priv_conns);
-	LIST_INIT(&srv->idle_conns);
-	LIST_INIT(&srv->safe_conns);
+
+	if ((srv->priv_conns = calloc(global.nbthread, sizeof(*srv->priv_conns))) == NULL)
+		goto free_srv;
+	if ((srv->idle_conns = calloc(global.nbthread, sizeof(*srv->idle_conns))) == NULL)
+		goto free_priv_conns;
+	if ((srv->safe_conns = calloc(global.nbthread, sizeof(*srv->safe_conns))) == NULL)
+		goto free_idle_conns;
+
+	for (i = 0; i < global.nbthread; i++) {
+		LIST_INIT(&srv->priv_conns[i]);
+		LIST_INIT(&srv->idle_conns[i]);
+		LIST_INIT(&srv->safe_conns[i]);
+	}
+
 	LIST_INIT(&srv->update_status);
 
 	srv->next_state = SRV_ST_RUNNING; /* early server setup */
@@ -1537,6 +1549,14 @@
 	srv->xprt  = srv->check.xprt = srv->agent.xprt = xprt_get(XPRT_RAW);
 
 	return srv;
+
+  free_idle_conns:
+	free(srv->idle_conns);
+  free_priv_conns:
+	free(srv->priv_conns);
+  free_srv:
+	free(srv);
+	return NULL;
 }
 
 /*