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: [RFC][PATCH 1/2] Port of lock elision on z/Architecture


Corrected patch; some changes were in the sencond patch but should
have been in the first one.  The new set of patches is smaller and
hopefully easier to read.

>From 066a0e26514d119c79750f151d5819d38e63735d Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@de.ibm.com>
Date: Wed, 10 Apr 2013 15:14:07 +0200
Subject: [PATCH 01/10] s390: Lowlevel infrastructure for lock pthread_mutex
 lock elision.

---
 nptl/sysdeps/unix/sysv/linux/s390/Makefile         |   2 +
 nptl/sysdeps/unix/sysv/linux/s390/elision-common.c |  40 +++++++
 nptl/sysdeps/unix/sysv/linux/s390/elision-common.h |  26 +++++
 nptl/sysdeps/unix/sysv/linux/s390/elision-conf.c   |  82 +++++++++++++++
 nptl/sysdeps/unix/sysv/linux/s390/elision-conf.h   |  42 ++++++++
 nptl/sysdeps/unix/sysv/linux/s390/elision-lock.c   | 105 +++++++++++++++++++
 nptl/sysdeps/unix/sysv/linux/s390/elision-timed.c  |  26 +++++
 .../sysdeps/unix/sysv/linux/s390/elision-trylock.c |  82 +++++++++++++++
 nptl/sysdeps/unix/sysv/linux/s390/elision-unlock.c |  41 ++++++++
 nptl/sysdeps/unix/sysv/linux/s390/htm.h            | 115 +++++++++++++++++++++
 nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h   |  23 +++++
 11 files changed, 584 insertions(+)
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/Makefile
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-common.c
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-common.h
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-conf.c
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-conf.h
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-lock.c
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-timed.c
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-trylock.c
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/elision-unlock.c
 create mode 100644 nptl/sysdeps/unix/sysv/linux/s390/htm.h

