From patchwork Sat Jan 16 18:56:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 10405 Received: (qmail 47654 invoked by alias); 16 Jan 2016 18:56:39 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 47643 invoked by uid 89); 16 Jan 2016 18:56:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=*value, *in, *out, 24, 16 X-HELO: mx-out03.mykolab.com X-Spam-Score: -2.9 Date: Sun, 17 Jan 2016 00:26:23 +0530 From: Siddhesh Poyarekar To: libc-alpha@sourceware.org Cc: roland@hack.frob.com, carlos@redhat.com, Andi Kleen , tuliom@linux.vnet.ibm.com, "Paul E. Murphy" , munroesj@linux.vnet.ibm.com Subject: [PATCHv2 2/2] Initialize tunable list with the GLIBC_TUNABLES environment variable Message-ID: <20160116185617.GA17783@devel.intra.reserved-bit.com> Content-Disposition: inline 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 #include #include +#include +#include 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)