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 5d38f25d263..ecb0e41aadd 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -173,6 +173,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 7fe01aac616..987fb9c58d2 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__ */ |