From 5cfa8dd3007d7e953c6a03b0fa2215d97c581b0c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 1 Jan 2012 22:39:59 -0500 Subject: [PATCH] Use mutex hint bit in PPC LWARX instructions, where possible. The hint bit makes for a small but measurable performance improvement in access to contended spinlocks. On the other hand, some PPC chips give an illegal-instruction failure. There doesn't seem to be a completely bulletproof way to tell whether the hint bit will cause an illegal-instruction failure other than by trying it; but most if not all 64-bit PPC machines should accept it, so follow the Linux kernel's lead and assume it's okay to use it in 64-bit builds. Of course we must also check whether the assembler accepts the command, since even with a recent CPU the toolchain could be old. Patch by Manabu Ori, significantly modified by me. --- configure | 62 +++++++++++++++++++++++++++++++++- configure.in | 18 +++++++++- src/include/pg_config.h.in | 5 ++- src/include/pg_config_manual.h | 18 ++++++++++ src/include/storage/s_lock.h | 4 +++ 5 files changed, 104 insertions(+), 3 deletions(-) diff --git a/configure b/configure index baa1b970f8..5cb3d9b14f 100755 --- a/configure +++ b/configure @@ -1635,7 +1635,7 @@ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. -Copyright (c) 1996-2011, PostgreSQL Global Development Group +Copyright (c) 1996-2012, PostgreSQL Global Development Group _ACEOF exit fi @@ -18207,6 +18207,66 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi +# On PPC, check if assembler supports LWARX instruction's mutex hint bit +case $host_cpu in + ppc*|powerpc*) + { $as_echo "$as_me:$LINENO: checking whether assembler supports lwarx hint bit" >&5 +$as_echo_n "checking whether assembler supports lwarx hint bit... " >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +int a = 0; int *p = &a; int r; + __asm__ __volatile__ (" lwarx %0,0,%1,1\n" : "=&r"(r) : "r"(p)); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + pgac_cv_have_ppc_mutex_hint=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + pgac_cv_have_ppc_mutex_hint=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:$LINENO: result: $pgac_cv_have_ppc_mutex_hint" >&5 +$as_echo "$pgac_cv_have_ppc_mutex_hint" >&6; } + if test x"$pgac_cv_have_ppc_mutex_hint" = xyes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PPC_LWARX_MUTEX_HINT 1 +_ACEOF + + fi + ;; +esac + # Check largefile support. You might think this is a system service not a # compiler characteristic, but you'd be wrong. We must check this before # probing existence of related functions such as fseeko, since the largefile diff --git a/configure.in b/configure.in index 48db5c39b5..3f195a6511 100644 --- a/configure.in +++ b/configure.in @@ -1170,11 +1170,27 @@ if test "$with_krb5" = yes; then AC_MSG_CHECKING(for krb5_free_unparsed_name) AC_TRY_LINK([#include ], [krb5_free_unparsed_name(NULL,NULL);], - [AC_DEFINE(HAVE_KRB5_FREE_UNPARSED_NAME, 1, [Define to 1 if you have krb5_free_unparsed_name]) + [AC_DEFINE(HAVE_KRB5_FREE_UNPARSED_NAME, 1, [Define to 1 if you have krb5_free_unparsed_name.]) AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)]) fi +# On PPC, check if assembler supports LWARX instruction's mutex hint bit +case $host_cpu in + ppc*|powerpc*) + AC_MSG_CHECKING([whether assembler supports lwarx hint bit]) + AC_TRY_COMPILE([], + [int a = 0; int *p = &a; int r; + __asm__ __volatile__ (" lwarx %0,0,%1,1\n" : "=&r"(r) : "r"(p));], + [pgac_cv_have_ppc_mutex_hint=yes], + [pgac_cv_have_ppc_mutex_hint=no]) + AC_MSG_RESULT([$pgac_cv_have_ppc_mutex_hint]) + if test x"$pgac_cv_have_ppc_mutex_hint" = xyes ; then + AC_DEFINE(HAVE_PPC_LWARX_MUTEX_HINT, 1, [Define to 1 if the assembler supports PPC's LWARX mutex hint bit.]) + fi + ;; +esac + # Check largefile support. You might think this is a system service not a # compiler characteristic, but you'd be wrong. We must check this before # probing existence of related functions such as fseeko, since the largefile diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index ef467b7386..e1b7fea49f 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -275,7 +275,7 @@ /* Define to 1 if `text.data' is member of `krb5_error'. */ #undef HAVE_KRB5_ERROR_TEXT_DATA -/* Define to 1 if you have krb5_free_unparsed_name */ +/* Define to 1 if you have krb5_free_unparsed_name. */ #undef HAVE_KRB5_FREE_UNPARSED_NAME /* Define to 1 if `client' is member of `krb5_ticket'. */ @@ -384,6 +384,9 @@ /* Define to 1 if you have the POSIX signal interface. */ #undef HAVE_POSIX_SIGNALS +/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ +#undef HAVE_PPC_LWARX_MUTEX_HINT + /* Define to 1 if you have the `pstat' function. */ #undef HAVE_PSTAT diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h index ac434fabbc..810be27e81 100644 --- a/src/include/pg_config_manual.h +++ b/src/include/pg_config_manual.h @@ -6,6 +6,9 @@ * for developers. If you edit any of these, be sure to do a *full* * rebuild (and an initdb if noted). * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * * src/include/pg_config_manual.h *------------------------------------------------------------------------ */ @@ -170,6 +173,21 @@ #define PG_PRINTF_ATTRIBUTE printf #endif +/* + * On PPC machines, decide whether to use the mutex hint bit in LWARX + * instructions. Setting the hint bit will slightly improve spinlock + * performance on POWER6 and later machines, but does nothing before that, + * and will result in illegal-instruction failures on some pre-POWER4 + * machines. By default we use the hint bit when building for 64-bit PPC, + * which should be safe in nearly all cases. You might want to override + * this if you are building 32-bit code for a known-recent PPC machine. + */ +#ifdef HAVE_PPC_LWARX_MUTEX_HINT /* must have assembler support in any case */ +#if defined(__ppc64__) || defined(__powerpc64__) +#define USE_PPC_LWARX_MUTEX_HINT +#endif +#endif + /* *------------------------------------------------------------------------ * The following symbols are for enabling debugging code, not for diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 98c12db3ab..cc67be81eb 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -372,7 +372,11 @@ tas(volatile slock_t *lock) int _res; __asm__ __volatile__( +#ifdef USE_PPC_LWARX_MUTEX_HINT +" lwarx %0,0,%3,1 \n" +#else " lwarx %0,0,%3 \n" +#endif " cmpwi %0,0 \n" " bne 1f \n" " addi %0,%0,1 \n"