diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/port/atomics.h | 25 | ||||
-rw-r--r-- | src/include/port/atomics/fallback.h | 3 | ||||
-rw-r--r-- | src/include/port/atomics/generic.h | 9 | ||||
-rw-r--r-- | src/include/storage/buf_internals.h | 3 |
4 files changed, 37 insertions, 3 deletions
diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h index f7884d72c6e..4e15ff8764d 100644 --- a/src/include/port/atomics.h +++ b/src/include/port/atomics.h @@ -255,10 +255,12 @@ pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr) } /* - * pg_atomic_write_u32 - unlocked write to atomic variable. + * pg_atomic_write_u32 - write to atomic variable. * * The write is guaranteed to succeed as a whole, i.e. it's not possible to - * observe a partial write for any reader. + * observe a partial write for any reader. Note that this correctly interacts + * with pg_atomic_compare_exchange_u32, in contrast to + * pg_atomic_unlocked_write_u32(). * * No barrier semantics. */ @@ -271,6 +273,25 @@ pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val) } /* + * pg_atomic_unlocked_write_u32 - unlocked write to atomic variable. + * + * The write is guaranteed to succeed as a whole, i.e. it's not possible to + * observe a partial write for any reader. But note that writing this way is + * not guaranteed to correctly interact with read-modify-write operations like + * pg_atomic_compare_exchange_u32. This should only be used in cases where + * minor performance regressions due to atomics emulation are unacceptable. + * + * No barrier semantics. + */ +static inline void +pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val) +{ + AssertPointerAlignment(ptr, 4); + + pg_atomic_unlocked_write_u32_impl(ptr, val); +} + +/* * pg_atomic_exchange_u32 - exchange newval with current value * * Returns the old value of 'ptr' before the swap. diff --git a/src/include/port/atomics/fallback.h b/src/include/port/atomics/fallback.h index bdaa795abe0..2290fff196f 100644 --- a/src/include/port/atomics/fallback.h +++ b/src/include/port/atomics/fallback.h @@ -133,6 +133,9 @@ pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr) #define PG_HAVE_ATOMIC_INIT_U32 extern void pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_); +#define PG_HAVE_ATOMIC_WRITE_U32 +extern void pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val); + #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32 extern bool pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval); diff --git a/src/include/port/atomics/generic.h b/src/include/port/atomics/generic.h index 32a01136e61..1acd19242b2 100644 --- a/src/include/port/atomics/generic.h +++ b/src/include/port/atomics/generic.h @@ -58,6 +58,15 @@ pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val) } #endif +#ifndef PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32 +#define PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32 +static inline void +pg_atomic_unlocked_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val) +{ + ptr->value = val; +} +#endif + /* * provide fallback for test_and_set using atomic_exchange if available */ diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index e0dfb2f5b03..c7da9f6ac2f 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -168,7 +168,8 @@ typedef struct buftag * We use this same struct for local buffer headers, but the locks are not * used and not all of the flag bits are useful either. To avoid unnecessary * overhead, manipulations of the state field should be done without actual - * atomic operations (i.e. only pg_atomic_read/write). + * atomic operations (i.e. only pg_atomic_read_u32() and + * pg_atomic_unlocked_write_u32()). * * Be careful to avoid increasing the size of the struct when adding or * reordering members. Keeping it below 64 bytes (the most common CPU |