v1-0001-Make-SpinLockAcquire-and-SpinLockRelease-full-mem.patch
text/x-patch
Filename: v1-0001-Make-SpinLockAcquire-and-SpinLockRelease-full-mem.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0001
Subject: Make SpinLockAcquire and SpinLockRelease full memory barriers.
| File | + | − |
|---|---|---|
| src/include/storage/s_lock.h | 15 | 3 |
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