ce426f
commit 8d2c0a593bdefd220be0822fb70de6b8d3bfd39d
ce426f
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
ce426f
Date:   Fri Nov 7 12:25:32 2014 -0500
ce426f
ce426f
    powerpc: Add the lock elision using HTM
ce426f
    
ce426f
    This patch adds support for lock elision using ISA 2.07 hardware
ce426f
    transactional memory instructions for pthread_mutex primitives.
ce426f
    Similar to s390 version, the for elision logic defined in
ce426f
    'force-elision.h' is only enabled if ENABLE_LOCK_ELISION is defined.
ce426f
    
ce426f
    Also, the lock elision code should be able to be built even with
ce426f
    a compiler that does not provide HTM support with builtins.
ce426f
    However I have noted the performance is sub-optimal due scheduling
ce426f
    pressures.
ce426f
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
ce426f
@@ -0,0 +1,80 @@
ce426f
+/* elision-conf.c: Lock elision tunable parameters.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include "config.h"
ce426f
+#include <pthreadP.h>
ce426f
+#include <elision-conf.h>
ce426f
+#include <unistd.h>
ce426f
+#include <dl-procinfo.h>
ce426f
+
ce426f
+/* Reasonable initial tuning values, may be revised in the future.
ce426f
+   This is a conservative initial value.  */
ce426f
+
ce426f
+struct elision_config __elision_aconf =
ce426f
+  {
ce426f
+    /* How many times to use a non-transactional lock after a transactional
ce426f
+       failure has occurred because the lock is already acquired.  Expressed
ce426f
+       in number of lock acquisition attempts.  */
ce426f
+    .skip_lock_busy = 3,
ce426f
+    /* How often to not attempt to use elision if a transaction aborted due
ce426f
+       to reasons other than other threads' memory accesses.  Expressed in
ce426f
+       number of lock acquisition attempts.  */
ce426f
+    .skip_lock_internal_abort = 3,
ce426f
+    /* How often to not attempt to use elision if a lock used up all retries
ce426f
+       without success.  Expressed in number of lock acquisition attempts.  */
ce426f
+    .skip_lock_out_of_tbegin_retries = 3,
ce426f
+    /* How often we retry using elision if there is chance for the transaction
ce426f
+       to finish execution (e.g., it wasn't aborted due to the lock being
ce426f
+       already acquired.  */
ce426f
+    .try_tbegin = 3,
ce426f
+    /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock.  */
ce426f
+    .skip_trylock_internal_abort = 3,
ce426f
+  };
ce426f
+
ce426f
+/* Force elision for all new locks.  This is used to decide whether existing
ce426f
+   DEFAULT locks should be automatically use elision in pthread_mutex_lock().
ce426f
+   Disabled for suid programs.  Only used when elision is available.  */
ce426f
+
ce426f
+int __pthread_force_elision attribute_hidden;
ce426f
+
ce426f
+/* Initialize elision.  */
ce426f
+
ce426f
+static void
ce426f
+elision_init (int argc __attribute__ ((unused)),
ce426f
+	      char **argv  __attribute__ ((unused)),
ce426f
+	      char **environ)
ce426f
+{
ce426f
+#ifdef ENABLE_LOCK_ELISION
ce426f
+  int elision_available = (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM) ? 1 : 0;
ce426f
+  __pthread_force_elision = __libc_enable_secure ? 0 : elision_available;
ce426f
+#endif
ce426f
+}
ce426f
+
ce426f
+#ifdef SHARED
ce426f
+# define INIT_SECTION ".init_array"
ce426f
+# define MAYBE_CONST
ce426f
+#else
ce426f
+# define INIT_SECTION ".preinit_array"
ce426f
+# define MAYBE_CONST const
ce426f
+#endif
ce426f
+
ce426f
+void (*MAYBE_CONST __pthread_init_array []) (int, char **, char **)
ce426f
+  __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
ce426f
+{
ce426f
+  &elision_init
ce426f
+};
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-conf.h
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-conf.h
ce426f
@@ -0,0 +1,42 @@
ce426f
+/* elision-conf.h: Lock elision tunable parameters.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#ifndef _ELISION_CONF_H
ce426f
+#define _ELISION_CONF_H 1
ce426f
+
ce426f
+#include <pthread.h>
ce426f
+#include <time.h>
ce426f
+
ce426f
+/* Should make sure there is no false sharing on this.  */
ce426f
+struct elision_config
ce426f
+{
ce426f
+  int skip_lock_busy;
ce426f
+  int skip_lock_internal_abort;
ce426f
+  int skip_lock_out_of_tbegin_retries;
ce426f
+  int try_tbegin;
ce426f
+  int skip_trylock_internal_abort;
ce426f
+} __attribute__ ((__aligned__ (128)));
ce426f
+
ce426f
+extern struct elision_config __elision_aconf attribute_hidden;
ce426f
+
ce426f
+extern int __pthread_force_elision attribute_hidden;
ce426f
+
ce426f
+/* Tell the test suite to test elision for this architecture.  */
ce426f
+#define HAVE_ELISION 1
ce426f
+
ce426f
+#endif
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
ce426f
@@ -0,0 +1,107 @@
ce426f
+/* elision-lock.c: Elided pthread mutex lock.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <stdio.h>
ce426f
+#include <pthread.h>
ce426f
+#include <pthreadP.h>
ce426f
+#include <lowlevellock.h>
ce426f
+#include <elision-conf.h>
ce426f
+#include "htm.h"
ce426f
+
ce426f
+/* PowerISA 2.0.7 Section B.5.5 defines isync to be insufficient as a
ce426f
+   barrier in acquire mechanism for HTM operations, a strong 'sync' is
ce426f
+   required.  */
ce426f
+#undef __arch_compare_and_exchange_val_32_acq
ce426f
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)           \
ce426f
+  ({                                                                          \
ce426f
+      __typeof (*(mem)) __tmp;                                                \
ce426f
+      __typeof (mem)  __memp = (mem);                                         \
ce426f
+      __asm __volatile (                                                      \
ce426f
+                        "1:     lwarx   %0,0,%1" MUTEX_HINT_ACQ "\n"          \
ce426f
+                        "       cmpw    %0,%2\n"                              \
ce426f
+                        "       bne     2f\n"                                 \
ce426f
+                        "       stwcx.  %3,0,%1\n"                            \
ce426f
+                        "       bne-    1b\n"                                 \
ce426f
+                        "2:     sync"                                         \
ce426f
+                        : "=&r" (__tmp)                                       \
ce426f
+                        : "b" (__memp), "r" (oldval), "r" (newval)            \
ce426f
+                        : "cr0", "memory");                                   \
ce426f
+      __tmp;                                                                  \
ce426f
+  })
ce426f
+
ce426f
+#if !defined(LLL_LOCK) && !defined(EXTRAARG)
ce426f
+/* Make sure the configuration code is always linked in for static
ce426f
+   libraries.  */
ce426f
+#include "elision-conf.c"
ce426f
+#endif
ce426f
+
ce426f
+#ifndef EXTRAARG
ce426f
+# define EXTRAARG
ce426f
+#endif
ce426f
+#ifndef LLL_LOCK
ce426f
+# define LLL_LOCK(a,b) lll_lock(a,b), 0
ce426f
+#endif
ce426f
+
ce426f
+#define aconf __elision_aconf
ce426f
+
ce426f
+/* Adaptive lock using transactions.
ce426f
+   By default the lock region is run as a transaction, and when it
ce426f
+   aborts or the lock is busy the lock adapts itself.  */
ce426f
+
ce426f
+int
ce426f
+__lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared)
ce426f
+{
ce426f
+  if (*adapt_count > 0)
ce426f
+    {
ce426f
+      (*adapt_count)--;
ce426f
+      goto use_lock;
ce426f
+    }
ce426f
+
ce426f
+  int try_begin = aconf.try_tbegin;
ce426f
+  while (1)
ce426f
+    {
ce426f
+      if (__builtin_tbegin (0))
ce426f
+	{
ce426f
+	  if (*lock == 0)
ce426f
+	    return 0;
ce426f
+	  /* Lock was busy.  Fall back to normal locking.  */
ce426f
+	  __builtin_tabort (_ABORT_LOCK_BUSY);
ce426f
+	}
ce426f
+      else
ce426f
+	{
ce426f
+	  /* A persistent failure indicates that a retry will probably
ce426f
+	     result in another failure.  Use normal locking now and
ce426f
+	     for the next couple of calls.  */
ce426f
+	  if (try_begin-- <= 0
ce426f
+	      || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
ce426f
+	    {
ce426f
+	      if (aconf.skip_lock_internal_abort > 0)
ce426f
+		*adapt_count = aconf.skip_lock_internal_abort;
ce426f
+	      goto use_lock;
ce426f
+	    }
ce426f
+	  /* Same logic as above, but for for a number of temporary failures
ce426f
+	     in a row.  */
ce426f
+	  else if (aconf.skip_lock_out_of_tbegin_retries > 0
ce426f
+                   && aconf.try_tbegin > 0)
ce426f
+	    *adapt_count = aconf.skip_lock_out_of_tbegin_retries;
ce426f
+	}
ce426f
+     }
ce426f
+
ce426f
+use_lock:
ce426f
+  return LLL_LOCK ((*lock), pshared);
ce426f
+}
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-timed.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-timed.c
ce426f
@@ -0,0 +1,28 @@
ce426f
+/* elision-timed.c: Lock elision timed lock.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <time.h>
ce426f
+#include <elision-conf.h>
ce426f
+#include <lowlevellock.h>
ce426f
+
ce426f
+#define __lll_lock_elision __lll_timedlock_elision
ce426f
+#define EXTRAARG const struct timespec *t,
ce426f
+#undef LLL_LOCK
ce426f
+#define LLL_LOCK(a, b) lll_timedlock(a, t, b)
ce426f
+
ce426f
+#include "elision-lock.c"
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
ce426f
@@ -0,0 +1,68 @@
ce426f
+/* elision-trylock.c: Lock eliding trylock for pthreads.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <pthread.h>
ce426f
+#include <pthreadP.h>
ce426f
+#include <lowlevellock.h>
ce426f
+#include <elision-conf.h>
ce426f
+#include "htm.h"
ce426f
+
ce426f
+#define aconf __elision_aconf
ce426f
+
ce426f
+/* Try to elide a futex trylock.  FUTEX is the futex variable.  ADAPT_COUNT is
ce426f
+   the adaptation counter in the mutex.  */
ce426f
+
ce426f
+int
ce426f
+__lll_trylock_elision (int *futex, short *adapt_count)
ce426f
+{
ce426f
+  /* Implement POSIX semantics by forbiding nesting elided trylocks.  */
ce426f
+  __builtin_tabort (_ABORT_NESTED_TRYLOCK);
ce426f
+
ce426f
+  /* Only try a transaction if it's worth it.  */
ce426f
+  if (*adapt_count > 0)
ce426f
+    {
ce426f
+      (*adapt_count)--;
ce426f
+      goto use_lock;
ce426f
+    }
ce426f
+
ce426f
+  if (__builtin_tbegin (0))
ce426f
+    {
ce426f
+      if (*futex == 0)
ce426f
+	return 0;
ce426f
+
ce426f
+      /* Lock was busy.  Fall back to normal locking.  */
ce426f
+      __builtin_tabort (_ABORT_LOCK_BUSY);
ce426f
+    }
ce426f
+  else
ce426f
+    {
ce426f
+      if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
ce426f
+	{
ce426f
+	  /* A persistent failure indicates that a retry will probably
ce426f
+	     result in another failure.  Use normal locking now and
ce426f
+	     for the next couple of calls.  */
ce426f
+	  if (aconf.skip_trylock_internal_abort > 0)
ce426f
+	    *adapt_count = aconf.skip_trylock_internal_abort;
ce426f
+	}
ce426f
+
ce426f
+	if (aconf.skip_lock_busy > 0)
ce426f
+	  *adapt_count = aconf.skip_lock_busy;
ce426f
+    }
ce426f
+
ce426f
+use_lock:
ce426f
+  return lll_trylock (*futex);
ce426f
+}
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
ce426f
@@ -0,0 +1,32 @@
ce426f
+/* elision-unlock.c: Commit an elided pthread lock.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include "pthreadP.h"
ce426f
+#include <lowlevellock.h>
ce426f
+#include "htm.h"
ce426f
+
ce426f
+int
ce426f
+__lll_unlock_elision(int *lock, int pshared)
ce426f
+{
ce426f
+  /* When the lock was free we're in a transaction.  */
ce426f
+  if (*lock == 0)
ce426f
+    __builtin_tend (0);
ce426f
+  else
ce426f
+    lll_unlock ((*lock), pshared);
ce426f
+  return 0;
ce426f
+}
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/force-elision.h
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/force-elision.h
ce426f
@@ -0,0 +1,28 @@
ce426f
+/* force-elision.h: Automatic enabling of elision for mutexes
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#ifdef ENABLE_LOCK_ELISION
ce426f
+/* Automatically enable elision for existing user lock kinds.  */
ce426f
+#define FORCE_ELISION(m, s)						\
ce426f
+  if (__pthread_force_elision						\
ce426f
+      && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)	\
ce426f
+    {									\
ce426f
+      mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP;			\
ce426f
+      s;								\
ce426f
+    }
ce426f
+#endif
ce426f
Index: glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/htm.h
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/htm.h
ce426f
@@ -0,0 +1,138 @@
ce426f
+/* Shared HTM header.  Emulate transactional execution facility intrinsics for
ce426f
+   compilers and assemblers that do not support the intrinsics and instructions
ce426f
+   yet.
ce426f
+
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#ifndef _HTM_H
ce426f
+#define _HTM_H 1
ce426f
+
ce426f
+#ifdef __ASSEMBLER__
ce426f
+
ce426f
+/* tbegin.  */
ce426f
+.macro TBEGIN
ce426f
+	.long 0x7c00051d
ce426f
+.endm
ce426f
+
ce426f
+/* tend. 0  */
ce426f
+.macro TEND
ce426f
+	.long 0x7c00055d
ce426f
+.endm
ce426f
+
ce426f
+/* tabort. code  */
ce426f
+.macro TABORT code
ce426f
+	.byte 0x7c
ce426f
+	.byte \code
ce426f
+	.byte 0x07
ce426f
+	.byte 0x1d
ce426f
+.endm
ce426f
+
ce426f
+/*"TEXASR - Transaction EXception And Summary Register"
ce426f
+   mfspr %dst,130  */
ce426f
+.macro TEXASR dst
ce426f
+	mfspr \dst,130
ce426f
+.endm
ce426f
+
ce426f
+#else
ce426f
+
ce426f
+#include <endian.h>
ce426f
+
ce426f
+/* Official HTM intrinsics interface matching GCC, but works
ce426f
+   on older GCC compatible compilers and binutils.
ce426f
+   We should somehow detect if the compiler supports it, because
ce426f
+   it may be able to generate slightly better code.  */
ce426f
+
ce426f
+#define TBEGIN ".long 0x7c00051d"
ce426f
+#define TEND   ".long 0x7c00055d"
ce426f
+#if __BYTE_ORDER == __LITTLE_ENDIAN
ce426f
+# define TABORT ".byte 0x1d,0x07,%1,0x1d"
ce426f
+#else
ce426f
+# define TABORT ".byte 0x7c,%1,0x07,0x1d"
ce426f
+#endif
ce426f
+
ce426f
+#define __force_inline        inline __attribute__((__always_inline__))
ce426f
+
ce426f
+#ifndef __HTM__
ce426f
+
ce426f
+#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
ce426f
+  (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1))
ce426f
+#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \
ce426f
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1)
ce426f
+
ce426f
+#define _tbegin()			\
ce426f
+  ({ unsigned int __ret;		\
ce426f
+     asm volatile (			\
ce426f
+       TBEGIN "\t\n"			\
ce426f
+       "mfcr   %0\t\n"			\
ce426f
+       "rlwinm %0,%0,3,1\t\n"		\
ce426f
+       "xori %0,%0,1\t\n"		\
ce426f
+       : "=r" (__ret) :			\
ce426f
+       : "cr0", "memory");		\
ce426f
+     __ret;				\
ce426f
+  })
ce426f
+
ce426f
+#define _tend()				\
ce426f
+  ({ unsigned int __ret;		\
ce426f
+     asm volatile (			\
ce426f
+       TEND "\t\n"			\
ce426f
+       "mfcr   %0\t\n"			\
ce426f
+       "rlwinm %0,%0,3,1\t\n"		\
ce426f
+       "xori %0,%0,1\t\n"		\
ce426f
+       : "=r" (__ret) :			\
ce426f
+       : "cr0", "memory");		\
ce426f
+     __ret;				\
ce426f
+  })
ce426f
+
ce426f
+#define _tabort(__code)			\
ce426f
+  ({ unsigned int __ret;		\
ce426f
+     asm volatile (			\
ce426f
+       TABORT "\t\n"			\
ce426f
+       "mfcr   %0\t\n"			\
ce426f
+       "rlwinm %0,%0,3,1\t\n"		\
ce426f
+       "xori %0,%0,1\t\n"		\
ce426f
+       : "=r" (__ret) : "r" (__code)	\
ce426f
+       : "cr0", "memory");		\
ce426f
+     __ret;				\
ce426f
+  })
ce426f
+
ce426f
+#define _texasru()			\
ce426f
+  ({ unsigned long __ret;		\
ce426f
+     asm volatile (			\
ce426f
+       "mfspr %0,131\t\n"		\
ce426f
+       : "=r" (__ret));			\
ce426f
+     __ret;				\
ce426f
+  })
ce426f
+
ce426f
+#define __builtin_tbegin(tdb)       _tbegin ()
ce426f
+#define __builtin_tend(nested)      _tend ()
ce426f
+#define __builtin_tabort(abortcode) _tabort (abortcode)
ce426f
+#define __builtin_get_texasru()     _texasru ()
ce426f
+
ce426f
+#else
ce426f
+# include <htmintrin.h>
ce426f
+#endif /* __HTM__  */
ce426f
+
ce426f
+#endif /* __ASSEMBLER__ */
ce426f
+
ce426f
+/* Definitions used for TEXASR Failure code (bits 0:6), they need to be even
ce426f
+   because tabort. always sets the first bit.  */
ce426f
+#define _ABORT_LOCK_BUSY       0x3f   /* Lock already used.  */
ce426f
+#define _ABORT_NESTED_TRYLOCK  0x3e   /* Write operation in trylock.  */
ce426f
+#define _ABORT_SYSCALL         0x3d   /* Syscall issued.  */
ce426f
+
ce426f
+#endif
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
ce426f
===================================================================
ce426f
--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
ce426f
@@ -326,4 +326,28 @@ extern int __lll_timedwait_tid (int *, c
ce426f
     __res;								      \
ce426f
   })
