Skip to content

Latest commit

 

History

History
165 lines (132 loc) · 6.61 KB

20240302_01.md

File metadata and controls

165 lines (132 loc) · 6.61 KB

PostgreSQL 17 preview - 引入读写原子操作函数接口with full barrier semantics

作者

digoal

日期

2024-03-02

标签

PostgreSQL , PolarDB , DuckDB , atomic , 原子操作 , 内存屏障


背景

https://blog.csdn.net/gp_community/article/details/124636303

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=bd5132db558b6c8d11eb838be81e2177a95c7388

Introduce atomic read/write functions with full barrier semantics.  
  
author  Nathan Bossart <nathan@postgresql.org>    
Thu, 29 Feb 2024 16:00:44 +0000 (10:00 -0600)  
committer Nathan Bossart <nathan@postgresql.org>    
Thu, 29 Feb 2024 16:00:44 +0000 (10:00 -0600)  
commit  bd5132db558b6c8d11eb838be81e2177a95c7388  
tree  c27f73a66003401092c363a65dae5f88e568af2d  tree  
parent  5f2e179bd31e5f5803005101eb12a8d7bf8db8f3  commit | diff  
  
Introduce atomic read/write functions with full barrier semantics.  
  
Writing correct code using atomic variables is often difficult due  
to the memory barrier semantics (or lack thereof) of the underlying  
operations.  This commit introduces atomic read/write functions  
with full barrier semantics to ease this cognitive load.  For  
example, some spinlocks protect a single value, and these new  
functions make it easy to convert the value to an atomic variable  
(thus eliminating the need for the spinlock) without modifying the  
barrier semantics previously provided by the spinlock.  Since these  
functions may be less performant than the other atomic reads and  
writes, they are not suitable for every use-case.  However, using a  
single atomic operation with full barrier semantics may be more  
performant in cases where a separate explicit barrier would  
otherwise be required.  
  
The base implementations for these new functions are atomic  
exchanges (for writes) and atomic fetch/adds with 0 (for reads).  
These implementations can be overwritten with better architecture-  
specific versions as they are discovered.  
  
This commit leaves converting existing code to use these new  
functions as a future exercise.  
  
Reviewed-by: Andres Freund, Yong Li, Jeff Davis  
Discussion: https://postgr.es/m/20231110205128.GB1315705%40nathanxps13  

src/include/port/atomics.h

+/*  
+ * pg_atomic_read_membarrier_u32 - read with barrier semantics.  
+ *  
+ * This read is guaranteed to return the current value, provided that the value  
+ * is only ever updated via operations with barrier semantics, such as  
+ * pg_atomic_compare_exchange_u32() and pg_atomic_write_membarrier_u32().  
+ * While this may be less performant than pg_atomic_read_u32(), it may be  
+ * easier to reason about correctness with this function in less performance-  
+ * sensitive code.  
+ *  
+ * Full barrier semantics.  
+ */  
+static inline uint32  
+pg_atomic_read_membarrier_u32(volatile pg_atomic_uint32 *ptr)  
+{  
+   AssertPointerAlignment(ptr, 4);  
+  
+   return pg_atomic_read_membarrier_u32_impl(ptr);  
+}  
+  
 /*  
  * pg_atomic_write_u32 - write to atomic variable.  
  *  
@@ -274,6 +294,26 @@ pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)  
    pg_atomic_unlocked_write_u32_impl(ptr, val);  
 }  
   
+/*  
+ * pg_atomic_write_membarrier_u32 - write with barrier semantics.  
+ *  
+ * The write is guaranteed to succeed as a whole, i.e., it's not possible to  
+ * observe a partial write for any reader.  Note that this correctly interacts  
+ * with both pg_atomic_compare_exchange_u32() and  
+ * pg_atomic_read_membarrier_u32().  While this may be less performant than  
+ * pg_atomic_write_u32(), it may be easier to reason about correctness with  
+ * this function in less performance-sensitive code.  
+ *  
+ * Full barrier semantics.  
+ */  
+static inline void  
+pg_atomic_write_membarrier_u32(volatile pg_atomic_uint32 *ptr, uint32 val)  
+{  
+   AssertPointerAlignment(ptr, 4);  
+  
+   pg_atomic_write_membarrier_u32_impl(ptr, val);  
+}  
+  
 /*  
  * pg_atomic_exchange_u32 - exchange newval with current value  
  *  
@@ -427,6 +467,15 @@ pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)  
    return pg_atomic_read_u64_impl(ptr);  
 }  
   
+static inline uint64  
+pg_atomic_read_membarrier_u64(volatile pg_atomic_uint64 *ptr)  
+{  
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION  
+   AssertPointerAlignment(ptr, 8);  
+#endif  
+   return pg_atomic_read_membarrier_u64_impl(ptr);  
+}  
+  
 static inline void  
 pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)  
 {  
@@ -436,6 +485,15 @@ pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)  
    pg_atomic_write_u64_impl(ptr, val);  
 }  
   
+static inline void  
+pg_atomic_write_membarrier_u64(volatile pg_atomic_uint64 *ptr, uint64 val)  
+{  
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION  
+   AssertPointerAlignment(ptr, 8);  
+#endif  
+   pg_atomic_write_membarrier_u64_impl(ptr, val);  
+}  
+  
 static inline uint64  
 pg_atomic_exchange_u64(volatile pg_atomic_uin  

digoal's wechat