This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH 2/2] Add environment variable tuning for elision parameters.
- From: Andi Kleen <andi at firstfloor dot org>
- To: libc-alpha at sourceware dot org
- Cc: Andi Kleen <ak at linux dot jf dot intel dot com>
- Date: Tue, 18 Jun 2013 14:52:50 -0700
- Subject: [PATCH 2/2] Add environment variable tuning for elision parameters.
- References: <1371592370-22170-1-git-send-email-andi at firstfloor dot org>
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-18 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-18 Andi Kleen <ak@linux.intel.com>
* manual/elision.texi: Add sections describing environment variables.
---
manual/elision.texi | 98 ++++++++++++++++-
nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c | 135 +++++++++++++++++++++++-
2 files changed, 231 insertions(+), 2 deletions(-)
diff --git a/manual/elision.texi b/manual/elision.texi
index f05eae2..698098b 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
@@ -176,7 +178,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.
@@ -215,10 +217,73 @@ 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 enabled in the program.
+
+@item
+@code{GLIBC_PTHREAD_MUTEX=no_elision}
+Don't use elide mutexes, unless explicitly enabled in the program.
+Alias for none.
+@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.
@@ -231,3 +296,34 @@ 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. Also suid programs don't enable elision by default, unless
+the choice is overriden.
+
+@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.
+
+@item
+@code{GLIBC_PTHREAD_RWLOCK=no_elision}
+Don't use elided rwlocks, unless explicitly enabled in the program.
+Alias for none.
+@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 4a2956c..39ea383 100644
--- a/nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c
+++ b/nptl/sysdeps/unix/sysv/linux/x86/elision-conf.c
@@ -18,9 +18,10 @@
#include "config.h"
#include <pthreadP.h>
+#include <unistd.h>
#include <init-arch.h>
#include <elision-conf.h>
-#include <unistd.h>
+#include <glibc-var.h>
struct elision_config __elision_aconf =
{
@@ -30,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;
@@ -46,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 (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 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 || strcmp (s, "no_elision") == 0)
+ __rwlock_rtm_enabled = 0;
+ else
+ complain (PAIR ("pthreads: Unknown setting for GLIBC_PTHREAD_RWLOCK\n"));
+}
+
/* Initialize elison. */
static void
@@ -58,6 +186,11 @@ elision_init (int argc __attribute__ ((unused)),
__pthread_force_elision = __libc_enable_secure ? 0 : __elision_available;
__rwlock_rtm_enabled = __libc_enable_secure ? 0 : __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