MAJOR: threads: Start threads to experiment multithreading

[WARNING] For now, HAProxy is not thread-safe, so from this commit, it will be
          broken for a while, when compiled with threads.

When nbthread parameter is greater than 1, HAProxy will create the corresponding
number of threads. If nbthread is set to 1, nothing should be done. So if there
are concurrency issues (and be sure there will be, unfortunatly), an obvious
workaround is to disable the multithreading...

Each created threads will run a polling loop. So, in a certain way, it is pretty
similar to the nbproc mode ("outside" the bugs and the lock
contention). Nevertheless, there are an init and a deinit steps for each thread
to deal with per-thread allocation.

Each thread has a tid (thread-id), numbered from 0 to (nbtread-1). It is used in
many place to do bitwise operations or to improve debugging information.
diff --git a/src/haproxy.c b/src/haproxy.c
index bd8dfd6..c145639 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2237,6 +2237,32 @@
 	}
 }
 
+#ifdef USE_THREAD
+static void *run_thread_poll_loop(void *data)
+{
+	struct per_thread_init_fct   *ptif;
+	struct per_thread_deinit_fct *ptdf;
+
+	tid     = *((unsigned int *)data);
+	tid_bit = (1UL << tid);
+	tv_update_date(-1,-1);
+
+	list_for_each_entry(ptif, &per_thread_init_list, list) {
+		if (!ptif->fct()) {
+			Alert("failed to initialize thread %u.\n", tid);
+			exit(1);
+		}
+	}
+
+	run_poll_loop();
+
+	list_for_each_entry(ptdf, &per_thread_deinit_list, list)
+		ptdf->fct();
+
+	pthread_exit(NULL);
+}
+#endif
+
 /* This is the global management task for listeners. It enables listeners waiting
  * for global resources when there are enough free resource, or at least once in
  * a while. It is designed to be called as a task.
@@ -2755,11 +2781,32 @@
 	/*
 	 * That's it : the central polling loop. Run until we stop.
 	 */
-	run_poll_loop();
+	if (global.nbthread > 1) {
+#ifdef USE_THREAD
+		unsigned int *tids    = calloc(global.nbthread, sizeof(unsigned int));
+		pthread_t    *threads = calloc(global.nbthread, sizeof(pthread_t));
+		int          i;
+
+		for (i = 0; i < global.nbthread; i++) {
+			tids[i] = i;
+			pthread_create(&threads[i], NULL, &run_thread_poll_loop, &tids[i]);
+		}
+		for (i = 0; i < global.nbthread; i++)
+			pthread_join(threads[i], NULL);
 
-	/* Do some cleanup */ 
+		free(tids);
+		free(threads);
+
+#endif /* USE_THREAD */
+	}
+	else {
+		tid = 0;
+		run_poll_loop();
+	}
+
+	/* Do some cleanup */
 	deinit();
-    
+
 	exit(0);
 }