-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
powerpc: Add the lock elision using HTM
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.
- Loading branch information
Adhemerval Zanella
committed
Jan 12, 2015
1 parent
ec4fbd4
commit 8d2c0a5
Showing
17 changed files
with
709 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* 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 many times to use a non-transactional lock after a transactional | ||
failure has occurred 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 use elision in pthread_mutex_lock(). | ||
Disabled for suid programs. Only used when elision is available. */ | ||
|
||
int __pthread_force_elision attribute_hidden; | ||
|
||
/* Initialize elision. */ | ||
|
||
static void | ||
elision_init (int argc __attribute__ ((unused)), | ||
char **argv __attribute__ ((unused)), | ||
char **environ) | ||
{ | ||
#ifdef ENABLE_LOCK_ELISION | ||
int elision_available = (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM) ? 1 : 0; | ||
__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 | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* 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; | ||
} __attribute__ ((__aligned__ (128))); | ||
|
||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* 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 insufficient as a | ||
barrier in acquire mechanism for HTM operations, a strong 'sync' is | ||
required. */ | ||
#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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" |
Oops, something went wrong.