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]

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


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
+@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)
+    __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
-- 
1.8.1.4


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