MEDIUM: threads/server: Add a lock per server and atomically update server vars

The server's lock is use, among other things, to lock acces to the active
connection list of a server.
diff --git a/include/common/hathreads.h b/include/common/hathreads.h
index 80a4b24..5003d51 100644
--- a/include/common/hathreads.h
+++ b/include/common/hathreads.h
@@ -148,6 +148,7 @@
 	LISTENER_LOCK,
 	LISTENER_QUEUE_LOCK,
 	PROXY_LOCK,
+	SERVER_LOCK,
 	SIGNALS_LOCK,
 	LOCK_LABELS
 };
@@ -233,7 +234,8 @@
 {
 	const char *labels[LOCK_LABELS] = {"THREAD_SYNC", "FDTAB", "FDCACHE", "FD", "POLL",
 					   "TASK_RQ", "TASK_WQ", "POOL",
-					   "LISTENER", "LISTENER_QUEUE", "PROXY", "SIGNALS" };
+					   "LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER",
+					   "SIGNALS" };
 	int lbl;
 
 	for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
diff --git a/include/proto/server.h b/include/proto/server.h
index b101b3e..ff4ec77 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -64,10 +64,9 @@
 /* increase the number of cumulated connections on the designated server */
 static void inline srv_inc_sess_ctr(struct server *s)
 {
-	s->counters.cum_sess++;
-	update_freq_ctr(&s->sess_per_sec, 1);
-	if (s->sess_per_sec.curr_ctr > s->counters.sps_max)
-		s->counters.sps_max = s->sess_per_sec.curr_ctr;
+	HA_ATOMIC_ADD(&s->counters.cum_sess, 1);
+	HA_ATOMIC_UPDATE_MAX(&s->counters.sps_max,
+			     update_freq_ctr(&s->sess_per_sec, 1));
 }
 
 /* set the time of last session on the designated server */
diff --git a/include/proto/stream.h b/include/proto/stream.h
index 00f452c..aae7d34 100644
--- a/include/proto/stream.h
+++ b/include/proto/stream.h
@@ -262,17 +262,23 @@
 
 static void inline stream_add_srv_conn(struct stream *sess, struct server *srv)
 {
+	SPIN_LOCK(SERVER_LOCK, &srv->lock);
 	sess->srv_conn = srv;
 	LIST_ADD(&srv->actconns, &sess->by_srv);
+	SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
 }
 
 static void inline stream_del_srv_conn(struct stream *sess)
 {
-	if (!sess->srv_conn)
+	struct server *srv = sess->srv_conn;
+
+	if (!srv)
 		return;
 
+	SPIN_LOCK(SERVER_LOCK, &srv->lock);
 	sess->srv_conn = NULL;
 	LIST_DEL(&sess->by_srv);
+	SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
 }
 
 static void inline stream_init_srv_conn(struct stream *sess)
diff --git a/include/types/server.h b/include/types/server.h
index ecf04d7..31fb76f 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -32,6 +32,8 @@
 
 #include <common/config.h>
 #include <common/mini-clist.h>
+#include <common/hathreads.h>
+
 #include <eb32tree.h>
 
 #include <types/connection.h>
@@ -283,6 +285,10 @@
 		struct sample_expr *sni;        /* sample expression for SNI */
 	} ssl_ctx;
 #endif
+
+#ifdef USE_THREAD
+	HA_SPINLOCK_T lock;
+#endif
 	struct {
 		const char *file;		/* file where the section appears */
 		int line;			/* line where the section appears */