ce426f
 
ce426f
+/* Transactional lock elision definitions.  */
ce426f
+extern int __lll_timedlock_elision
ce426f
+  (int *futex, short *adapt_count, const struct timespec *timeout, int private)
ce426f
+  attribute_hidden;
ce426f
+
ce426f
+#define lll_timedlock_elision(futex, adapt_count, timeout, private)	      \
ce426f
+  __lll_timedlock_elision(&(futex), &(adapt_count), timeout, private)
ce426f
+
ce426f
+extern int __lll_lock_elision (int *futex, short *adapt_count, int private)
ce426f
+  attribute_hidden;
ce426f
+
ce426f
+extern int __lll_unlock_elision(int *lock, int private)
ce426f
+  attribute_hidden;
ce426f
+
ce426f
+extern int __lll_trylock_elision(int *lock, short *adapt_count)
ce426f
+  attribute_hidden;
ce426f
+
ce426f
+#define lll_lock_elision(futex, adapt_count, private) \
ce426f
+  __lll_lock_elision (&(futex), &(adapt_count), private)
ce426f
+#define lll_unlock_elision(futex, private) \
ce426f
+  __lll_unlock_elision (&(futex), private)
ce426f
+#define lll_trylock_elision(futex, adapt_count) \
ce426f
+  __lll_trylock_elision (&(futex), &(adapt_count))
ce426f
+
ce426f
 #endif	/* lowlevellock.h */
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c
ce426f
@@ -0,0 +1,22 @@
ce426f
+/* Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+/* The cond lock is not actually elided yet, but we still need to handle
ce426f
+   already elided locks.  */
ce426f
+#include <elision-conf.h>
ce426f
+
ce426f
+#include "sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c"
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c
ce426f
@@ -0,0 +1,22 @@
ce426f
+/* Elided version of pthread_mutex_lock.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <elision-conf.h>
ce426f
+#include <force-elision.h>
ce426f
+
ce426f
+#include <nptl/pthread_mutex_lock.c>
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c
ce426f
@@ -0,0 +1,22 @@
ce426f
+/* Elided version of pthread_mutex_timedlock.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <elision-conf.h>
ce426f
+#include <force-elision.h>
ce426f
+
ce426f
+#include <nptl/pthread_mutex_timedlock.c>
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c
ce426f
===================================================================
ce426f
--- /dev/null
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c
ce426f
@@ -0,0 +1,22 @@
ce426f
+/* Elided version of pthread_mutex_trylock.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <elision-conf.h>
ce426f
+#include <force-elision.h>
ce426f
+
ce426f
+#include <nptl/pthread_mutex_trylock.c>
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
ce426f
===================================================================
ce426f
--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
ce426f
@@ -90,14 +90,25 @@ typedef union
ce426f
        binary compatibility.  */