diff --git a/nptl/sysdeps/unix/sysv/linux/s390/Makefile b/nptl/sysdeps/unix/sysv/linux/s390/Makefile
new file mode 100644
index 0000000..6a6b455
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/Makefile
@@ -0,0 +1,2 @@
+libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
+			      elision-trylock elision-common
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-common.c b/nptl/sysdeps/unix/sysv/linux/s390/elision-common.c
new file mode 100644
index 0000000..be138f1
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-common.c
@@ -0,0 +1,40 @@
+/* elision-common.c: Code shared by specific elision function implementations.
+   Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <elision-common.h>
+
+__attribute__ ((aligned(256))) __thread char __my_etdb[256] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+__thread uint64_t __attribute__ ((aligned(8))) __rtm_explicit_abort_rc = 0;
+libc_hidden_def (__rtm_explicit_abort_rc);
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-common.h b/nptl/sysdeps/unix/sysv/linux/s390/elision-common.h
new file mode 100644
index 0000000..15f05ee
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-common.h
@@ -0,0 +1,26 @@
+/* elision-common.h: Code shared by specific elision function implementations.
+   Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#ifndef _ELISION_COMMON_H
+#define _ELISION_COMMON_H 1
+
+#include <tls.h>
+
+extern __thread char __my_etdb[256];
+extern __thread uint64_t __rtm_explicit_abort_rc;
+
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-conf.c b/nptl/sysdeps/unix/sysv/linux/s390/elision-conf.c
new file mode 100644
index 0000000..76df37f
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-conf.c
@@ -0,0 +1,82 @@
+/* elision-conf.c: Lock elision tunable parameters.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include <pthreadP.h>
+#include <elision-conf.h>
+#include <unistd.h>
+#include <dl-procinfo.h>
+
+/* Reasonable initial tuning values, may be revised in the future.
+   This is a conservative initial value.  */
+
+struct elision_config __elision_aconf =
+  {
+    /* How often to not attempt to use elision if a transaction aborted
+       because the lock is already acquired.  Expressed in number of lock
+       acquisition attempts.  */
+    .skip_lock_busy = 3,
+    /* How often to not attempt to use elision if a transaction aborted due
+       to reasons other than other threads' memory accesses.  Expressed in
+       number of lock acquisition attempts.  */
+    .skip_lock_internal_abort = 3,
+    /* How often we retry using elision if there is chance for the transaction
+       to finish execution (e.g., it wasn't aborted due to the lock being
+       already acquired.  */
+    .retry_try_xbegin = 3,
+    /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock.  */
+    .skip_trylock_internal_abort = 3,
+  };
+
+/* Set when the CPU supports elision. When false elision is never attempted.  */
+
+int __elision_available attribute_hidden;
+
+/* Force elision for all new locks.  This is used to decide whether existing
+   DEFAULT locks should be automatically upgraded to elision in
+   pthread_mutex_lock().  Disabled for suid programs.  Only used when elision
+   is available.  */
+
+int __pthread_force_elision attribute_hidden;
+
+/* Initialize elison.  */
+
+static void
+elision_init (int argc __attribute__ ((unused)),
+	      char **argv  __attribute__ ((unused)),
+	      char **environ)
+{
+  __elision_available = (GLRO (dl_hwcap) & HWCAP_S390_TE) ? 1 : 0;
+#ifdef ENABLE_LOCK_ELISION
+  __pthread_force_elision = __libc_enable_secure ? 0 : __elision_available;
+#endif
+}
+
+#ifdef SHARED
+# define INIT_SECTION ".init_array"
+# define MAYBE_CONST
+#else
+# define INIT_SECTION ".preinit_array"
+# define MAYBE_CONST const
+#endif
+
+void (*MAYBE_CONST __pthread_init_array []) (int, char **, char **)
+  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
+{
+  &elision_init
+};
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-conf.h b/nptl/sysdeps/unix/sysv/linux/s390/elision-conf.h
new file mode 100644
index 0000000..c62b723
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-conf.h
@@ -0,0 +1,42 @@
+/* elision-conf.h: Lock elision tunable parameters.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#ifndef _ELISION_CONF_H
+#define _ELISION_CONF_H 1
+
+#include <pthread.h>
+#include <time.h>
+
+/* Should make sure there is no false sharing on this.  */
+
+struct elision_config
+{
+  int skip_lock_busy;
+  int skip_lock_internal_abort;
+  int retry_try_xbegin;
+  int skip_trylock_internal_abort;
+};
+
+extern struct elision_config __elision_aconf attribute_hidden;
+
+extern int __elision_available attribute_hidden;
+extern int __pthread_force_elision attribute_hidden;
+
+/* Tell the test suite to test elision for this architecture.  */
+#define HAVE_ELISION 1
+
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-lock.c b/nptl/sysdeps/unix/sysv/linux/s390/elision-lock.c
new file mode 100644
index 0000000..ec0db56
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-lock.c
@@ -0,0 +1,105 @@
+/* elision-lock.c: Elided pthread mutex lock.
+   Copyright (C) 2011-2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <pthreadP.h>
+#include <lowlevellock.h>
+#include "htm.h"
+#include <elision-conf.h>
+#include "elision-common.h"
+
+#if !defined(LLL_LOCK) && !defined(EXTRAARG)
+/* Make sure the configuration code is always linked in for static
+   libraries.  */
+#include "elision-conf.c"
+#endif
+
+#ifndef EXTRAARG
+#define EXTRAARG
+#endif
+#ifndef LLL_LOCK
+#define LLL_LOCK(a,b) lll_lock(a,b), 0
+#endif
+
+#define aconf __elision_aconf
+
+/* Adaptive lock using transactions.
+   By default the lock region is run as a transaction, and when it
+   aborts or the lock is busy the lock adapts itself.  */
+
+int
+__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private)
+{
+  if (*adapt_count <= 0)
+    {
+      unsigned status;
+      int try_xbegin;
+      uint64_t explicit_abort_rc;
+
+      for (try_xbegin = aconf.retry_try_xbegin;
+	   try_xbegin > 0;
+	   try_xbegin--)
+	{
+	  if (__builtin_expect
+	      ((status = __builtin_tbegin((void *)0)) == _TBEGIN_OK, 1))
+	    {
+	      if (*futex == 0)
+		return 0;
+
+	      /* Lock was busy.  Fall back to normal locking.  We cannot use
+		 _tend here because this might not be the outermost
+		 transaction.  */
+	      __builtin_non_tx_store (&__rtm_explicit_abort_rc,
+				      _ABORT_LOCK_BUSY);
+	      __builtin_tabort (_ABORT_LOCK_BUSY);
+	    }
+
+	  asm volatile (
+	    "" ::: "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
+	    "f10", "f11", "f12", "f13", "f14", "f15", "cc", "memory");
+	  explicit_abort_rc = __rtm_explicit_abort_rc;
+	  __rtm_explicit_abort_rc = 0;
+
+	  if (status != _TABORT_RETRY)
+	    {
+	      if (explicit_abort_rc == _ABORT_LOCK_BUSY)
+	        {
+		  /* Right now we skip here.  Better would be to wait a bit
+		     and retry.  This likely needs some spinning.  */
+		  if (*adapt_count != aconf.skip_lock_busy)
+		    *adapt_count = aconf.skip_lock_busy;
+		}
+	      /* The condition code indicates that a retry is probably futile.
+		 Use the normal locking and next time use lock.
+		 Be careful to avoid writing to the lock.  */
+	      else if (*adapt_count != aconf.skip_lock_internal_abort)
+		*adapt_count = aconf.skip_lock_internal_abort;
+	      break;
+	    }
+	}
+    }
+  else
+    {
+      /* Use a normal lock until the threshold counter runs out.
+	 Lost updates possible.  */
+      (*adapt_count)--;
+    }
+
+  /* Use a normal lock here.  */
+  return LLL_LOCK ((*futex), private);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-timed.c b/nptl/sysdeps/unix/sysv/linux/s390/elision-timed.c
new file mode 100644
index 0000000..1532964
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-timed.c
@@ -0,0 +1,26 @@
+/* elision-timed.c: Lock elision timed lock.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <time.h>
+#include <elision-conf.h>
+#include "lowlevellock.h"
+#define __lll_lock_elision __lll_timedlock_elision
+#define EXTRAARG const struct timespec *t,
+#undef LLL_LOCK
+#define LLL_LOCK(a, b) lll_timedlock(a, t, b)
+#include "elision-lock.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-trylock.c b/nptl/sysdeps/unix/sysv/linux/s390/elision-trylock.c
new file mode 100644
index 0000000..9eed967
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-trylock.c
@@ -0,0 +1,82 @@
+/* elision-trylock.c: Lock eliding trylock for pthreads.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <pthreadP.h>
+#include <lowlevellock.h>
+#include "htm.h"
+#include <elision-conf.h>
+#include "elision-common.h"
+
+#define aconf __elision_aconf
+
+/* Try to elide a futex trylock.  FUTEX is the futex variable.  ADAPT_COUNT is
+   the adaptation counter in the mutex.  */
+
+int
+__lll_trylock_elision (int *futex, short *adapt_count)
+{
+  /* Implement POSIX semantics by forbiding nesting
+     trylock.  Sorry.  After the abort the code is re-executed
+     non transactional and if the lock was already locked
+     return an error.  */
+  if (__builtin_tx_nesting_depth () > 0)
+    {
+      __builtin_non_tx_store (&__rtm_explicit_abort_rc, _ABORT_NESTED_TRYLOCK);
+      __builtin_tabort (_ABORT_NESTED_TRYLOCK);
+    }
+
+  /* Only try a transaction if it's worth it.  */
+  if (*adapt_count <= 0)
+    {
+      unsigned status;
+
+      if (__builtin_expect
+	  ((status = __builtin_tbegin ((void *)0)) == _TBEGIN_OK, 1))
+	{
+	  if (*futex == 0)
+	    return 0;
+
+	  /* Lock was busy.  Fall back to normal locking.  We cannot use
+	     _tend here because this might not be the outermost
+	     transaction.  */
+	  __builtin_non_tx_store (&__rtm_explicit_abort_rc, _ABORT_LOCK_BUSY);
+	  __builtin_tabort (_ABORT_LOCK_BUSY);
+	}
+
+      asm volatile (
+	"" ::: "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
+	"f10", "f11", "f12", "f13", "f14", "f15", "cc", "memory");
+      __rtm_explicit_abort_rc = 0;
+      if (status != _TABORT_RETRY)
+        {
+          /* The condition code indicates that a retry is probably futile.
+	     For future locks don't try speculation for some time.  */
+          if (*adapt_count != aconf.skip_trylock_internal_abort)
+            *adapt_count = aconf.skip_trylock_internal_abort;
+        }
+      /* Could do some retries here.  */
+    }
+  else
+    {
+      /* Lost updates are possible, but harmless.  */
+      (*adapt_count)--;
+    }
+
+  return lll_trylock (*futex);
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/elision-unlock.c b/nptl/sysdeps/unix/sysv/linux/s390/elision-unlock.c
new file mode 100644
index 0000000..ac42d24
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/elision-unlock.c
@@ -0,0 +1,41 @@
+/* elision-unlock.c: Commit an elided pthread lock.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "pthreadP.h"
+#include "lowlevellock.h"
+#include "htm.h"
+
+int
+__lll_unlock_elision(int *lock, int private)
+{
+  /* When the lock was free we're in a transaction.
+     When you crash here you unlocked a free lock.  */
+  if (*lock == 0)
+    {
+      /* The instruction ETND is slower than TEND, so the latter is used to
+	 check whether there was an active transaction.  */
+      if (__builtin_expect (__builtin_tend() != 0, 0))
+	{
+	  /* Lock released outside a transaction.  */
+	  abort ();
+	}
+    }
+  else
+    lll_unlock ((*lock), private);
+  return 0;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/htm.h b/nptl/sysdeps/unix/sysv/linux/s390/htm.h
new file mode 100644
index 0000000..3e0fbd1
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/s390/htm.h
@@ -0,0 +1,115 @@
+/* Shared HTM header.  Emulate transactional execution facility intrinsics for
+ * compilers and assemblers that do not support the intrinsics and instructions
+ * yet.  */
+#ifndef _HTM_H
+#define _HTM_H 1
+
+#ifdef __ASSEMBLER__
+
+.macro TBEGIN rsm, flags
+	.byte 0xe5,0x60,0x00,0x00,\rsm,\flags
+.endm
+
+.macro TEND
+	.insn s,0xb2f80000,0(0)
+.endm
+
+.macro TABORT code
+	.insn s,0xb2fc0000,\code
+.endm
+
+.macro NTSTG code_reg, addr_reg
+	.byte 0xe3
+	.byte \code_reg << 4
+	.byte \addr_reg << 4
+	.byte 0x00,0x00,0x25
+.endm
+
+.macro ETND dest_reg
+	.byte 0xb2,0xec,0x00,\dest_reg << 4
+.endm
+
+#endif
+
+/* Official HTM intrinsics interface matching gcc/icc, but works
+   on older gcc compatible compilers and binutils.
+   We should somehow detect if the compiler supports it, because
+   it may be able to generate slightly better code.  */
+
+#define _TBEGIN_OK		(0u)
+#define _TABORT_RETRY		(2u)
+#define _TABORT_CODE(x)		(((x) >> 24) & 0xff)
+
+#define _ABORT_LOCK_BUSY 	0x1ff
+#define _ABORT_LOCK_IS_LOCKED	0x1fe
+#define _ABORT_NESTED_TRYLOCK	0x1fd
+#endif
+
+#ifndef __ASSEMBLER__
+
+#ifndef __HTM__
+
+#define __force_inline inline __attribute__((__always_inline__))
+#define __force_inline_unused inline __attribute__((__always_inline__,unused))
+
+static __force_inline_unused int _tbegin(void)
+{
+  int ret;
+  asm volatile (
+    ".insn sil,0xe56000000000,0(0),-242\n"
+    "ipm %0\n"
+    "srl %0, 28\n"
+    : "=d" (ret) :: "cc", "memory");
+  return ret;
+}
+
+static __force_inline_unused int _tbegin_debug(void *tdb)
+{
+  int ret;
+  asm volatile (
+    ".insn sil,0xe56000000000,0(%1),-242\n"
+    "ipm %0\n"
+    "srl %0, 28\n"
+    : "=d" (ret) : "a" (tdb) : "cc", "memory");
+  return ret;
+}
+
+static __force_inline_unused int _tend(void)
+{
+  int ret;
+  asm volatile (
+    ".insn s,0xb2f80000,0(0)\n"
+    "ipm %0\n"
+    "srl %0, 28\n"
+    : "=d" (ret) :: "cc");
+  return ret;
+}
+
+static __force_inline_unused void _tabort(const unsigned short abortcode)
+{
+  asm volatile (".insn s,0xb2fc0000,%0(0)" :: "J" (abortcode) : "cc", "memory");
+}
+
+static __force_inline_unused void
+_ntstg(void *addr, const unsigned short abortcode)
+{
+  asm volatile (
+    ".insn rxy,0xe30000000025,%1,0(0,%0)\n"
+    :: "d" (abortcode), "a" (addr) :);
+}
+
+static __force_inline_unused unsigned short _etnd(void)
+{
+  unsigned short nd;
+  asm volatile (".insn rre,0xb2ec0000,%0,0\n" : "=d" (nd) ::);
+  return nd;
+}
+
+#define __builtin_tbegin(tdb) _tbegin_debug (tdb)
+#define __builtin_tend() _tend ()
+#define __builtin_tabort(abortcode) _tabort (abortcode)
+#define __builtin_non_tx_store(addr, value) _ntstg (addr, value)
+#define __builtin_tx_nesting_depth _etnd
+
+#endif
+#endif
diff --git a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
index 3dab05e..f2f863e 100644
--- a/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
+++ b/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
@@ -285,6 +285,13 @@ __lll_timedlock (int *futex, const struct timespec *abstime, int private)
 #define lll_timedlock(futex, abstime, private) \
   __lll_timedlock (&(futex), abstime, private)
 
+extern int __lll_timedlock_elision
+  (int *futex, short *adapt_count, const struct timespec *timeout, int private)
+  attribute_hidden;
+
+#define lll_timedlock_elision(futex, adapt_count, timeout, private)	\
+  __lll_timedlock_elision(&(futex), &(adapt_count), timeout, private)
+
 static inline int
 __attribute__ ((always_inline))
 __lll_robust_timedlock (int *futex, const struct timespec *abstime,
@@ -360,4 +367,20 @@ extern int __lll_timedwait_tid (int *, const struct timespec *)
     __res;								      \
   })
 
+extern int __lll_lock_elision (int *futex, short *adapt_count, int private)
+  attribute_hidden;
+
+extern int __lll_unlock_elision(int *lock, int private)
+  attribute_hidden;
+
+extern int __lll_trylock_elision(int *lock, short *adapt_count)
+  attribute_hidden;
+
+#define lll_lock_elision(futex, adapt_count, private) \
+  __lll_lock_elision (&(futex), &(adapt_count), private)
+#define lll_unlock_elision(futex, private) \
+  __lll_unlock_elision (&(futex), private)
+#define lll_trylock_elision(futex, adapt_count) \
+  __lll_trylock_elision(&(futex), &(adapt_count))
+
 #endif	/* lowlevellock.h */
-- 
1.7.11.4

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany


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