MINOR: global: add a new "thread-groups" directive

This is used to configure the number of thread groups. For now it can
only be 1.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 463b655..bc1e0a2 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2070,6 +2070,11 @@
   By default, the stats socket is limited to 10 concurrent connections. It is
   possible to change this value with "stats maxconn".
 
+thread-groups <number>
+  This setting is only available when support for threads was built in. It
+  makes HAProxy split its threads into <number> independent groups. At the
+  moment, the limit is 1 and is also the default value. See also "nbthread".
+
 uid <number>
   Changes the process's user ID to <number>. It is recommended that the user ID
   is dedicated to HAProxy or to a small set of similar daemons. HAProxy must
diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h
index 554d1d9..fb01e07 100644
--- a/include/haproxy/global-t.h
+++ b/include/haproxy/global-t.h
@@ -111,7 +111,7 @@
 	int rlimit_memmax_all;	/* default all-process memory limit in megs ; 0=unset */
 	int rlimit_memmax;	/* default per-process memory limit in megs ; 0=unset */
 	long maxzlibmem;        /* max RAM for zlib in bytes */
-
+	int nbtgroups;          /* number of thread groups (IDs start at 1) */
 	int spread_checks;
 	int max_spread_checks;
 	int max_syslog_len;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 7aeffaa..fe49811 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2436,6 +2436,9 @@
 #endif
 	}
 
+	if (!global.nbtgroups)
+		global.nbtgroups = 1;
+
 	pool_head_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
 
 	pool_head_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
diff --git a/src/thread.c b/src/thread.c
index 445a73f..5788303 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -1035,16 +1035,56 @@
 #endif
 
 	HA_DIAG_WARNING_COND(global.nbthread,
-	                     "parsing [%s:%d] : nbthread is already defined and will be overridden.\n",
-	                     file, line);
+	                     "parsing [%s:%d] : '%s' is already defined and will be overridden.\n",
+	                     file, line, args[0]);
 
 	global.nbthread = nbthread;
 	return 0;
 }
 
+/* Parse the "thread-groups" global directive, which takes an integer argument
+ * that contains the desired number of thread groups.
+ */
+static int cfg_parse_thread_groups(char **args, int section_type, struct proxy *curpx,
+                                   const struct proxy *defpx, const char *file, int line,
+                                   char **err)
+{
+	long nbtgroups;
+	char *errptr;
+
+	if (too_many_args(1, args, err, NULL))
+		return -1;
+
+	nbtgroups = strtol(args[1], &errptr, 10);
+	if (!*args[1] || *errptr) {
+		memprintf(err, "'%s' passed a missing or unparsable integer value in '%s'", args[0], args[1]);
+		return -1;
+	}
+
+#ifndef USE_THREAD
+	if (nbtgroups != 1) {
+		memprintf(err, "'%s' specified with a value other than 1 while HAProxy is not compiled with threads support. Please check build options for USE_THREAD", args[0]);
+		return -1;
+	}
+#else
+	if (nbtgroups < 1 || nbtgroups > MAX_TGROUPS) {
+		memprintf(err, "'%s' value must be between 1 and %d (was %ld)", args[0], MAX_TGROUPS, nbtgroups);
+		return -1;
+	}
+#endif
+
+	HA_DIAG_WARNING_COND(global.nbtgroups,
+	                     "parsing [%s:%d] : '%s' is already defined and will be overridden.\n",
+	                     file, line, args[0]);
+
+	global.nbtgroups = nbtgroups;
+	return 0;
+}
+
 /* config keyword parsers */
 static struct cfg_kw_list cfg_kws = {ILH, {
 	{ CFG_GLOBAL, "nbthread",       cfg_parse_nbthread, 0 },
+	{ CFG_GLOBAL, "thread-groups",  cfg_parse_thread_groups, 0 },
 	{ 0, NULL, NULL }
 }};