diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/pg_config.h.in | 3 | ||||
-rw-r--r-- | src/include/storage/s_lock.h | 25 |
2 files changed, 26 insertions, 2 deletions
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index e3a6c9982ad..f537360ee5d 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -148,6 +148,9 @@ /* Define to 1 if your compiler understands __FUNCTION__. */ #undef HAVE_FUNCNAME__FUNCTION +/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ +#undef HAVE_GCC_INT_ATOMICS + /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 7d9448fb7e4..a3c15d4ffc8 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -252,13 +252,33 @@ tas(volatile slock_t *lock) #endif /* __ia64__ || __ia64 */ +/* + * On ARM, we use __sync_lock_test_and_set(int *, int) if available, and if + * not fall back on the SWPB instruction. SWPB does not work on ARMv6 or + * later, so the compiler builtin is preferred if available. Note also that + * the int-width variant of the builtin works on more chips than other widths. + */ #if defined(__arm__) || defined(__arm) #define HAS_TEST_AND_SET -typedef unsigned char slock_t; - #define TAS(lock) tas(lock) +#ifdef HAVE_GCC_INT_ATOMICS + +typedef int slock_t; + +static __inline__ int +tas(volatile slock_t *lock) +{ + return __sync_lock_test_and_set(lock, 1); +} + +#define S_UNLOCK(lock) __sync_lock_release(lock) + +#else /* !HAVE_GCC_INT_ATOMICS */ + +typedef unsigned char slock_t; + static __inline__ int tas(volatile slock_t *lock) { @@ -272,6 +292,7 @@ tas(volatile slock_t *lock) return (int) _res; } +#endif /* HAVE_GCC_INT_ATOMICS */ #endif /* __arm__ */ |