MEDIUM: threads: replace ha_set_tid() with ha_set_thread()

ha_set_tid() was randomly used either to explicitly set thread 0 or to
set any possibly incomplete thread during boot. Let's replace it with
a pointer to a valid thread or NULL for any thread. This allows us to
check that the designated threads are always valid, and to ignore the
thread 0's mapping when setting it to NULL, and always use group 0 with
it during boot.

The initialization code is also cleaner, as we don't pass ugly casts
of a thread ID to a pointer anymore.
diff --git a/include/haproxy/thread.h b/include/haproxy/thread.h
index c70108b..d55c54e 100644
--- a/include/haproxy/thread.h
+++ b/include/haproxy/thread.h
@@ -88,11 +88,21 @@
 
 #define ha_sigmask(how, set, oldset)  sigprocmask(how, set, oldset)
 
-static inline void ha_set_tid(unsigned int tid)
+/* Sets the current thread to a valid one described by <thr>, or to any thread
+ * and any group if NULL (e.g. for use during boot where they're not totally
+ * initialized).
+ */
+static inline void ha_set_thread(const struct thread_info *thr)
 {
-	ti = &ha_thread_info[tid];
-	tg = ti->tg ? ti->tg : &ha_tgroup_info[0];
-	th_ctx = &ha_thread_ctx[tid];
+	if (thr) {
+		ti = thr;
+		tg = ti->tg;
+		th_ctx = &ha_thread_ctx[ti->tid];
+	} else {
+		ti = &ha_thread_info[0];
+		tg = &ha_tgroup_info[0];
+		th_ctx = &ha_thread_ctx[0];
+	}
 }
 
 static inline void thread_idle_now()
@@ -203,18 +213,28 @@
 
 #define ha_sigmask(how, set, oldset)  pthread_sigmask(how, set, oldset)
 
-/* sets the thread ID, TID bit and thread cfg/ctx pointers for the current
- * thread. Since it may be called during early boot even before threads are
- * initialized, we have to be extra careful about some fields which may still
- * be null. For example tg may be null during a part of the boot.
+/* Sets the current thread to a valid one described by <thr>, or to any thread
+ * and any group if NULL (e.g. for use during boot where they're not totally
+ * initialized).
  */
-static inline void ha_set_tid(unsigned int data)
+static inline void ha_set_thread(const struct thread_info *thr)
 {
-	tid     = data;
-	tid_bit = (1UL << tid);
-	ti      = &ha_thread_info[tid];
-	tg      = ti->tg ? ti->tg : &ha_tgroup_info[0];
-	th_ctx  = &ha_thread_ctx[tid];
+	if (thr) {
+		BUG_ON(!thr->tid_bit);
+		BUG_ON(!thr->tg);
+
+		ti      = thr;
+		tg      = thr->tg;
+		tid     = thr->tid;
+		tid_bit = thr->tid_bit;
+		th_ctx  = &ha_thread_ctx[tid];
+	} else {
+		tid     = 0;
+		tid_bit = 1;
+		ti      = &ha_thread_info[0];
+		tg      = &ha_tgroup_info[0];
+		th_ctx  = &ha_thread_ctx[0];
+	}
 }
 
 /* Marks the thread as idle, which means that not only it's not doing anything
diff --git a/src/haproxy.c b/src/haproxy.c
index c8b5ee7..7a4dc79 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -253,6 +253,7 @@
 /* per-boot randomness */
 unsigned char boot_seed[20];        /* per-boot random seed (160 bits initially) */
 
+/* takes the thread config in argument or NULL for any thread */
 static void *run_thread_poll_loop(void *data);
 
 /* bitfield of a few warnings to emit just once (WARN_*) */
@@ -836,7 +837,7 @@
 		leave */
 
 	fork_poller();
