diff mbox

[2/2] Initialize tunable list with the GLIBC_TUNABLES environment variable

Message ID 1467397878-11514-3-git-send-email-siddhesh@sourceware.org
State Superseded
Headers show

Commit Message

Siddhesh Poyarekar July 1, 2016, 6:31 p.m. UTC
Read tunables values from the users using the GLIBC_TUNABLES
environment variable.  The value of this variable is a colon-separated
list of name=value pairs.  So a typical string would look like this:

GLIBC_TUNABLES=glibc.malloc.mmap_threshold=2048:glibc.malloc.trim_threshold=1024

	* elf/dl-tunables.c: Include string.h.
	(parse_tunables): New function.
	(GLIBC_TUNABLES): New macro.
	(__tunables_init): Use it.
---
 elf/dl-tunables.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
diff mbox

Patch

diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 8a26dfc..04d1d52 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -22,10 +22,13 @@ 
 #include <stdbool.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <string.h>
 
 #define TUNABLES_INTERNAL 1
 #include "dl-tunables.h"
 
+#define GLIBC_TUNABLES "GLIBC_TUNABLES"
+
 /* Compare environment names, bounded by the name hardcoded in glibc.  */
 static bool
 is_name (const char *orig, const char *envname)
@@ -104,6 +107,66 @@  tunable_initialize (tunable_t *cur)
     }
 }
 
+static void
+parse_tunables (char *tunestr)
+{
+  if (tunestr == NULL || *tunestr == '\0')
+    return;
+
+  char *p = tunestr;
+
+  while (true)
+    {
+      char *name = p;
+      size_t len = 0;
+
+      /* First, find where the name ends.  */
+      while (p[len] != '=' && p[len] != ':' && p[len] != '\0')
+	len++;
+
+      /* If we reach the end of the string before getting a valid name-value
+	 pair, bail out.  */
+      if (p[len] == '\0')
+	return;
+
+      /* We did not find a valid name-value pair before encountering the
+	 colon.  */
+      if (p[len]== ':')
+	{
+	  p += len + 1;
+	  continue;
+	}
+
+      p += len + 1;
+
+      char *value = p;
+      len = 0;
+
+      while (p[len] != ':' && p[len] != '\0')
+	len++;
+
+      char end = p[len];
+      p[len] = '\0';
+
+      /* Add the tunable if it exists.  */
+      for (size_t i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
+	{
+	  if (is_name (tunable_list[i].name, name))
+	    {
+	      /* Tunable values take precedence over the env_alias.  */
+	      tunable_list[i].strval = value;
+	      tunable_initialize (&tunable_list[i]);
+	      break;
+	    }
+	}
+
+      if (end == ':')
+	p += len + 1;
+      else
+	return;
+    }
+}
+
 /* Initialize the tunables list from the environment.  For now we only use the
    ENV_ALIAS to find values.  Later we will also use the tunable names to find
    values.  */
@@ -116,6 +179,12 @@  __tunables_init (char **envp)
 
   while (get_next_env (&envp, &envname, &len, &envval))
     {
+      if (is_name (GLIBC_TUNABLES, envname))
+	{
+	  parse_tunables (strdup (envval));
+	  continue;
+	}
+
       for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
 	{
 	  tunable_t *cur = &tunable_list[i];