From 1315faa9a01c8d768fd750ed643bae4f3eefc48a Mon Sep 17 00:00:00 2001
From: Yura Sokolov <y.sokolov@postgrespro.ru>
Date: Tue, 13 May 2025 18:57:46 +0300
Subject: [PATCH v1] Make SpinLockAcquire and SpinLockRelease full memory
 barriers.

Andres Freund stated SpinLockAcquire is used as a full memory barrier at
least once [1].

Code comment in spin.h also states:

> Load and stores operation in calling code are guaranteed not to be
> reordered with respect to these operations, because they include a
> compiler barrier.

But ARM/ARM64 code used __spin_lock_test_and_set and __spin_lock_release
which only have acquire and release semantics respectively.

Fix it by adding __sync_synchronize before __sync_lock_test_and_set and
after __sync_lock_release.
---
 src/include/storage/s_lock.h | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 2f73f9fcf57..7ee94302df1 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -258,10 +258,14 @@ typedef int slock_t;
 static __inline__ int
 tas(volatile slock_t *lock)
 {
+	__sync_synchronize();
 	return __sync_lock_test_and_set(lock, 1);
 }
 
-#define S_UNLOCK(lock) __sync_lock_release(lock)
+#define S_UNLOCK(lock) do { \
+	__sync_lock_release(lock); \
+	__sync_synchronize(); \
+} while(0)
 
 #if defined(__aarch64__)
 
@@ -543,10 +547,14 @@ typedef int slock_t;
 static __inline__ int
 tas(volatile slock_t *lock)
 {
+	__sync_synchronize();
 	return __sync_lock_test_and_set(lock, 1);
 }
 
-#define S_UNLOCK(lock) __sync_lock_release(lock)
+#define S_UNLOCK(lock) do { \
+	__sync_lock_release(lock); \
+	__sync_synchronize(); \
+} while(0)
 
 #elif defined(HAVE_GCC__SYNC_CHAR_TAS)
 #define HAS_TEST_AND_SET
@@ -558,10 +566,14 @@ typedef char slock_t;
 static __inline__ int
 tas(volatile slock_t *lock)
 {
+	__sync_synchronize();
 	return __sync_lock_test_and_set(lock, 1);
 }
 
-#define S_UNLOCK(lock) __sync_lock_release(lock)
+#define S_UNLOCK(lock) do { \
+	__sync_lock_release(lock); \
+	__sync_synchronize(); \
+} while(0)
 
 #endif	 /* HAVE_GCC__SYNC_INT32_TAS */
 
-- 
2.43.0

