This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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

	* tunables/tunables.c: Include sys/mman.h and libc-internals.h.
	(GLIBC_TUNABLES): New macro.
	(t_strdup): New function.
	(__tunables_init): Implement initializer.
---
 tunables/tunables.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/tunables/tunables.c b/tunables/tunables.c
index 8834aff..d5090fd 100644
--- a/tunables/tunables.c
+++ b/tunables/tunables.c
@@ -24,12 +24,16 @@
 #include <stdbool.h>
 #include <unistd.h>
 #include <sys/param.h>
+#include <sys/mman.h>
+#include <libc-internal.h>
 
 extern char **__environ;
 
 #define TUNABLES_INTERNAL 1
 #include "tunables.h"
 
+#define GLIBC_TUNABLES "GLIBC_TUNABLES"
+
 /* We avoid calling into the C library as much as we can, especially functions
    that we know could use tunables in future for some reason or the other.  For
    example, we call mmap directly instead of malloc because malloc uses
@@ -57,6 +61,31 @@ t_strcmp (const char *a, const char *b)
   return *a - *b;
 }
 
+static char *
+t_strdup (const char *in)
+{
+  size_t len = 0;
+
+  while (in[len] != '\0')
+    len++;
+
+  /* Allocate enough number of pages.  Given the number of tunables this should
+     not exceed a single page but we err on the conservative side and try to
+     allocate space as needed.  */
+  size_t alloclen = ALIGN_UP (len + 1, __getpagesize ());
+
+  char *out = __mmap (NULL, alloclen, PROT_READ | PROT_WRITE,
+		      MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+
+  if (__glibc_unlikely (out == MAP_FAILED))
+    return NULL;
+  else
+    {
+      t_memcpy (out, in, len);
+      return out;
+    }
+}
+
 static bool
 get_next_env (char ***envp, char **name, size_t *namelen, char **val)
 {
@@ -93,7 +122,78 @@ get_next_env (char ***envp, char **name, size_t *namelen, char **val)
 void
 __tunables_init (char **envp)
 {
-  /* Empty for now.  */
+  static bool initialized = false;
+
+  if (__glibc_likely (initialized))
+    return;
+
+  char **evp = envp;
+  char *p = NULL;
+
+  char *envname;
+  size_t envnamelen;
+  char *envval;
+
+  while (get_next_env (&evp, &envname, &envnamelen, &envval))
+    {
+      char *name = alloca (envnamelen + 1);
+
+      t_memcpy (name, envname, envnamelen);
+      name[envnamelen] = '\0';
+
+      if (!t_strcmp (name, GLIBC_TUNABLES))
+	{
+	  p = t_strdup (envval);
+	  break;
+	}
+    }
+
+  if (p == NULL || *p == '\0')
+    goto out;
+
+  while (true)
+    {
+      char *name = p;
+      size_t len = 0;
+
+      /* First, find where the name ends.  */
+      while (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')
+	goto out;
+
+      p[len] = '\0';
+      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 (t_strcmp (name, tunable_list[i].name) == 0)
+	    {
+	      tunable_list[i].val = value;
+	      break;
+	    }
+	}
+
+      if (end == ':')
+	p += len + 1;
+      else
+	goto out;
+    }
+out:
+  initialized = true;
 }
 libc_hidden_def (__tunables_init)
 
-- 
2.5.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]