Andres Freund <and...@anarazel.de> writes: > On 2022-11-02 11:37:35 -0400, Tom Lane wrote: >> I wonder if we shouldn't just do that (ie, try to use >> __sync_lock_test_and_set) as a generic fallback on any unsupported >> architecture. We could get rid of the separate stanza for RISC-V >> that way. The main thing that an arch-specific stanza could bring >> is knowledge of the best data type width to use for a spinlock; >> but I don't see a big problem with defaulting to "int". We can >> always add arch-specific stanzas for any machines where that's >> shown to be a seriously poor choice.
> Yes, please. It might not be perfect for all architectures, and it might not > be good for some very old architectures. But for anything new it'll be vastly > better than not having spinlocks at all. So about like this, then. regards, tom lane
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 4225d9b7fc..d3972f61fc 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -293,29 +293,6 @@ spin_delay(void) #endif /* __arm__ || __arm || __aarch64__ */ -/* - * RISC-V likewise uses __sync_lock_test_and_set(int *, int) if available. - */ -#if defined(__riscv) -#ifdef HAVE_GCC__SYNC_INT32_TAS -#define HAS_TEST_AND_SET - -#define TAS(lock) tas(lock) - -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) - -#endif /* HAVE_GCC__SYNC_INT32_TAS */ -#endif /* __riscv */ - - /* S/390 and S/390x Linux (32- and 64-bit zSeries) */ #if defined(__s390__) || defined(__s390x__) #define HAS_TEST_AND_SET @@ -716,6 +693,52 @@ spin_delay(void) #endif /* !defined(HAS_TEST_AND_SET) */ +/* + * Last-ditch try. + * + * If we have no platform-specific knowledge, but we found that the compiler + * provides __sync_lock_test_and_set(), use that. Prefer the int-width + * version over the char-width version if we have both, on the rather dubious + * grounds that that's known to be more likely to work in the ARM ecosystem. + * (But we dealt with ARM above.) + */ +#if !defined(HAS_TEST_AND_SET) + +#if defined(HAVE_GCC__SYNC_INT32_TAS) +#define HAS_TEST_AND_SET + +#define TAS(lock) tas(lock) + +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) + +#elif defined(HAVE_GCC__SYNC_CHAR_TAS) +#define HAS_TEST_AND_SET + +#define TAS(lock) tas(lock) + +typedef char 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) + +#endif /* HAVE_GCC__SYNC_INT32_TAS */ + +#endif /* !defined(HAS_TEST_AND_SET) */ + + /* Blow up if we didn't have any way to do spinlocks */ #ifndef HAS_TEST_AND_SET #error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to pgsql-b...@lists.postgresql.org.