]> granicus.if.org Git - postgresql/commitdiff
Further atomic ops portability improvements and bug fixes.
authorAndres Freund <andres@anarazel.de>
Fri, 26 Sep 2014 13:55:44 +0000 (15:55 +0200)
committerAndres Freund <andres@anarazel.de>
Fri, 26 Sep 2014 13:55:44 +0000 (15:55 +0200)
* Don't play tricks for a more efficient pg_atomic_clear_flag() in the
  generic gcc implementation. The old version was broken on gcc < 4.7
  on !x86 platforms. Per buildfarm member chipmunk.
* Make usage of __atomic() fences depend on HAVE_GCC__ATOMIC_INT32_CAS
  instead of HAVE_GCC__ATOMIC_INT64_CAS - there's platforms with 32bit
  support that don't support 64bit atomics.
* Blindly fix two superflous #endif in generic-xlc.h
* Check for --disable-atomics in platforms but x86.

src/include/port/atomics/arch-x86.h
src/include/port/atomics/generic-acc.h
src/include/port/atomics/generic-gcc.h
src/include/port/atomics/generic-msvc.h
src/include/port/atomics/generic-sunpro.h
src/include/port/atomics/generic-xlc.h

index 11a891c865d6426d4a71a7b7113e88d5e29d848b..691b1e7d67665eb623ca1faa8724b91ed22e44cf 100644 (file)
@@ -78,6 +78,7 @@ typedef struct pg_atomic_uint64
 #endif
 
 #endif /* defined(HAVE_ATOMICS) */
+
 #endif /* defined(__GNUC__) && !defined(__INTEL_COMPILER) */
 
 #if defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS)
@@ -160,6 +161,18 @@ pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
        return _res == 0;
 }
 
+#define PG_HAVE_ATOMIC_CLEAR_FLAG
+static inline void
+pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
+{
+       /*
+        * On a TSO architecture like x86 it's sufficient to use a compiler
+        * barrier to achieve release semantics.
+        */
+       __asm__ __volatile__("" ::: "memory");
+       ptr->value = 0;
+}
+
 #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
 static inline bool
 pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
index 627e2dfcb5e134c7d62431e1bd2b44a27bc27a34..8983b1cda4b1828a3a263dbb83131e0c494f19bc 100644 (file)
 
 #include <machine/sys/inline.h>
 
+#define pg_compiler_barrier_impl()     _Asm_sched_fence()
+
+#if defined(HAVE_ATOMICS)
+
 /* IA64 always has 32/64 bit atomics */
 
 #define PG_HAVE_ATOMIC_U32_SUPPORT
@@ -39,10 +43,13 @@ typedef struct pg_atomic_uint64
        volatile uint64 value;
 } pg_atomic_uint64;
 
-#define pg_compiler_barrier_impl()     _Asm_sched_fence()
+#endif /* defined(HAVE_ATOMICS) */
+
 
 #if defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS)
 
+#if defined(HAVE_ATOMICS)
+
 #define MINOR_FENCE (_Asm_fence) (_UP_CALL_FENCE | _UP_SYS_FENCE | \
                                                                 _DOWN_CALL_FENCE | _DOWN_SYS_FENCE )
 
@@ -96,4 +103,6 @@ pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
 
 #undef MINOR_FENCE
 
+#endif /* defined(HAVE_ATOMICS) */
+
 #endif /* defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS) */
index 6a2373079b08db1bc8d413c29e77a9245867d9db..ecabef3144b20a83b4d4ee4d7506f09a3615e30e 100644 (file)
  * definitions where possible, and use this only as a fallback.
  */
 #if !defined(pg_memory_barrier_impl)
-#      if defined(HAVE_GCC__ATOMIC_INT64_CAS)
+#      if defined(HAVE_GCC__ATOMIC_INT32_CAS)
 #              define pg_memory_barrier_impl()         __atomic_thread_fence(__ATOMIC_SEQ_CST)
 #      elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
 #              define pg_memory_barrier_impl()         __sync_synchronize()
 #      endif
 #endif /* !defined(pg_memory_barrier_impl) */
 
