MINOR: activity: add the profiling.memory global setting

This allows to enable/disable memory usage profiling very early, which
can be convenient to trace the memory usage in maps, certificates, Lua
etc.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index f370b8a..12d44c5 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2243,6 +2243,17 @@
   Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the
   command line argument "-dR".
 
+profiling.memory { on | off }
+  Enables ('on') or disables ('off') per-function memory profiling. This will
+  keep usage statistics of malloc/calloc/realloc/free calls anywhere in the
+  process (including libraries) which will be reported on the CLI using the
+  "show profiling" command. This is essentially meant to be used when an
+  abnormal memory usage is observed that cannot be explained by the pools and
+  other info are required. The performance hit will typically be around 1%,
+  maybe a bit more on highly threaded machines, so it is normally suitable for
+  use in production. The same may be achieved at run time on the CLI using the
+  "set profiling memory" command, please consult the management manual.
+
 profiling.tasks { auto | on | off }
   Enables ('on') or disables ('off') per-task CPU profiling. When set to 'auto'
   the profiling automatically turns on a thread when it starts to suffer from
diff --git a/src/activity.c b/src/activity.c
index afed0ca..3f69e44 100644
--- a/src/activity.c
+++ b/src/activity.c
@@ -331,6 +331,27 @@
 	update_freq_ctr_period(&activity[tid].cpust_15s, 15000, stolen);
 }
 
+#ifdef USE_MEMORY_PROFILING
+/* config parser for global "profiling.memory", accepts "on" or "off" */
+static int cfg_parse_prof_memory(char **args, int section_type, struct proxy *curpx,
+                                const struct proxy *defpx, const char *file, int line,
+                                char **err)
+{
+	if (too_many_args(1, args, err, NULL))
+		return -1;
+
+	if (strcmp(args[1], "on") == 0)
+		profiling |= HA_PROF_MEMORY;
+	else if (strcmp(args[1], "off") == 0)
+		profiling &= ~HA_PROF_MEMORY;
+	else {
+		memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
+		return -1;
+	}
+	return 0;
+}
+#endif // USE_MEMORY_PROFILING
+
 /* config parser for global "profiling.tasks", accepts "on" or "off" */
 static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *curpx,
                                 const struct proxy *defpx, const char *file, int line,
@@ -802,6 +823,9 @@
 
 /* config keyword parsers */
 static struct cfg_kw_list cfg_kws = {ILH, {
+#ifdef USE_MEMORY_PROFILING
+	{ CFG_GLOBAL, "profiling.memory",     cfg_parse_prof_memory     },
+#endif
 	{ CFG_GLOBAL, "profiling.tasks",      cfg_parse_prof_tasks      },
 	{ 0, NULL, NULL }
 }};