This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH 2/2] Add environment variable tuning for elision parameters.
- From: Torvald Riegel <triegel at redhat dot com>
- To: Andi Kleen <andi at firstfloor dot org>
- Cc: libc-alpha at sourceware dot org, Andi Kleen <ak at linux dot jf dot intel dot com>
- Date: Mon, 17 Jun 2013 16:57:52 +0200
- Subject: Re: [PATCH 2/2] Add environment variable tuning for elision parameters.
- References: <1371232449-12102-1-git-send-email-andi at firstfloor dot org> <1371232449-12102-3-git-send-email-andi at firstfloor dot org>
On Fri, 2013-06-14 at 10:54 -0700, Andi Kleen wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> Add tunables for enabling/disabling elision and tuning the elision retry
> and skip counts.
>
> This builds on the glibc-var infrastructure added earlier.
>
> nptl/:
> 2013-06-12 Andi Kleen <ak@linux.intel.com>
>
> * sysdeps/unix/sysv/linux/x86/elision-conf.c (struct elision_config): Add.
> (struct tune): dito.
> (complain): New function to write error message.
> (elision_aconf_setup): New function to parse parameters.
> (elision_mutex_init): New function to parse GLIBC_PTHREAD_MUTEX.
> (elision_rwlock_init): New function to parse GLIBC_PTHREAD_RWLOCK.
> (elision_init): Call elision_mutex_init and elision_rwlock_init.
>
> /:
> 2013-06-12 Andi Kleen <ak@linux.intel.com>
>
> * manual/elision.texi: Add sections describing environment variables.
> ---
> manual/elision.texi | 87 ++++++++++++++-
> nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c | 134 ++++++++++++++++++++++++
> 2 files changed, 220 insertions(+), 1 deletion(-)
>
> diff --git a/manual/elision.texi b/manual/elision.texi
> index fc7de08..b9c3397 100644
> --- a/manual/elision.texi
> +++ b/manual/elision.texi
> @@ -11,7 +11,9 @@ This chapter describes the elided lock implementation for POSIX thread locks.
> * Semantic differences of elided locks::
> * Tuning lock elision::
> * Setting elision for individual @code{pthread_mutex_t}::
> +* Setting @code{pthread_mutex_t} elision using environment variables::
> * Setting elision for individual @code{pthread_rwlock_t}::
> +* Setting @code{pthread_rwlock_t} elision using environment variables::
> @end menu
>
> @node Lock elision introduction
> @@ -173,7 +175,7 @@ to only write when the value changed.
> @section Setting elision for individual @code{pthread_mutex_t}
>
> Elision can be explicitly disabled or enabled for each @code{pthread_mutex_t} in the program.
> -This overrides any other defaults for this lock.
> +This overrides any other defaults set by environment variables for this lock.
>
> @code{pthrex_mutex_t} Initializers for using in variable initializations.
>
> @@ -212,10 +214,68 @@ pthread_mutex_init (&object->mylock, &attr);
>
> @code{pthread_mutex_gettype} will return additional flags too.
>
> +@node Setting @code{pthread_mutex_t} elision using environment variables
> +@section Setting @code{pthread_mutex_t} elision using environment variables
> +The elision of @code{pthread_mutex_t} mutexes can be configured at runtime with the @code{GLIBC_PTHREAD_MUTEX}
> +environment variable. This will force a specific lock type for all
> +mutexes in the program that do not have another type set explicitly.
> +An explicitly set lock type will override the environment variable.
> +
> +@smallexample
> +# run myprogram with no elision
> +GLIBC_PTHREAD_MUTEX=none myprogram
> +@end smallexample
> +
> +The default depends on the @theglibc{} build configuration and whether the hardware
> +supports lock elision.
> +
> +@itemize
> +@item
> +@code{GLIBC_PTHREAD_MUTEX=elision}
> +Use elided mutexes, unless explicitly disabled in the program.
> +
> +@item
> +@code{GLIBC_PTHREAD_MUTEX=none}
> +Don't use elide mutexes, unless explicitly enable in the program.
> +@end itemize
> +
> +Additional tunables can be configured through the environment variable,
> +like this:
> +@code{GLIBC_PTHREAD_MUTEX=adaptive:retry_lock_busy=10,retry_lock_internal_abort=20}
> +Note these parameters do not constitute an ABI and may change or disappear
> +at any time as the lock elision algorithm evolves.
> +
> +Currently supported parameters are:
> +
> +@itemize
> +@item
> +skip_lock_busy
> +How often to not attempt a transaction when the lock is seen as busy.
> +Expressed in number of lock attempts.
> +
> +@item
> +skip_lock_internal_abort
> +How often to not attempt a transaction after an internal abort is seen.
> +Expressed in number of lock attempts.
> +
> +@item
> +retry_try_xbegin
> +How often to retry the transaction on external aborts.
> +Expressed in number of transaction starts.
> +
> +@item
> +skip_trylock_internal_abort
> +How often to skip doing a transaction on internal aborts during trylock.
> +This setting is also used for adaptive locks.
> +Expressed in number of transaction starts.
> +
> +@end itemize
> +
> @node Setting elision for individual @code{pthread_rwlock_t}
> @section Setting elision for individual @code{pthread_rwlock_t}
>
> Elision can be explicitly disabled or enabled for each @code{pthread_rwlock_t} in the program.
> +This overrides any other defaults set by environment variables for this lock.
>
> Valid flags are @code{PTHREAD_RWLOCK_ELISION_NP} to force elision and @code{PTHREAD_RWLOCK_NO_ELISION_NP}
> to disable elision. These can be ored with other rwlock types.
> @@ -228,3 +288,28 @@ pthread_rwlockattr_settype (&rwattr, PTHREAD_RWLOCK_NO_ELISION_NP);
> pthread_rwlock_init (&object->myrwlock, &rwattr);
> @end smallexample
>
> +@node Setting @code{pthread_rwlock_t} elision using environment variables
> +@section Setting @code{pthread_rwlock_t} elision using environment variables
> +The elision of @code{pthread_rwlock_t} rwlocks can be configured at
> +runtime with the @code{GLIBC_PTHREAD_RWLOCK} environment variable.
> +This will force a specific lock type for all
> +rwlockes in the program that do not have another type set explicitly.
> +An explicitly set lock type will override the environment variable.
> +
> +@smallexample
> +# run myprogram with no elision
> +GLIBC_PTHREAD_RWLOCK=none myprogram
See below.
> +@end smallexample
> +
> +The default depends on the @theglibc{} build configuration and whether the hardware
> +supports lock elision.
> +
> +@itemize
> +@item
> +@code{GLIBC_PTHREAD_RWLOCK=elision}
> +Use elided rwlockes, unless explicitly disabled in the program.
> +
> +@item
> +@code{GLIBC_PTHREAD_RWLOCK=none}
> +Don't use elided rwlocks, unless explicitly enabled in the program.
> +@end itemize
> diff --git a/nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c b/nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c
> index 29bd654..e10e420 100644
> --- a/nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c
> +++ b/nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c
> @@ -18,8 +18,10 @@
>
> #include "config.h"
> #include <pthreadP.h>
> +#include <unistd.h>
> #include <init-arch.h>
> #include <elision-conf.h>
> +#include <glibc-var.h>
>
> struct elision_config __elision_aconf =
> {
> @@ -29,6 +31,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;
> + }
> + }
> +}
> +
> /* Elided rwlock toggle. */
>
> int __rwlock_rtm_enabled attribute_hidden;
> @@ -45,6 +126,54 @@ 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 (strncmp (s, "none", 4) == 0 && s[4] == 0)
This should be "no_elision" or something like that. A setting like
"GLIBC_PTHREAD_MUTEX=none" is confusing: no what? no mutexes?
> + __pthread_force_elision = 0;
> + else
> + complain (PAIR ("pthreads: Unknown setting for GLIBC_PTHREAD_MUTEX\n"));
> +}
> +
> +/* Initialize elision for rwlocks. */
> +
> +static void
> +elision_rwlock_init (const char *s)
> +{
> + if (s == NULL)
> + return;
> + if (strncmp (s, "elision", 7) == 0)
> + {
> + __rwlock_rtm_enabled = __elision_available;
> + if (s[7] == ':')
> + {
> + char *end;
> + int n;
> +
> + n = strtoul (s + 8, &end, 0);
> + if (end == s + 8)
> + complain (PAIR ("pthreads: Bad retry number for GLIBC_PTHREAD_RWLOCK\n"));
> + else
> + __rwlock_rtm_read_retries = n;
> + }
> + }
> + else if (strcmp (s, "none") == 0)
> + __rwlock_rtm_enabled = 0;
> + else
> + complain (PAIR ("pthreads: Unknown setting for GLIBC_PTHREAD_RWLOCK\n"));
> +}
> +
> /* Initialize elison. */
>
> static void
> @@ -57,6 +186,11 @@ elision_init (int argc __attribute__ ((unused)),
> __pthread_force_elision = __elision_available;
> __rwlock_rtm_enabled = __elision_available;
> #endif
> +
> + /* 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);
> + elision_rwlock_init (_dl_glibc_var[GLIBC_VAR_PTHREAD_RWLOCK].val);
> }
>
> #ifdef SHARED