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]

Re: [PATCH 2/2] Add environment variable tuning for elision parameters.


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




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