This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH 2/2] Initialize tunable list with the GLIBC_TUNABLES environment variable
- From: Siddhesh Poyarekar <sid at reserved-bit dot com>
- To: libc-alpha at sourceware dot org
- Cc: roland at hack dot frob dot com, carlos at redhat dot com, "Paul E. Murphy" <murphyp at linux dot vnet dot ibm dot com>, Andi Kleen <andi at firstfloor dot org>
- Date: Mon, 11 Jan 2016 16:47:21 +0530
- Subject: [PATCH 2/2] Initialize tunable list with the GLIBC_TUNABLES environment variable
- Authentication-results: sourceware.org; auth=none
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 | 103 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 98 insertions(+), 5 deletions(-)
diff --git a/tunables/tunables.c b/tunables/tunables.c
index 2ae1050..ddd1934 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"
+
static int
t_strncmp (const char *a, const char *b, size_t len)
{
@@ -46,6 +50,31 @@ t_strncmp (const char *a, const char *b, size_t len)
return 0;
}
+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
+ {
+ memcpy (out, in, len);
+ return out;
+ }
+}
+
static bool
get_next_env (char ***envp, char **name, size_t *namelen, char **val)
{
@@ -74,14 +103,78 @@ get_next_env (char ***envp, char **name, size_t *namelen, char **val)
return false;
}
-/* This is where tunables will be read in from either an environment variable,
- a set of environment variables or some other source and then initialized.
- Caller should pass it the environment variable; __environ may not be
- reliable if it is called earlier than libc.so initialization. */
+/* Initialize tunables from the GLIBC_TUNABLES environment variable. The
+ variable is set as colon separated name=value pairs. */
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))
+ {
+ if (!t_strncmp (envname, GLIBC_TUNABLES, sizeof (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_strncmp (name, tunable_list[i].name, SIZE_MAX) == 0)
+ {
+ tunable_list[i].val = value;
+ break;
+ }
+ }
+
+ if (end == ':')
+ p += len + 1;
+ else
+ goto out;
+ }
+out:
+ initialized = true;
}
strong_alias (__tunables_init, tunables_init)
--
2.5.0