diff mbox

[1/3] PowerPC: Add the low level infrastructure for pthreads

Message ID 545CFD9F.5040004@linux.vnet.ibm.com
State New
Headers show

Commit Message

Adhemerval Zanella Nov. 7, 2014, 5:13 p.m. UTC
This patch adds support for lock elision using ISA 2.07 hardware
transactional memory instructions for pthread_mutex primitives.
Similar to s390 version, the for elision logic defined in 
'force-elision.h' is only enabled if ENABLE_LOCK_ELISION is defined.

Also, the lock elision code should be able to be built even with
a compiler that does not provide HTM support with builtins.  
However I have noted the performance is sub-optimal due scheduling
pressures.

--

	* sysdeps/unix/sysv/linux/powerpc/Makefile [nptl]
	(sysdep_routines): Add lock elision objects.
	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
	[pthread_mutex_t] (__spins): Rework to add lock elision field.
	[pthread_mutex_t] (__elision): Add field.
	[__PTHREAD_SPINS]: Adjust to init lock elision field.
	* sysdeps/unix/sysv/linux/powerpc/elision-conf.c: New file: lock
	elision definitions for powerpc.
	* sysdeps/unix/sysv/linux/powerpc/elision-lock.c: New file:
	implementation of lock elision for powerpc.
	* sysdeps/unix/sysv/linux/powerpc/elision-timed.c: New file:
	implementation of timed lock elision for powerpc.
	* sysdeps/unix/sysv/linux/powerpc/elision-trylock.c: New file:
	implementation of trylock with lock elision for powerpc.
	* sysdeps/unix/sysv/linux/powerpc/elision-unlock.c: New file:
	implementaion of unlock for lock elision for powerpc.
	* sysdeps/unix/sysv/linux/powerpc/force-elision.h: New file:
	automatic enable lock elision for mutexes.
	* sysdeps/unix/sysv/linux/powerpc/htm.h: New file: hardware
	transaction execution definitions for powerpc.
	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
	(__lll_timedlock_elision): New prototype.
	(__lll_lock_elision): Likewise.
	(__lll_unlock_elision): Likewise.
	(__lll_trylock_elision): Likewise.
	(lll_timedlock_elision): New define.
	(lll_lock_elision): Likewise.
	(lll_unlock_elision): Likewise.
	(lll_trylock_elision): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c: Likewise.

---

Comments

Adhemerval Zanella Nov. 7, 2014, 5:57 p.m. UTC | #1
This patch is a wrong rebase I did, please do not consider it.
I will send a correct version shortly, thanks.