-#if !defined(pg_read_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT64_CAS)
+#if !defined(pg_read_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
 /* acquire semantics include read barrier semantics */
 #              define pg_read_barrier_impl()           __atomic_thread_fence(__ATOMIC_ACQUIRE)
 #endif
 
-#if !defined(pg_write_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT64_CAS)
+#if !defined(pg_write_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
 /* release semantics include write barrier semantics */
 #              define pg_write_barrier_impl()          __atomic_thread_fence(__ATOMIC_RELEASE)
 #endif
@@ -139,13 +139,7 @@ pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
 static inline void
 pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
 {
-       /*
-        * XXX: It would be nicer to use __sync_lock_release here, but gcc insists
-        * on making that an atomic op which is far to expensive and a stronger
-        * guarantee than what we actually need.
-        */
-       pg_write_barrier_impl();
-       ptr->value = 0;
+       __sync_lock_release(&ptr->value);
 }
 #endif
 
index 747daa0a760e42554628a1c9312a48aa156666fa..419cbc389561211b189bf058b46bd73fa7e6b44c 100644 (file)
@@ -32,6 +32,8 @@
 #define pg_memory_barrier_impl()       MemoryBarrier()
 #endif
 
+#if defined(HAVE_ATOMICS)
+
 #define PG_HAVE_ATOMIC_U32_SUPPORT
 typedef struct pg_atomic_uint32
 {
@@ -44,9 +46,13 @@ typedef struct pg_atomic_uint64
        volatile uint64 value;
 } pg_atomic_uint64;
 
+#endif /* defined(HAVE_ATOMICS) */
+
 
 #if defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS)
 
+#if defined(HAVE_ATOMICS)
+
 #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
 static inline bool
 pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
@@ -100,4 +106,6 @@ pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
 }
 #endif /* _WIN64 */
 
+#endif /* HAVE_ATOMICS */
+
 #endif /* defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS) */
index b71b5230d3c9ec2350225b217e230e8c7956635b..77d3ebe0031cd0b1e8847d348d6527228d7e34fc 100644 (file)
@@ -17,6 +17,8 @@
  * -------------------------------------------------------------------------
  */
 
+#if defined(HAVE_ATOMICS)
+
 /* Older versions of the compiler don't have atomic.h... */
 #ifdef HAVE_ATOMIC_H
 
@@ -36,9 +38,13 @@ typedef struct pg_atomic_uint64
 
 #endif /* HAVE_ATOMIC_H */
 
+#endif /* defined(HAVE_ATOMICS) */
+
 
 #if defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS)
 
+#if defined(HAVE_ATOMICS)
+
 #ifdef HAVE_ATOMIC_H
 
 #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
@@ -71,4 +77,6 @@ pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
 
 #endif /* HAVE_ATOMIC_H */
 
+#endif /* defined(HAVE_ATOMICS) */
+
 #endif /* defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS) */
index 579554d8a67cf6486e358f20f52fc43148e236f3..1cc7ba28cde7075f010f74cb4d20778dff22561c 100644 (file)
@@ -16,6 +16,8 @@
  * -------------------------------------------------------------------------
  */
 
+#if defined(HAVE_ATOMICS)
+
 #include <atomic.h>
 
 #define PG_HAVE_ATOMIC_U32_SUPPORT
@@ -35,8 +37,12 @@ typedef struct pg_atomic_uint64
 
 #endif /* __64BIT__ */
 
+#endif /* defined(HAVE_ATOMICS) */
+
 #if defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS)
 
+#if defined(HAVE_ATOMICS)
+
 #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
 static inline bool
 pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
@@ -69,7 +75,6 @@ pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
 {
        return __fetch_and_add(&ptr->value, add_);
 }
-#endif
 
 #ifdef PG_HAVE_ATOMIC_U64_SUPPORT
 
@@ -96,8 +101,9 @@ pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
 {
        return __fetch_and_addlp(&ptr->value, add_);
 }
-#endif
 
 #endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
 
+#endif /* defined(HAVE_ATOMICS) */
+
 #endif /* defined(PG_USE_INLINE) || defined(ATOMICS_INCLUDE_DEFINITIONS) */