ce426f
     int __kind;
ce426f
 #if __WORDSIZE == 64
ce426f
-    int __spins;
ce426f
+    short __spins;
ce426f
+    short __elision;
ce426f
     __pthread_list_t __list;
ce426f
 # define __PTHREAD_MUTEX_HAVE_PREV	1
ce426f
+# define __PTHREAD_SPINS             0, 0
ce426f
+# define __PTHREAD_MUTEX_HAVE_ELISION	1
ce426f
 #else
ce426f
     unsigned int __nusers;
ce426f
     __extension__ union
ce426f
     {
ce426f
-      int __spins;
ce426f
+      struct
ce426f
+      {
ce426f
+	short __espins;
ce426f
+	short __elision;
ce426f
+# define __spins __elision_data.__espins
ce426f
+# define __elision __elision_data.__elision
ce426f
+# define __PTHREAD_SPINS         { 0, 0 }
ce426f
+# define __PTHREAD_MUTEX_HAVE_ELISION	2
ce426f
+      } __elision_data;
ce426f
       __pthread_slist_t __list;
ce426f
     };
ce426f
 #endif
ce426f
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile
ce426f
===================================================================
ce426f
--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile
ce426f
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile
ce426f
@@ -1,2 +1,4 @@
ce426f
 # pull in __syscall_error routine
ce426f
 libpthread-routines += sysdep
ce426f
+libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
ce426f
+			      elision-trylock