From patchwork Fri Dec 19 07:37:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andi Kleen X-Patchwork-Id: 4355 Received: (qmail 14589 invoked by alias); 19 Dec 2014 07:38:04 -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 14539 invoked by uid 89); 19 Dec 2014 07:38:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mga09.intel.com X-ExtLoop1: 1 From: Andi Kleen To: libc-alpha@sourceware.org Cc: Andi Kleen Subject: [PATCH 2/7] Add environment tuning interface for mutexes Date: Thu, 18 Dec 2014 23:37:42 -0800 Message-Id: <1418974667-32587-3-git-send-email-andi@firstfloor.org> In-Reply-To: <1418974667-32587-1-git-send-email-andi@firstfloor.org> References: <1418974667-32587-1-git-send-email-andi@firstfloor.org> From: Andi Kleen This adds a straight forward environment variable tuning interface for the elision parameters. This patch enables tuning for mutexes. Lock elision can be enabled and disabled and the retry counts can be changed. This is useful to override any choices done at build time: for example a distribution can decide to ship with elision off by default, but allow users to turn it on per program. Or it can be turned on at build time, but disabled for testing. This is similar to the original proposal. See the upcoming manual patch for detailed documentation. See also the last patch. 2014-12-17 Andi Kleen * sysdeps/unix/sysv/linux/x86/elision-conf.c (tune, tunings): Add array for tuning variables for elision parameters. (complain): Add new function to report errors. (elision_aconf_setup): Add new function to parse mutex configuration. (elision_mutex_init): Call elision_aconf_setup and fetch environment variables. --- sysdeps/unix/sysv/linux/x86/elision-conf.c | 106 +++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/sysdeps/unix/sysv/linux/x86/elision-conf.c b/sysdeps/unix/sysv/linux/x86/elision-conf.c index 28e48d9..c0405a3 100644 --- a/sysdeps/unix/sysv/linux/x86/elision-conf.c +++ b/sysdeps/unix/sysv/linux/x86/elision-conf.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Reasonable initial tuning values, may be revised in the future. This is a conservative initial value. */ @@ -43,6 +44,85 @@ struct elision_config __elision_aconf = .skip_trylock_internal_abort = 3, }; +struct tune +{ + const char *name; + unsigned offset; + int len; +}; + +#define FIELD(x) { #x, offsetof(struct elision_config, x), sizeof(#x)-1 } + +static const struct tune tunings[] = + { + FIELD(skip_lock_busy), + FIELD(skip_lock_internal_abort), + FIELD(retry_try_xbegin), + FIELD(skip_trylock_internal_abort), + {} + }; + +#define PAIR(x) x, sizeof (x)-1 + +/* Complain. */ + +static void +complain (const char *msg, int len) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (write, err, 3, 2, (char *)msg, len); +} + +/* Parse configuration information. */ + +static void +elision_aconf_setup (const char *s) +{ + int i; + + while (*s) + { + for (i = 0; tunings[i].name != NULL; i++) + { + int nlen = tunings[i].len; + + if (strncmp (tunings[i].name, s, nlen) == 0) + { + char *end; + int val; + + if (s[nlen] != '=') + { + complain (PAIR ("pthreads: invalid GLIBC_PTHREAD_MUTEX syntax: missing =\n")); + return; + } + s += nlen + 1; + val = strtoul (s, &end, 0); + if (end == s) + { + complain (PAIR ("pthreads: invalid GLIBC_PTHREAD_MUTEX syntax: missing number\n")); + return; + } + *(int *)(((char *)&__elision_aconf) + tunings[i].offset) = val; + s = end; + if (*s == ',' || *s == ':') + s++; + else if (*s) + { + complain (PAIR ("pthreads: invalid GLIBC_PTHREAD_MUTEX syntax: garbage after number\n")); + return; + } + break; + } + } + if (tunings[i].name == NULL) + { + complain (PAIR ("pthreads: invalid GLIBC_PTHREAD_MUTEX syntax: unknown tunable\n")); + return; + } + } +} + /* Set when the CPU supports elision. When false elision is never attempted. */ @@ -55,6 +135,26 @@ int __elision_available attribute_hidden; int __pthread_force_elision attribute_hidden; +/* Initialize mutex elision. */ + +static void +elision_mutex_init (const char *s) +{ + if (s == NULL) + return; + + if (strncmp (s, "elision", 7) == 0 && (s[7] == 0 || s[7] == ':')) + { + __pthread_force_elision = __elision_available; + if (s[7] == ':') + elision_aconf_setup (s + 8); + } + else if (strcmp (s, "none") == 0 || strcmp (s, "no_elision") == 0) + __pthread_force_elision = 0; + else + complain (PAIR ("pthreads: Unknown setting for GLIBC_PTHREAD_MUTEX\n")); +} + /* Initialize elison. */ static void @@ -68,6 +168,12 @@ elision_init (int argc __attribute__ ((unused)), #endif if (!HAS_RTM) __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks */ + + + /* For static builds need to call this explicitely. Noop for dynamic. */ + __glibc_var_init (argc, argv, environ); + + elision_mutex_init (_dl_glibc_var[GLIBC_VAR_PTHREAD_MUTEX].val); } #ifdef SHARED