Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 068e08e

Browse files
committed
Use __sync_lock_test_and_set() for spinlocks on ARM, if available.
Historically we've used the SWPB instruction for TAS() on ARM, but this is deprecated and not available on ARMv6 and later. Instead, make use of a GCC builtin if available. We'll still fall back to SWPB if not, so as not to break existing ports using older GCC versions. Eventually we might want to try using __sync_lock_test_and_set() on some other architectures too, but for now that seems to present only risk and not reward. Back-patch to all supported versions, since people might want to use any of them on more recent ARM chips. Martin Pitt
1 parent f517ece commit 068e08e

File tree

4 files changed

+102
-2
lines changed

4 files changed

+102
-2
lines changed

configure

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22472,6 +22472,71 @@ fi
2247222472
done
2247322473

2247422474

22475+
{ $as_echo "$as_me:$LINENO: checking for builtin locking functions" >&5
22476+
$as_echo_n "checking for builtin locking functions... " >&6; }
22477+
if test "${pgac_cv_gcc_int_atomics+set}" = set; then
22478+
$as_echo_n "(cached) " >&6
22479+
else
22480+
cat >conftest.$ac_ext <<_ACEOF
22481+
/* confdefs.h. */
22482+
_ACEOF
22483+
cat confdefs.h >>conftest.$ac_ext
22484+
cat >>conftest.$ac_ext <<_ACEOF
22485+
/* end confdefs.h. */
22486+
22487+
int
22488+
main ()
22489+
{
22490+
int lock = 0;
22491+
__sync_lock_test_and_set(&lock, 1);
22492+
__sync_lock_release(&lock);
22493+
;
22494+
return 0;
22495+
}
22496+
_ACEOF
22497+
rm -f conftest.$ac_objext conftest$ac_exeext
22498+
if { (ac_try="$ac_link"
22499+
case "(($ac_try" in
22500+
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
22501+
*) ac_try_echo=$ac_try;;
22502+
esac
22503+
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
22504+
$as_echo "$ac_try_echo") >&5
22505+
(eval "$ac_link") 2>conftest.er1
22506+
ac_status=$?
22507+
grep -v '^ *+' conftest.er1 >conftest.err
22508+
rm -f conftest.er1
22509+
cat conftest.err >&5
22510+
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
22511+
(exit $ac_status); } && {
22512+
test -z "$ac_c_werror_flag" ||
22513+
test ! -s conftest.err
22514+
} && test -s conftest$ac_exeext && {
22515+
test "$cross_compiling" = yes ||
22516+
$as_test_x conftest$ac_exeext
22517+
}; then
22518+
pgac_cv_gcc_int_atomics="yes"
22519+
else
22520+
$as_echo "$as_me: failed program was:" >&5
22521+
sed 's/^/| /' conftest.$ac_ext >&5
22522+
22523+
pgac_cv_gcc_int_atomics="no"
22524+
fi
22525+
22526+
rm -rf conftest.dSYM
22527+
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
22528+
conftest$ac_exeext conftest.$ac_ext
22529+
fi
22530+
{ $as_echo "$as_me:$LINENO: result: $pgac_cv_gcc_int_atomics" >&5
22531+
$as_echo "$pgac_cv_gcc_int_atomics" >&6; }
22532+
if test x"$pgac_cv_gcc_int_atomics" = x"yes"; then
22533+
22534+
cat >>confdefs.h <<\_ACEOF
22535+
#define HAVE_GCC_INT_ATOMICS 1
22536+
_ACEOF
22537+
22538+
fi
22539+
2247522540

2247622541
#
2247722542
# Pthreads

configure.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,17 @@ AC_CHECK_FUNCS(atexit, [],
14421442
[AC_CHECK_FUNCS(on_exit, [],
14431443
[AC_MSG_ERROR([neither atexit() nor on_exit() found])])])
14441444

1445+
AC_CACHE_CHECK([for builtin locking functions], pgac_cv_gcc_int_atomics,
1446+
[AC_TRY_LINK([],
1447+
[int lock = 0;
1448+
__sync_lock_test_and_set(&lock, 1);
1449+
__sync_lock_release(&lock);],
1450+
[pgac_cv_gcc_int_atomics="yes"],
1451+
[pgac_cv_gcc_int_atomics="no"])])
1452+
if test x"$pgac_cv_gcc_int_atomics" = x"yes"; then
1453+
AC_DEFINE(HAVE_GCC_INT_ATOMICS, 1, [Define to 1 if you have __sync_lock_test_and_set(int *) and friends.])
1454+
fi
1455+
14451456

14461457
#
14471458
# Pthreads

src/include/pg_config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@
173173
/* Define to 1 if your compiler understands __FUNCTION__. */
174174
#undef HAVE_FUNCNAME__FUNCTION
175175

176+
/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
177+
#undef HAVE_GCC_INT_ATOMICS
178+
176179
/* Define to 1 if you have the `getaddrinfo' function. */
177180
#undef HAVE_GETADDRINFO
178181

src/include/storage/s_lock.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,33 @@ tas(volatile slock_t *lock)
252252
#endif /* __ia64__ || __ia64 */
253253

254254

255+
/*
256+
* On ARM, we use __sync_lock_test_and_set(int *, int) if available, and if
257+
* not fall back on the SWPB instruction. SWPB does not work on ARMv6 or
258+
* later, so the compiler builtin is preferred if available. Note also that
259+
* the int-width variant of the builtin works on more chips than other widths.
260+
*/
255261
#if defined(__arm__) || defined(__arm)
256262
#define HAS_TEST_AND_SET
257263

258-
typedef unsigned char slock_t;
259-
260264
#define TAS(lock) tas(lock)
261265

266+
#ifdef HAVE_GCC_INT_ATOMICS
267+
268+
typedef int slock_t;
269+
270+
static __inline__ int
271+
tas(volatile slock_t *lock)
272+
{
273+
return __sync_lock_test_and_set(lock, 1);
274+
}
275+
276+
#define S_UNLOCK(lock) __sync_lock_release(lock)
277+
278+
#else /* !HAVE_GCC_INT_ATOMICS */
279+
280+
typedef unsigned char slock_t;
281+
262282
static __inline__ int
263283
tas(volatile slock_t *lock)
264284
{
@@ -272,6 +292,7 @@ tas(volatile slock_t *lock)
272292
return (int) _res;
273293
}
274294

295+
#endif /* HAVE_GCC_INT_ATOMICS */
275296
#endif /* __arm__ */
276297

277298

0 commit comments

Comments
 (0)