On 07-11-2014 15:13, Adhemerval Zanella wrote:
> This patch adds support for lock elision using ISA 2.07 hardware
> transactional memory instructions for pthread_mutex primitives.
> Similar to s390 version, the for elision logic defined in 
> 'force-elision.h' is only enabled if ENABLE_LOCK_ELISION is defined.
>
> Also, the lock elision code should be able to be built even with
> a compiler that does not provide HTM support with builtins.  
> However I have noted the performance is sub-optimal due scheduling
> pressures.
>
> --
>
> 	* sysdeps/unix/sysv/linux/powerpc/Makefile [nptl]
> 	(sysdep_routines): Add lock elision objects.
> 	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> 	[pthread_mutex_t] (__spins): Rework to add lock elision field.
> 	[pthread_mutex_t] (__elision): Add field.
> 	[__PTHREAD_SPINS]: Adjust to init lock elision field.
> 	* sysdeps/unix/sysv/linux/powerpc/elision-conf.c: New file: lock
> 	elision definitions for powerpc.
> 	* sysdeps/unix/sysv/linux/powerpc/elision-lock.c: New file:
> 	implementation of lock elision for powerpc.
> 	* sysdeps/unix/sysv/linux/powerpc/elision-timed.c: New file:
> 	implementation of timed lock elision for powerpc.
> 	* sysdeps/unix/sysv/linux/powerpc/elision-trylock.c: New file:
> 	implementation of trylock with lock elision for powerpc.
> 	* sysdeps/unix/sysv/linux/powerpc/elision-unlock.c: New file:
> 	implementaion of unlock for lock elision for powerpc.
> 	* sysdeps/unix/sysv/linux/powerpc/force-elision.h: New file:
> 	automatic enable lock elision for mutexes.
> 	* sysdeps/unix/sysv/linux/powerpc/htm.h: New file: hardware
> 	transaction execution definitions for powerpc.
> 	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
> 	(__lll_timedlock_elision): New prototype.
> 	(__lll_lock_elision): Likewise.
> 	(__lll_unlock_elision): Likewise.
> 	(__lll_trylock_elision): Likewise.
> 	(lll_timedlock_elision): New define.
> 	(lll_lock_elision): Likewise.
> 	(lll_unlock_elision): Likewise.
> 	(lll_trylock_elision): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c: New file.
> 	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c: Likewise.
>
> ---
>
> diff --git a/ChangeLog b/ChangeLog
> index a8d9c49..7fec4b9 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,39 @@
> +2014-11-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
> +
> +	* sysdeps/unix/sysv/linux/powerpc/Makefile [nptl]
> +	(sysdep_routines): Add lock elision objects.
> +	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> +	[pthread_mutex_t] (__spins): Rework to add lock elision field.
> +	[pthread_mutex_t] (__elision): Add field.
> +	[__PTHREAD_SPINS]: Adjust to init lock elision field.
> +	* sysdeps/unix/sysv/linux/powerpc/elision-conf.c: New file: lock
> +	elision definitions for powerpc.
> +	* sysdeps/unix/sysv/linux/powerpc/elision-lock.c: New file:
> +	implementation of lock elision for powerpc.
> +	* sysdeps/unix/sysv/linux/powerpc/elision-timed.c: New file:
> +	implementation of timed lock elision for powerpc.
> +	* sysdeps/unix/sysv/linux/powerpc/elision-trylock.c: New file:
> +	implementation of trylock with lock elision for powerpc.
> +	* sysdeps/unix/sysv/linux/powerpc/elision-unlock.c: New file:
> +	implementaion of unlock for lock elision for powerpc.
> +	* sysdeps/unix/sysv/linux/powerpc/force-elision.h: New file:
> +	automatic enable lock elision for mutexes.
> +	* sysdeps/unix/sysv/linux/powerpc/htm.h: New file: hardware
> +	transaction execution definitions for powerpc.
> +	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
> +	(__lll_timedlock_elision): New prototype.
> +	(__lll_lock_elision): Likewise.
> +	(__lll_unlock_elision): Likewise.
> +	(__lll_trylock_elision): Likewise.
> +	(lll_timedlock_elision): New define.
> +	(lll_lock_elision): Likewise.
> +	(lll_unlock_elision): Likewise.
> +	(lll_trylock_elision): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c: New file.
> +	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c: Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c: Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c: Likewise.
> +
>  2014-11-07  Joseph Myers  <joseph@codesourcery.com>
>
>  	* include/sys/wait.h (__libc_waitpid): Remove declaration.
> diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
> index e660736..dd5d3bc 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/Makefile
> +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
> @@ -32,4 +32,6 @@ endif
>
>  ifeq ($(subdir),nptl)
>  libpthread-routines += sysdep
> +libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
> +			      elision-trylock
>  endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> index 4e9c518..396a3d9 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
> @@ -90,14 +90,23 @@ typedef union
>         binary compatibility.  */
>      int __kind;
>  #if __WORDSIZE == 64
> -    int __spins;
> +    short __spins;
> +    short __elision;
>      __pthread_list_t __list;
>  # define __PTHREAD_MUTEX_HAVE_PREV	1
> +# define __PTHREAD_SPINS             0, 0
>  #else
>      unsigned int __nusers;
>      __extension__ union
>      {
> -      int __spins;
> +      struct
> +      {
> +	short __espins;
> +	short __elision;
> +# define __spins __elision_data.__espins
> +# define __elision __elision_data.__elision
> +# define __PTHREAD_SPINS         { 0, 0 }
> +      } __elision_data;
>        __pthread_slist_t __list;
>      };
>  #endif
> @@ -106,9 +115,6 @@ typedef union
>    long int __align;
>  } pthread_mutex_t;
>
> -/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER.  */
> -#define __PTHREAD_SPINS 0
> -
>  typedef union
>  {
>    char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
> diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
> new file mode 100644
> index 0000000..60a7900
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
> @@ -0,0 +1,81 @@
> +/* elision-conf.c: Lock elision tunable parameters.
> +   Copyright (C) 2014 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 to not attempt to use elision if a lock used up all retries
> +       without success.  Expressed in number of lock acquisition attempts.  */
> +    .skip_lock_out_of_tbegin_retries = 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.  */
> +    .try_tbegin = 3,
> +    /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock.  */
> +    .skip_trylock_internal_abort = 3,
> +  };
> +
> +/* 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)
> +{
> +  int elision_available = (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM) ? 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/sysdeps/unix/sysv/linux/powerpc/elision-conf.h b/sysdeps/unix/sysv/linux/powerpc/elision-conf.h
> new file mode 100644
> index 0000000..333226a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.h
> @@ -0,0 +1,43 @@
> +/* elision-conf.h: Lock elision tunable parameters.
> +   Copyright (C) 2014 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 skip_lock_out_of_tbegin_retries;
> +  int try_tbegin;
> +  int skip_trylock_internal_abort;
> +};
> +
> +extern struct elision_config __elision_aconf 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/sysdeps/unix/sysv/linux/powerpc/elision-lock.c b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
> new file mode 100644
> index 0000000..d177465
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
> @@ -0,0 +1,106 @@
> +/* elision-lock.c: Elided pthread mutex lock.
> +   Copyright (C) 2014 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 <stdio.h>
> +#include <pthread.h>
> +#include <pthreadP.h>
> +#include <lowlevellock.h>
> +#include <elision-conf.h>
> +#include "htm.h"
> +
> +/* PowerISA 2.0.7 Section B.5.5 defines isync to be isuficient to memory
> +   barrier in acquire mechanism, a strong sync need to used.  */
> +#undef __arch_compare_and_exchange_val_32_acq
> +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)           \
> +  ({                                                                          \
> +      __typeof (*(mem)) __tmp;                                                \
> +      __typeof (mem)  __memp = (mem);                                         \
> +      __asm __volatile (                                                      \
> +                        "1:     lwarx   %0,0,%1" MUTEX_HINT_ACQ "\n"          \
> +                        "       cmpw    %0,%2\n"                              \
> +                        "       bne     2f\n"                                 \
> +                        "       stwcx.  %3,0,%1\n"                            \
> +                        "       bne-    1b\n"                                 \
> +                        "2:     sync"                                         \
> +                        : "=&r" (__tmp)                                       \
> +                        : "b" (__memp), "r" (oldval), "r" (newval)            \
> +                        : "cr0", "memory");                                   \
> +      __tmp;                                                                  \
> +  })
> +
> +#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 *lock, short *adapt_count, EXTRAARG int pshared)
> +{
> +  if (*adapt_count > 0)
> +    {
> +      (*adapt_count)--;
> +      goto use_lock;
> +    }
> +
> +  int try_begin = aconf.try_tbegin;
> +  while (1)
> +    {
> +      if (__builtin_tbegin (0))
> +	{
> +	  if (*lock == 0)
> +	    return 0;
> +	  /* Lock was busy.  Fall back to normal locking.  */
> +	  __builtin_tabort (_ABORT_LOCK_BUSY);
> +	}
> +      else
> +	{
> +	  /* A persistent failure indicates that a retry will probably
> +	     result in another failure.  Use normal locking now and
> +	     for the next couple of calls.  */
> +	  if (try_begin-- <= 0
> +	      || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
> +	    {
> +	      if (aconf.skip_lock_internal_abort > 0) 
> +		*adapt_count = aconf.skip_lock_internal_abort;
> +	      goto use_lock;
> +	    }
> +	  /* Same logic as above, but for for a number of temporary failures
> +	     in a row.  */
> +	  else if (aconf.skip_lock_out_of_tbegin_retries > 0
> +                   && aconf.try_tbegin > 0)
> +	    *adapt_count = aconf.skip_lock_out_of_tbegin_retries;
> +	}
> +     }
> +
> +use_lock:
> +  return LLL_LOCK ((*lock), pshared);
> +}
> diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-timed.c b/sysdeps/unix/sysv/linux/powerpc/elision-timed.c
> new file mode 100644
> index 0000000..7d5de9b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/elision-timed.c
> @@ -0,0 +1,28 @@
> +/* elision-timed.c: Lock elision timed lock.
> +   Copyright (C) 2014 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/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
> new file mode 100644
> index 0000000..60aaf90
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
> @@ -0,0 +1,68 @@
> +/* elision-trylock.c: Lock eliding trylock for pthreads.
> +   Copyright (C) 2014 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 <elision-conf.h>
> +#include "htm.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 elided trylocks.  */
> +  __builtin_tabort (_ABORT_NESTED_TRYLOCK);
> +
> +  /* Only try a transaction if it's worth it.  */
> +  if (*adapt_count > 0)
> +    {
> +      (*adapt_count)--;
> +      goto use_lock;
> +    }
> +
> +  if (__builtin_tbegin (0))
> +    {
> +      if (*futex == 0)
> +	return 0;
> +
> +      /* Lock was busy.  Fall back to normal locking.  */
> +      __builtin_tabort (_ABORT_LOCK_BUSY);
> +    }
> +  else
> +    {
> +      if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
> +	{
> +	  /* A persistent failure indicates that a retry will probably
> +	     resulting in another failure.  Use normal locking now and
> +	     for the next couple of calls.  */
> +	  if (aconf.skip_trylock_internal_abort > 0)
> +	    *adapt_count = aconf.skip_trylock_internal_abort;
> +	}
> +
> +	if (aconf.skip_lock_busy > 0)
> +	  *adapt_count = aconf.skip_lock_busy;
> +    }
> +
> +use_lock:
> +  return lll_trylock (*futex);
> +}
> diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
> new file mode 100644
> index 0000000..59d46bb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
> @@ -0,0 +1,32 @@
> +/* elision-unlock.c: Commit an elided pthread lock.
> +   Copyright (C) 2014 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 pshared)
> +{
> +  /* When the lock was free we're in a transaction.  */
> +  if (*lock == 0)
> +    __builtin_tend (0);
> +  else
> +    lll_unlock ((*lock), pshared);
> +  return 0;
> +}
> diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
> new file mode 100644
> index 0000000..38c79bf
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
> @@ -0,0 +1,33 @@
> +/* force-elision.h: Automatic enabling of elision for mutexes
> +   Copyright (C) 2014 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/>.  */
> +
> +#ifdef ENABLE_LOCK_ELISION
> +/* Check for elision on this lock without upgrading.  */
> +#define DO_ELISION(m)							\
> +  (__pthread_force_elision						\
> +   && (m->__data.__kind & PTHREAD_MUTEX_NO_ELISION_NP) == 0)		\
> +
> +/* Automatically enable elision for existing user lock kinds.  */
> +#define FORCE_ELISION(m, s)						\
> +  if (__pthread_force_elision						\
> +      && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)	\
> +    {									\
> +      mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP;			\
> +      s;								\
> +    }
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/htm.h b/sysdeps/unix/sysv/linux/powerpc/htm.h
> new file mode 100644
> index 0000000..a031d01
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/htm.h
> @@ -0,0 +1,136 @@
> +/* Shared HTM header.  Emulate transactional execution facility intrinsics for
> +   compilers and assemblers that do not support the intrinsics and instructions
> +   yet. 
> +
> +   Copyright (C) 2014 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 _HTM_H
> +#define _HTM_H 1
> +
> +#ifdef __ASSEMBLER__
> +
> +/* tbegin.  */
> +.macro TBEGIN
> +	.byte 0x7c,0x00,0x05,0x1d
> +.endm
> +
> +/* tend. 0  */
> +.macro TEND
> +	.byte 0x7c,0x00,0x05,0x5d
> +.endm
> +
> +/* tabort. code  */
> +.macro TABORT code
> +        .byte 0x7c
> +        .byte \code
> +	.byte 0x07
> +	.byte 0x1d
> +.endm
> +
> +/* mfspr %dst,130  */
> +.macro TEXASR dst
> +	mfspr \dst,130
> +.endm
> +
> +#else
> +
> +/* Official HTM intrinsics interface matching gcc, 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 ".byte 0x7c,0x00,0x05,0x1d"
> +#define TEND   ".byte 0x7c,0x00,0x05,0x5d"
> +#define TABORT ".byte 0x7c,%1,0x07,0x1d"
> +
> +#define __force_inline        inline __attribute__((__always_inline__))
> +
> +#ifndef __HTM__
> +
> +#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
> +  (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1))
> +#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \
> +  _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1)
> +
> +static __force_inline
> +unsigned int _tbegin (void)
> +{
> +  unsigned int ret;
> +  asm volatile (
> +    TBEGIN "\t\n"
> +    "mfcr   %0,128\t\n"
> +    "rlwinm %0,%0,3,1\t\n"
> +    "subfic %0,%0,1\t\n"
> +    : "=r" (ret) :: "cr0", "memory");
> +  return ret;
> +}
> +
> +static __force_inline
> +unsigned int _tend (void)
> +{
> +  unsigned int ret;
> +  asm volatile (
> +    TEND "\t\n"
> +    "mfcr   %0,128\t\n"
> +    "rlwinm %0,%0,3,1\t\n"
> +    "subfic %0,%0,1\t\n"
> +    : "=r" (ret) :: "cr0", "memory");
> +  return ret;
> +}
> +
> +static __force_inline
> +unsigned int _tabort (unsigned int code)
> +{
> +  unsigned int ret;
> +  asm volatile (
> +    TABORT "\t\n"
> +    "mfcr     %0,128\t\n"
> +    "rlwinm   %0,%0,3,1\t\n"
> +    "subfic   %0,%0,1\t\n"
> +    : "=r" (ret) : "r" (code) : "cr0", "memory");
> +  return ret;
> +}
> +
> +static __force_inline
> +unsigned long _texasru (void)
> +{
> +  unsigned long ret;
> +  asm volatile (
> +    "mfspr %0,131\t\n"
> +    : "=r" (ret));
> +  return ret;
> +}
> +
> +#define __builtin_tbegin(tdb)       _tbegin ()
> +#define __builtin_tend(nested)      _tend ()
> +#define __builtin_tabort(abortcode) _tabort (abortcode)
> +#define __builtin_get_texasru()     _texasru ()
> +
> +#else
> +# include <htmintrin.h>
> +#endif /* __HTM__  */
> +
> +#endif /* __ASSEMBLER__ */
> +
> +/* Definitions used for TEXASR Failure code (bits 0:6), they need to be even
> +   because tabort. always sets the first bit.  */
> +#define _ABORT_LOCK_BUSY       0x3f   /* Lock already used.  */
> +#define _ABORT_NESTED_TRYLOCK  0x3e   /* Write operation in trylock.  */
> +#define _ABORT_SYSCALL         0x3d   /* Syscall issued.  */
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c
> new file mode 100644
> index 0000000..aa6cf9a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c
> @@ -0,0 +1,22 @@
> +/* Copyright (C) 2014 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/>.  */
> +
> +/* The cond lock is not actually elided yet, but we still need to handle
> +   already elided locks.  */
> +#include <elision-conf.h>
> +
> +#include <nptl/pthread_mutex_cond_lock.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c
> new file mode 100644
> index 0000000..6fd6a98
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c
> @@ -0,0 +1,22 @@
> +/* Elided version of pthread_mutex_lock.
> +   Copyright (C) 2014 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-conf.h>
> +#include <force-elision.h>
> +
> +#include <nptl/pthread_mutex_lock.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c
> new file mode 100644
> index 0000000..d0e6537
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c
> @@ -0,0 +1,22 @@
> +/* Elided version of pthread_mutex_timedlock.
> +   Copyright (C) 2014 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-conf.h>
> +#include <force-elision.h>
> +
> +#include <nptl/pthread_mutex_timedlock.c>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c
> new file mode 100644
> index 0000000..ea8a8ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c
> @@ -0,0 +1,22 @@
> +/* Elided version of pthread_mutex_trylock.
> +   Copyright (C) 2014 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-conf.h>
> +#include <force-elision.h>
> +
> +#include <nptl/pthread_mutex_trylock.c>
> diff --git a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
> index d764075..f2e2fe3 100644
> --- a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
> +++ b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
> @@ -274,6 +274,13 @@ __lll_robust_timedlock (int *futex, const struct timespec *abstime,
>  #define lll_robust_timedlock(futex, abstime, id, private) \
>    __lll_robust_timedlock (&(futex), abstime, id, 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)
> +
>  #define lll_unlock(lock, private) \
>    ((void) ({								      \
>      int *__futex = &(lock);						      \
> @@ -321,4 +328,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 */
>
diff mbox