-	run_thread_poll_loop(0);
+	run_thread_poll_loop(NULL);
 }
 
 /*
@@ -2697,7 +2698,7 @@
 	__decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
 	__decl_thread(static pthread_cond_t  init_cond  = PTHREAD_COND_INITIALIZER);
 
-	ha_set_tid((unsigned long)data);
+	ha_set_thread(data);
 	set_thread_cpu_affinity();
 	clock_set_local_source();
 
@@ -3397,7 +3398,7 @@
 	haproxy_unblock_signals();
 
 	/* Finally, start the poll loop for the first thread */
-	run_thread_poll_loop(0);
+	run_thread_poll_loop(&ha_thread_info[0]);
 
 	/* wait for all threads to terminate */
 	wait_for_threads_completion();
diff --git a/src/hlua.c b/src/hlua.c
index d5d3f59..b03d8bb 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -11060,7 +11060,7 @@
 
 	/* loading for global state */
 	hlua_state_id = 0;
-	ha_set_tid(0);
+	ha_set_thread(NULL);
 	return hlua_load_state(args[1], hlua_states[0], err);
 }
 
@@ -11104,7 +11104,7 @@
 
 	/* loading for thread 1 only */
 	hlua_state_id = 1;
-	ha_set_tid(0);
+	ha_set_thread(NULL);
 	return hlua_load_state(args[1], hlua_states[1], err);
 }
 
@@ -11311,7 +11311,7 @@
 
 	/* Perform post init of common thread */
 	hlua_state_id = 0;
-	ha_set_tid(0);
+	ha_set_thread(&ha_thread_info[0]);
 	ret = hlua_post_init_state(hlua_states[hlua_state_id]);
 	if (ret == 0)
 		return 0;
@@ -11320,7 +11320,7 @@
 	for (hlua_state_id = 2; hlua_state_id < global.nbthread + 1; hlua_state_id++) {
 
 		/* set thread context */
-		ha_set_tid(hlua_state_id - 1);
+		ha_set_thread(&ha_thread_info[hlua_state_id - 1]);
 
 		/* Init lua state */
 		hlua_states[hlua_state_id] = hlua_init_state(hlua_state_id);
@@ -11336,13 +11336,13 @@
 	}
 
 	/* Reset thread context */
-	ha_set_tid(0);
+	ha_set_thread(NULL);
 
 	/* Execute post init for all states */
 	for (hlua_state_id = 1; hlua_state_id < global.nbthread + 1; hlua_state_id++) {
 
 		/* set thread context */
-		ha_set_tid(hlua_state_id - 1);
+		ha_set_thread(&ha_thread_info[hlua_state_id - 1]);
 
 		/* run post init */
 		ret = hlua_post_init_state(hlua_states[hlua_state_id]);
@@ -11351,7 +11351,7 @@
 	}
 
 	/* Reset thread context */
-	ha_set_tid(0);
+	ha_set_thread(NULL);
 
 	/* control functions registering. Each function must have:
 	 *  - only the function_ref[0] set positive and all other to -1
@@ -12057,12 +12057,12 @@
 
 	/* Init state for common/shared lua parts */
 	hlua_state_id = 0;
-	ha_set_tid(0);
+	ha_set_thread(NULL);
 	hlua_states[0] = hlua_init_state(0);
 
 	/* Init state 1 for thread 0. We have at least one thread. */
 	hlua_state_id = 1;
-	ha_set_tid(0);
+	ha_set_thread(NULL);
 	hlua_states[1] = hlua_init_state(1);
 
 	/* Proxy and server configuration initialisation. */
diff --git a/src/thread.c b/src/thread.c
index 2f904de..ce6a476 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -217,7 +217,7 @@
 	/* Create nbthread-1 thread. The first thread is the current process */
 	ha_pthread[0] = pthread_self();
 	for (i = 1; i < global.nbthread; i++)
-		pthread_create(&ha_pthread[i], NULL, handler, (void *)(long)i);
+		pthread_create(&ha_pthread[i], NULL, handler, &ha_thread_info[i]);
 }
 
 /* waits for all threads to terminate. Does nothing when threads are