LCOV - differential code coverage report
Current view: top level - src/include/port/atomics - generic-gcc.h (source / functions) Coverage Total Hit CBC
Current: 7a15cff1f11193467898da1c1fabf06fd2caee04 vs 84a3778c79c2d28b4dc281d03ef2ab019b16483b Lines: 100.0 % 21 21 21
Current Date: 2025-12-15 18:36:29 -0500 Functions: 100.0 % 10 10 10
Baseline: lcov-20251216-010103-baseline Line coverage date bins:
Baseline Date: 2025-12-15 13:30:48 -0800 (360..) days: 100.0 % 21 21 21
Legend: Lines:     hit not hit Function coverage date bins:
(360..) days: 100.0 % 10 10 10

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * generic-gcc.h
                                  4                 :  *    Atomic operations, implemented using gcc (or compatible) intrinsics.
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  * NOTES:
                                 10                 :  *
                                 11                 :  * Documentation:
                                 12                 :  * * Legacy __sync Built-in Functions for Atomic Memory Access
                                 13                 :  *   https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fsync-Builtins.html
                                 14                 :  * * Built-in functions for memory model aware atomic operations
                                 15                 :  *   https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html
                                 16                 :  *
                                 17                 :  * src/include/port/atomics/generic-gcc.h
                                 18                 :  *
                                 19                 :  *-------------------------------------------------------------------------
                                 20                 :  */
                                 21                 : 
                                 22                 : /* intentionally no include guards, should only be included by atomics.h */
                                 23                 : #ifndef INSIDE_ATOMICS_H
                                 24                 : #error "should be included via atomics.h"
                                 25                 : #endif
                                 26                 : 
                                 27                 : /*
                                 28                 :  * An empty asm block should be a sufficient compiler barrier.
                                 29                 :  */
                                 30                 : #define pg_compiler_barrier_impl()  __asm__ __volatile__("" ::: "memory")
                                 31                 : 
                                 32                 : /*
                                 33                 :  * If we're on GCC, we should be able to get a memory barrier
                                 34                 :  * out of this compiler built-in.  But we prefer to rely on platform specific
                                 35                 :  * definitions where possible, and use this only as a fallback.
                                 36                 :  */
                                 37                 : #if !defined(pg_memory_barrier_impl)
                                 38                 : #   if defined(HAVE_GCC__ATOMIC_INT32_CAS)
                                 39                 : #       define pg_memory_barrier_impl()     __atomic_thread_fence(__ATOMIC_SEQ_CST)
                                 40                 : #   elif defined(__GNUC__)
                                 41                 : #       define pg_memory_barrier_impl()     __sync_synchronize()
                                 42                 : #   endif
                                 43                 : #endif /* !defined(pg_memory_barrier_impl) */
                                 44                 : 
                                 45                 : #if !defined(pg_read_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
                                 46                 : /* acquire semantics include read barrier semantics */
                                 47                 : #       define pg_read_barrier_impl() do \
                                 48                 : { \
                                 49                 :     pg_compiler_barrier_impl(); \
                                 50                 :     __atomic_thread_fence(__ATOMIC_ACQUIRE); \
                                 51                 : } while (0)
                                 52                 : #endif
                                 53                 : 
                                 54                 : #if !defined(pg_write_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
                                 55                 : /* release semantics include write barrier semantics */
                                 56                 : #       define pg_write_barrier_impl() do \
                                 57                 : { \
                                 58                 :     pg_compiler_barrier_impl(); \
                                 59                 :     __atomic_thread_fence(__ATOMIC_RELEASE); \
                                 60                 : } while (0)
                                 61                 : #endif
                                 62                 : 
                                 63                 : 
                                 64                 : /* generic gcc based atomic flag implementation */
                                 65                 : #if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) \
                                 66                 :     && (defined(HAVE_GCC__SYNC_INT32_TAS) || defined(HAVE_GCC__SYNC_CHAR_TAS))
                                 67                 : 
                                 68                 : #define PG_HAVE_ATOMIC_FLAG_SUPPORT
                                 69                 : typedef struct pg_atomic_flag
                                 70                 : {
                                 71                 :     /*
                                 72                 :      * If we have a choice, use int-width TAS, because that is more efficient
                                 73                 :      * and/or more reliably implemented on most non-Intel platforms.  (Note
                                 74                 :      * that this code isn't used on x86[_64]; see arch-x86.h for that.)
                                 75                 :      */
                                 76                 : #ifdef HAVE_GCC__SYNC_INT32_TAS
                                 77                 :     volatile int value;
                                 78                 : #else
                                 79                 :     volatile char value;
                                 80                 : #endif
                                 81                 : } pg_atomic_flag;
                                 82                 : 
                                 83                 : #endif /* !ATOMIC_FLAG_SUPPORT && SYNC_INT32_TAS */
                                 84                 : 
                                 85                 : /* generic gcc based atomic uint32 implementation */
                                 86                 : #if !defined(PG_HAVE_ATOMIC_U32_SUPPORT) \
                                 87                 :     && (defined(HAVE_GCC__ATOMIC_INT32_CAS) || defined(HAVE_GCC__SYNC_INT32_CAS))
                                 88                 : 
                                 89                 : #define PG_HAVE_ATOMIC_U32_SUPPORT
                                 90                 : typedef struct pg_atomic_uint32
                                 91                 : {
                                 92                 :     volatile uint32 value;
                                 93                 : } pg_atomic_uint32;
                                 94                 : 
                                 95                 : #endif /* defined(HAVE_GCC__ATOMIC_INT32_CAS) || defined(HAVE_GCC__SYNC_INT32_CAS) */
                                 96                 : 
                                 97                 : /* generic gcc based atomic uint64 implementation */
                                 98                 : #if !defined(PG_HAVE_ATOMIC_U64_SUPPORT) \
                                 99                 :     && !defined(PG_DISABLE_64_BIT_ATOMICS) \
                                100                 :     && (defined(HAVE_GCC__ATOMIC_INT64_CAS) || defined(HAVE_GCC__SYNC_INT64_CAS))
                                101                 : 
                                102                 : #define PG_HAVE_ATOMIC_U64_SUPPORT
                                103                 : typedef struct pg_atomic_uint64
                                104                 : {
                                105                 :     alignas(8) volatile uint64 value;
                                106                 : } pg_atomic_uint64;
                                107                 : 
                                108                 : #endif /* defined(HAVE_GCC__ATOMIC_INT64_CAS) || defined(HAVE_GCC__SYNC_INT64_CAS) */
                                109                 : 
                                110                 : #ifdef PG_HAVE_ATOMIC_FLAG_SUPPORT
                                111                 : 
                                112                 : #if defined(HAVE_GCC__SYNC_CHAR_TAS) || defined(HAVE_GCC__SYNC_INT32_TAS)
                                113                 : 
                                114                 : #ifndef PG_HAVE_ATOMIC_TEST_SET_FLAG
                                115                 : #define PG_HAVE_ATOMIC_TEST_SET_FLAG
                                116                 : static inline bool
                                117                 : pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
                                118                 : {
                                119                 :     /* NB: only an acquire barrier, not a full one */
                                120                 :     /* some platform only support a 1 here */
                                121                 :     return __sync_lock_test_and_set(&ptr->value, 1) == 0;
                                122                 : }
                                123                 : #endif
                                124                 : 
                                125                 : #endif /* defined(HAVE_GCC__SYNC_*_TAS) */
                                126                 : 
                                127                 : #ifndef PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
                                128                 : #define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
                                129                 : static inline bool
 4100 andres@anarazel.de        130 CBC        2383 : pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
                                131                 : {
                                132            2383 :     return ptr->value == 0;
                                133                 : }
                                134                 : #endif
                                135                 : 
                                136                 : #ifndef PG_HAVE_ATOMIC_CLEAR_FLAG
                                137                 : #define PG_HAVE_ATOMIC_CLEAR_FLAG
                                138                 : static inline void
                                139                 : pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
                                140                 : {
                                141                 :     __sync_lock_release(&ptr->value);
                                142                 : }
                                143                 : #endif
                                144                 : 
                                145                 : #ifndef PG_HAVE_ATOMIC_INIT_FLAG
                                146                 : #define PG_HAVE_ATOMIC_INIT_FLAG
                                147                 : static inline void
                                148           11725 : pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
                                149                 : {
                                150           11725 :     pg_atomic_clear_flag_impl(ptr);
                                151           11725 : }
                                152                 : #endif
                                153                 : 
                                154                 : #endif /* defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) */
                                155                 : 
                                156                 : /* prefer __atomic, it has a better API */
                                157                 : #if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
                                158                 : #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
                                159                 : static inline bool
                                160                 : pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
                                161                 :                                     uint32 *expected, uint32 newval)
                                162                 : {
                                163                 :     /* FIXME: we can probably use a lower consistency model */
                                164                 :     return __atomic_compare_exchange_n(&ptr->value, expected, newval, false,
                                165                 :                                        __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
                                166                 : }
                                167                 : #endif
                                168                 : 
                                169                 : #if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
                                170                 : #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
                                171                 : static inline bool
                                172                 : pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
                                173                 :                                     uint32 *expected, uint32 newval)
                                174                 : {
                                175                 :     bool    ret;
                                176                 :     uint32  current;
                                177                 :     current = __sync_val_compare_and_swap(&ptr->value, *expected, newval);
                                178                 :     ret = current == *expected;
                                179                 :     *expected = current;
                                180                 :     return ret;
                                181                 : }
                                182                 : #endif
                                183                 : 
                                184                 : /*
                                185                 :  * __sync_lock_test_and_set() only supports setting the value to 1 on some
                                186                 :  * platforms, so we only provide an __atomic implementation for
                                187                 :  * pg_atomic_exchange.
                                188                 :  *
                                189                 :  * We assume the availability of 32-bit __atomic_compare_exchange_n() implies
                                190                 :  * the availability of 32-bit __atomic_exchange_n().
                                191                 :  */
                                192                 : #if !defined(PG_HAVE_ATOMIC_EXCHANGE_U32) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
                                193                 : #define PG_HAVE_ATOMIC_EXCHANGE_U32
                                194                 : static inline uint32
  729 nathan@postgresql.or      195           12850 : pg_atomic_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 newval)
                                196                 : {
                                197           12850 :     return __atomic_exchange_n(&ptr->value, newval, __ATOMIC_SEQ_CST);
                                198                 : }
                                199                 : #endif
                                200                 : 
                                201                 : /* if we have 32-bit __sync_val_compare_and_swap, assume we have these too: */
                                202                 : 
                                203                 : #if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
                                204                 : #define PG_HAVE_ATOMIC_FETCH_ADD_U32
                                205                 : static inline uint32
                                206                 : pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
                                207                 : {
                                208                 :     return __sync_fetch_and_add(&ptr->value, add_);
                                209                 : }
                                210                 : #endif
                                211                 : 
                                212                 : #if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
                                213                 : #define PG_HAVE_ATOMIC_FETCH_SUB_U32
                                214                 : static inline uint32
 3023 tgl@sss.pgh.pa.us         215       304174135 : pg_atomic_fetch_sub_u32_impl(volatile pg_atomic_uint32 *ptr, int32 sub_)
                                216                 : {
                                217       304174135 :     return __sync_fetch_and_sub(&ptr->value, sub_);
                                218                 : }
                                219                 : #endif
                                220                 : 
                                221                 : #if !defined(PG_HAVE_ATOMIC_FETCH_AND_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
                                222                 : #define PG_HAVE_ATOMIC_FETCH_AND_U32
                                223                 : static inline uint32
                                224         2650000 : pg_atomic_fetch_and_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 and_)
                                225                 : {
                                226         2650000 :     return __sync_fetch_and_and(&ptr->value, and_);
                                227                 : }
                                228                 : #endif
                                229                 : 
                                230                 : #if !defined(PG_HAVE_ATOMIC_FETCH_OR_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
                                231                 : #define PG_HAVE_ATOMIC_FETCH_OR_U32
                                232                 : static inline uint32
                                233        34132285 : pg_atomic_fetch_or_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 or_)
                                234                 : {
                                235        34132285 :     return __sync_fetch_and_or(&ptr->value, or_);
                                236                 : }
                                237                 : #endif
                                238                 : 
                                239                 : 
                                240                 : #if !defined(PG_DISABLE_64_BIT_ATOMICS)
                                241                 : 
                                242                 : #if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64) && defined(HAVE_GCC__ATOMIC_INT64_CAS)
                                243                 : #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
                                244                 : static inline bool
                                245                 : pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
                                246                 :                                     uint64 *expected, uint64 newval)
                                247                 : {
                                248                 :     AssertPointerAlignment(expected, 8);
                                249                 :     return __atomic_compare_exchange_n(&ptr->value, expected, newval, false,
                                250                 :                                        __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
                                251                 : }
                                252                 : #endif
                                253                 : 
                                254                 : #if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
                                255                 : #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
                                256                 : static inline bool
                                257                 : pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
                                258                 :                                     uint64 *expected, uint64 newval)
                                259                 : {
                                260                 :     bool    ret;
                                261                 :     uint64  current;
                                262                 : 
                                263                 :     AssertPointerAlignment(expected, 8);
                                264                 :     current = __sync_val_compare_and_swap(&ptr->value, *expected, newval);
                                265                 :     ret = current == *expected;
                                266                 :     *expected = current;
                                267                 :     return ret;
                                268                 : }
                                269                 : #endif
                                270                 : 
                                271                 : /*
                                272                 :  * __sync_lock_test_and_set() only supports setting the value to 1 on some
                                273                 :  * platforms, so we only provide an __atomic implementation for
                                274                 :  * pg_atomic_exchange.
                                275                 :  *
                                276                 :  * We assume the availability of 64-bit __atomic_compare_exchange_n() implies
                                277                 :  * the availability of 64-bit __atomic_exchange_n().
                                278                 :  */
                                279                 : #if !defined(PG_HAVE_ATOMIC_EXCHANGE_U64) && defined(HAVE_GCC__ATOMIC_INT64_CAS)
                                280                 : #define PG_HAVE_ATOMIC_EXCHANGE_U64
                                281                 : static inline uint64
  729 nathan@postgresql.or      282        16528261 : pg_atomic_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 newval)
                                283                 : {
                                284        16528261 :     return __atomic_exchange_n(&ptr->value, newval, __ATOMIC_SEQ_CST);
                                285                 : }
                                286                 : #endif
                                287                 : 
                                288                 : /* if we have 64-bit __sync_val_compare_and_swap, assume we have these too: */
                                289                 : 
                                290                 : #if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
                                291                 : #define PG_HAVE_ATOMIC_FETCH_ADD_U64
                                292                 : static inline uint64
                                293                 : pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
                                294                 : {
                                295                 :     return __sync_fetch_and_add(&ptr->value, add_);
                                296                 : }
                                297                 : #endif
                                298                 : 
                                299                 : #if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
                                300                 : #define PG_HAVE_ATOMIC_FETCH_SUB_U64
                                301                 : static inline uint64
 3023 tgl@sss.pgh.pa.us         302               8 : pg_atomic_fetch_sub_u64_impl(volatile pg_atomic_uint64 *ptr, int64 sub_)
                                303                 : {
                                304               8 :     return __sync_fetch_and_sub(&ptr->value, sub_);
                                305                 : }
                                306                 : #endif
                                307                 : 
                                308                 : #if !defined(PG_HAVE_ATOMIC_FETCH_AND_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
                                309                 : #define PG_HAVE_ATOMIC_FETCH_AND_U64
                                310                 : static inline uint64
                                311               9 : pg_atomic_fetch_and_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 and_)
                                312                 : {
                                313               9 :     return __sync_fetch_and_and(&ptr->value, and_);
                                314                 : }
                                315                 : #endif
                                316                 : 
                                317                 : #if !defined(PG_HAVE_ATOMIC_FETCH_OR_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
                                318                 : #define PG_HAVE_ATOMIC_FETCH_OR_U64
                                319                 : static inline uint64
                                320               6 : pg_atomic_fetch_or_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 or_)
                                321                 : {
                                322               6 :     return __sync_fetch_and_or(&ptr->value, or_);
                                323                 : }
                                324                 : #endif
                                325                 : 
                                326                 : #endif /* !defined(PG_DISABLE_64_BIT_ATOMICS) */
        

Generated by: LCOV version 2.4-beta