Patch

diff --git a/ChangeLog b/ChangeLog
index a8d9c49..7fec4b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@ 
+2014-11-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/Makefile [nptl]
+	(sysdep_routines): Add lock elision objects.
+	* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
+	[pthread_mutex_t] (__spins): Rework to add lock elision field.
+	[pthread_mutex_t] (__elision): Add field.
+	[__PTHREAD_SPINS]: Adjust to init lock elision field.
+	* sysdeps/unix/sysv/linux/powerpc/elision-conf.c: New file: lock
+	elision definitions for powerpc.
+	* sysdeps/unix/sysv/linux/powerpc/elision-lock.c: New file:
+	implementation of lock elision for powerpc.
+	* sysdeps/unix/sysv/linux/powerpc/elision-timed.c: New file:
+	implementation of timed lock elision for powerpc.
+	* sysdeps/unix/sysv/linux/powerpc/elision-trylock.c: New file:
+	implementation of trylock with lock elision for powerpc.
+	* sysdeps/unix/sysv/linux/powerpc/elision-unlock.c: New file:
+	implementaion of unlock for lock elision for powerpc.
+	* sysdeps/unix/sysv/linux/powerpc/force-elision.h: New file:
+	automatic enable lock elision for mutexes.
+	* sysdeps/unix/sysv/linux/powerpc/htm.h: New file: hardware
+	transaction execution definitions for powerpc.
+	* sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
+	(__lll_timedlock_elision): New prototype.
+	(__lll_lock_elision): Likewise.
+	(__lll_unlock_elision): Likewise.
+	(__lll_trylock_elision): Likewise.
+	(lll_timedlock_elision): New define.
+	(lll_lock_elision): Likewise.
+	(lll_unlock_elision): Likewise.
+	(lll_trylock_elision): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c: New file.
+	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c: Likewise.
+
 2014-11-07  Joseph Myers  <joseph@codesourcery.com>
 
 	* include/sys/wait.h (__libc_waitpid): Remove declaration.
diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
index e660736..dd5d3bc 100644
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -32,4 +32,6 @@  endif
 
 ifeq ($(subdir),nptl)
 libpthread-routines += sysdep
+libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
+			      elision-trylock
 endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
index 4e9c518..396a3d9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
@@ -90,14 +90,23 @@  typedef union
        binary compatibility.  */
     int __kind;
 #if __WORDSIZE == 64
-    int __spins;
+    short __spins;
+    short __elision;
     __pthread_list_t __list;
 # define __PTHREAD_MUTEX_HAVE_PREV	1
+# define __PTHREAD_SPINS             0, 0
 #else
     unsigned int __nusers;
     __extension__ union
     {
-      int __spins;
+      struct
+      {
+	short __espins;
+	short __elision;
+# define __spins __elision_data.__espins
+# define __elision __elision_data.__elision
+# define __PTHREAD_SPINS         { 0, 0 }
+      } __elision_data;
       __pthread_slist_t __list;
     };
 #endif
@@ -106,9 +115,6 @@  typedef union
   long int __align;
 } pthread_mutex_t;
 
-/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER.  */
-#define __PTHREAD_SPINS 0
-
 typedef union
 {
   char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
new file mode 100644
index 0000000..60a7900
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c
@@ -0,0 +1,81 @@ 
+/* elision-conf.c: Lock elision tunable parameters.
+   Copyright (C) 2014 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 to not attempt to use elision if a lock used up all retries
+       without success.  Expressed in number of lock acquisition attempts.  */
+    .skip_lock_out_of_tbegin_retries = 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.  */
+    .try_tbegin = 3,
+    /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock.  */
+    .skip_trylock_internal_abort = 3,
+  };
+
+/* 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)
+{
+  int elision_available = (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM) ? 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/sysdeps/unix/sysv/linux/powerpc/elision-conf.h b/sysdeps/unix/sysv/linux/powerpc/elision-conf.h
new file mode 100644
index 0000000..333226a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.h
@@ -0,0 +1,43 @@ 
+/* elision-conf.h: Lock elision tunable parameters.
+   Copyright (C) 2014 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 skip_lock_out_of_tbegin_retries;
+  int try_tbegin;
+  int skip_trylock_internal_abort;
+};
+
+extern struct elision_config __elision_aconf 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/sysdeps/unix/sysv/linux/powerpc/elision-lock.c b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
new file mode 100644
index 0000000..d177465
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-lock.c
@@ -0,0 +1,106 @@ 
+/* elision-lock.c: Elided pthread mutex lock.
+   Copyright (C) 2014 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 <stdio.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <lowlevellock.h>
+#include <elision-conf.h>
+#include "htm.h"
+
+/* PowerISA 2.0.7 Section B.5.5 defines isync to be isuficient to memory
+   barrier in acquire mechanism, a strong sync need to used.  */
+#undef __arch_compare_and_exchange_val_32_acq
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)           \
+  ({                                                                          \
+      __typeof (*(mem)) __tmp;                                                \
+      __typeof (mem)  __memp = (mem);                                         \
+      __asm __volatile (                                                      \
+                        "1:     lwarx   %0,0,%1" MUTEX_HINT_ACQ "\n"          \
+                        "       cmpw    %0,%2\n"                              \
+                        "       bne     2f\n"                                 \
+                        "       stwcx.  %3,0,%1\n"                            \
+                        "       bne-    1b\n"                                 \
+                        "2:     sync"                                         \
+                        : "=&r" (__tmp)                                       \
+                        : "b" (__memp), "r" (oldval), "r" (newval)            \
+                        : "cr0", "memory");                                   \
+      __tmp;                                                                  \
+  })
+
+#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 *lock, short *adapt_count, EXTRAARG int pshared)
+{
+  if (*adapt_count > 0)
+    {
+      (*adapt_count)--;
+      goto use_lock;
+    }
+
+  int try_begin = aconf.try_tbegin;
+  while (1)
+    {
+      if (__builtin_tbegin (0))
+	{
+	  if (*lock == 0)
+	    return 0;
+	  /* Lock was busy.  Fall back to normal locking.  */
+	  __builtin_tabort (_ABORT_LOCK_BUSY);
+	}
+      else
+	{
+	  /* A persistent failure indicates that a retry will probably
+	     result in another failure.  Use normal locking now and
+	     for the next couple of calls.  */
+	  if (try_begin-- <= 0
+	      || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
+	    {
+	      if (aconf.skip_lock_internal_abort > 0) 
+		*adapt_count = aconf.skip_lock_internal_abort;
+	      goto use_lock;
+	    }
+	  /* Same logic as above, but for for a number of temporary failures
+	     in a row.  */
+	  else if (aconf.skip_lock_out_of_tbegin_retries > 0
+                   && aconf.try_tbegin > 0)
+	    *adapt_count = aconf.skip_lock_out_of_tbegin_retries;
+	}
+     }
+
+use_lock:
+  return LLL_LOCK ((*lock), pshared);
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-timed.c b/sysdeps/unix/sysv/linux/powerpc/elision-timed.c
new file mode 100644
index 0000000..7d5de9b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-timed.c
@@ -0,0 +1,28 @@ 
+/* elision-timed.c: Lock elision timed lock.
+   Copyright (C) 2014 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/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
new file mode 100644
index 0000000..60aaf90
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
@@ -0,0 +1,68 @@ 
+/* elision-trylock.c: Lock eliding trylock for pthreads.
+   Copyright (C) 2014 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 <elision-conf.h>
+#include "htm.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 elided trylocks.  */
+  __builtin_tabort (_ABORT_NESTED_TRYLOCK);
+
+  /* Only try a transaction if it's worth it.  */
+  if (*adapt_count > 0)
+    {
+      (*adapt_count)--;
+      goto use_lock;
+    }
+
+  if (__builtin_tbegin (0))
+    {
+      if (*futex == 0)
+	return 0;
+
+      /* Lock was busy.  Fall back to normal locking.  */
+      __builtin_tabort (_ABORT_LOCK_BUSY);
+    }
+  else
+    {
+      if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
+	{
+	  /* A persistent failure indicates that a retry will probably
+	     resulting in another failure.  Use normal locking now and
+	     for the next couple of calls.  */
+	  if (aconf.skip_trylock_internal_abort > 0)
+	    *adapt_count = aconf.skip_trylock_internal_abort;
+	}
+
+	if (aconf.skip_lock_busy > 0)
+	  *adapt_count = aconf.skip_lock_busy;
+    }
+
+use_lock:
+  return lll_trylock (*futex);
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
new file mode 100644
index 0000000..59d46bb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
@@ -0,0 +1,32 @@ 
+/* elision-unlock.c: Commit an elided pthread lock.
+   Copyright (C) 2014 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 pshared)
+{
+  /* When the lock was free we're in a transaction.  */
+  if (*lock == 0)
+    __builtin_tend (0);
+  else
+    lll_unlock ((*lock), pshared);
+  return 0;
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
new file mode 100644
index 0000000..38c79bf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h
@@ -0,0 +1,33 @@ 
+/* force-elision.h: Automatic enabling of elision for mutexes
+   Copyright (C) 2014 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/>.  */
+
+#ifdef ENABLE_LOCK_ELISION
+/* Check for elision on this lock without upgrading.  */
+#define DO_ELISION(m)							\
+  (__pthread_force_elision						\
+   && (m->__data.__kind & PTHREAD_MUTEX_NO_ELISION_NP) == 0)		\
+
+/* Automatically enable elision for existing user lock kinds.  */
+#define FORCE_ELISION(m, s)						\
+  if (__pthread_force_elision						\
+      && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0)	\
+    {									\
+      mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP;			\
+      s;								\
+    }
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/htm.h b/sysdeps/unix/sysv/linux/powerpc/htm.h
new file mode 100644
index 0000000..a031d01
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/htm.h
@@ -0,0 +1,136 @@ 
+/* Shared HTM header.  Emulate transactional execution facility intrinsics for
+   compilers and assemblers that do not support the intrinsics and instructions
+   yet. 
+
+   Copyright (C) 2014 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 _HTM_H
+#define _HTM_H 1
+
+#ifdef __ASSEMBLER__
+
+/* tbegin.  */
+.macro TBEGIN
+	.byte 0x7c,0x00,0x05,0x1d
+.endm
+
+/* tend. 0  */
+.macro TEND
+	.byte 0x7c,0x00,0x05,0x5d
+.endm
+
+/* tabort. code  */
+.macro TABORT code
+        .byte 0x7c
+        .byte \code
+	.byte 0x07
+	.byte 0x1d
+.endm
+
+/* mfspr %dst,130  */
+.macro TEXASR dst
+	mfspr \dst,130
+.endm
+
+#else
+
+/* Official HTM intrinsics interface matching gcc, 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 ".byte 0x7c,0x00,0x05,0x1d"
+#define TEND   ".byte 0x7c,0x00,0x05,0x5d"
+#define TABORT ".byte 0x7c,%1,0x07,0x1d"
+
+#define __force_inline        inline __attribute__((__always_inline__))
+
+#ifndef __HTM__
+
+#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+  (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1))
+#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1)
+
+static __force_inline
+unsigned int _tbegin (void)
+{
+  unsigned int ret;
+  asm volatile (
+    TBEGIN "\t\n"
+    "mfcr   %0,128\t\n"
+    "rlwinm %0,%0,3,1\t\n"
+    "subfic %0,%0,1\t\n"
+    : "=r" (ret) :: "cr0", "memory");
+  return ret;
+}
+
+static __force_inline
+unsigned int _tend (void)
+{
+  unsigned int ret;
+  asm volatile (
+    TEND "\t\n"
+    "mfcr   %0,128\t\n"
+    "rlwinm %0,%0,3,1\t\n"
+    "subfic %0,%0,1\t\n"
+    : "=r" (ret) :: "cr0", "memory");
+  return ret;
+}
+
+static __force_inline
+unsigned int _tabort (unsigned int code)
+{
+  unsigned int ret;
+  asm volatile (
+    TABORT "\t\n"
+    "mfcr     %0,128\t\n"
+    "rlwinm   %0,%0,3,1\t\n"
+    "subfic   %0,%0,1\t\n"
+    : "=r" (ret) : "r" (code) : "cr0", "memory");
+  return ret;
+}
+
+static __force_inline
+unsigned long _texasru (void)
+{
+  unsigned long ret;
+  asm volatile (
+    "mfspr %0,131\t\n"
+    : "=r" (ret));
+  return ret;
+}
+
+#define __builtin_tbegin(tdb)       _tbegin ()
+#define __builtin_tend(nested)      _tend ()
+#define __builtin_tabort(abortcode) _tabort (abortcode)
+#define __builtin_get_texasru()     _texasru ()
+
+#else
+# include <htmintrin.h>
+#endif /* __HTM__  */
+
+#endif /* __ASSEMBLER__ */
+
+/* Definitions used for TEXASR Failure code (bits 0:6), they need to be even
+   because tabort. always sets the first bit.  */
+#define _ABORT_LOCK_BUSY       0x3f   /* Lock already used.  */
+#define _ABORT_NESTED_TRYLOCK  0x3e   /* Write operation in trylock.  */
+#define _ABORT_SYSCALL         0x3d   /* Syscall issued.  */
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c
new file mode 100644
index 0000000..aa6cf9a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_cond_lock.c
@@ -0,0 +1,22 @@ 
+/* Copyright (C) 2014 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/>.  */
+
+/* The cond lock is not actually elided yet, but we still need to handle
+   already elided locks.  */
+#include <elision-conf.h>
+
+#include <nptl/pthread_mutex_cond_lock.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c
new file mode 100644
index 0000000..6fd6a98
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_lock.c
@@ -0,0 +1,22 @@ 
+/* Elided version of pthread_mutex_lock.
+   Copyright (C) 2014 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-conf.h>
+#include <force-elision.h>
+
+#include <nptl/pthread_mutex_lock.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c
new file mode 100644
index 0000000..d0e6537
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_timedlock.c
@@ -0,0 +1,22 @@ 
+/* Elided version of pthread_mutex_timedlock.
+   Copyright (C) 2014 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-conf.h>
+#include <force-elision.h>
+
+#include <nptl/pthread_mutex_timedlock.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c
new file mode 100644
index 0000000..ea8a8ff
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/pthread_mutex_trylock.c
@@ -0,0 +1,22 @@ 
+/* Elided version of pthread_mutex_trylock.
+   Copyright (C) 2014 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-conf.h>
+#include <force-elision.h>
+
+#include <nptl/pthread_mutex_trylock.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
index d764075..f2e2fe3 100644
--- a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -274,6 +274,13 @@  __lll_robust_timedlock (int *futex, const struct timespec *abstime,
 #define lll_robust_timedlock(futex, abstime, id, private) \
   __lll_robust_timedlock (&(futex), abstime, id, 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)
+
 #define lll_unlock(lock, private) \
   ((void) ({								      \
     int *__futex = &(lock);						      \
@@ -321,4 +328,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 */