LCOV - code coverage report
Current view: top level - src/include/port - atomics.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 100.0 % 80 80
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 32 32
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 100.0 % 6 6

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * atomics.h
       4                 :             :  *    Atomic operations.
       5                 :             :  *
       6                 :             :  * Hardware and compiler dependent functions for manipulating memory
       7                 :             :  * atomically and dealing with cache coherency. Used to implement locking
       8                 :             :  * facilities and lockless algorithms/data structures.
       9                 :             :  *
      10                 :             :  * To bring up postgres on a platform/compiler at the very least
      11                 :             :  * implementations for the following operations should be provided:
      12                 :             :  * * pg_compiler_barrier(), pg_write_barrier(), pg_read_barrier()
      13                 :             :  * * pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32()
      14                 :             :  * * pg_atomic_test_set_flag(), pg_atomic_init_flag(), pg_atomic_clear_flag()
      15                 :             :  * * PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY should be defined if appropriate.
      16                 :             :  *
      17                 :             :  * There exist generic, hardware independent, implementations for several
      18                 :             :  * compilers which might be sufficient, although possibly not optimal, for a
      19                 :             :  * new platform. If no such generic implementation is available spinlocks will
      20                 :             :  * be used to implement the 64-bit parts of the API.
      21                 :             :  *
      22                 :             :  * Implement _u64 atomics if and only if your platform can use them
      23                 :             :  * efficiently (and obviously correctly).
      24                 :             :  *
      25                 :             :  * Use higher level functionality (lwlocks, spinlocks, heavyweight locks)
      26                 :             :  * whenever possible. Writing correct code using these facilities is hard.
      27                 :             :  *
      28                 :             :  * For an introduction to using memory barriers within the PostgreSQL backend,
      29                 :             :  * see src/backend/storage/lmgr/README.barrier
      30                 :             :  *
      31                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      32                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      33                 :             :  *
      34                 :             :  * src/include/port/atomics.h
      35                 :             :  *
      36                 :             :  *-------------------------------------------------------------------------
      37                 :             :  */
      38                 :             : #ifndef ATOMICS_H
      39                 :             : #define ATOMICS_H
      40                 :             : 
      41                 :             : #ifdef FRONTEND
      42                 :             : #error "atomics.h may not be included from frontend code"
      43                 :             : #endif
      44                 :             : 
      45                 :             : #define INSIDE_ATOMICS_H
      46                 :             : 
      47                 :             : #include <limits.h>
      48                 :             : 
      49                 :             : /*
      50                 :             :  * First a set of architecture specific files is included.
      51                 :             :  *
      52                 :             :  * These files can provide the full set of atomics or can do pretty much
      53                 :             :  * nothing if all the compilers commonly used on these platforms provide
      54                 :             :  * usable generics.
      55                 :             :  *
      56                 :             :  * Don't add an inline assembly of the actual atomic operations if all the
      57                 :             :  * common implementations of your platform provide intrinsics. Intrinsics are
      58                 :             :  * much easier to understand and potentially support more architectures.
      59                 :             :  *
      60                 :             :  * It will often make sense to define memory barrier semantics here, since
      61                 :             :  * e.g. generic compiler intrinsics for x86 memory barriers can't know that
      62                 :             :  * postgres doesn't need x86 read/write barriers do anything more than a
      63                 :             :  * compiler barrier.
      64                 :             :  *
      65                 :             :  */
      66                 :             : #if defined(__arm__) || defined(__aarch64__)
      67                 :             : #include "port/atomics/arch-arm.h"
      68                 :             : #elif defined(__i386__) || defined(__x86_64__)
      69                 :             : #include "port/atomics/arch-x86.h"
      70                 :             : #elif defined(__powerpc__) || defined(__powerpc64__)
      71                 :             : #include "port/atomics/arch-ppc.h"
      72                 :             : #endif
      73                 :             : 
      74                 :             : /*
      75                 :             :  * Compiler specific, but architecture independent implementations.
      76                 :             :  *
      77                 :             :  * Provide architecture independent implementations of the atomic
      78                 :             :  * facilities. At the very least compiler barriers should be provided, but a
      79                 :             :  * full implementation of
      80                 :             :  * * pg_compiler_barrier(), pg_write_barrier(), pg_read_barrier()
      81                 :             :  * * pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32()
      82                 :             :  * using compiler intrinsics are a good idea.
      83                 :             :  */
      84                 :             : /*
      85                 :             :  * gcc or compatible, including clang and icc.
      86                 :             :  */
      87                 :             : #if defined(__GNUC__) || defined(__INTEL_COMPILER)
      88                 :             : #include "port/atomics/generic-gcc.h"
      89                 :             : #elif defined(_MSC_VER)
      90                 :             : #include "port/atomics/generic-msvc.h"
      91                 :             : #else
      92                 :             : /* Unknown compiler. */
      93                 :             : #endif
      94                 :             : 
      95                 :             : /* Fail if we couldn't find implementations of required facilities. */
      96                 :             : #if !defined(PG_HAVE_ATOMIC_U32_SUPPORT)
      97                 :             : #error "could not find an implementation of pg_atomic_uint32"
      98                 :             : #endif
      99                 :             : #if !defined(pg_compiler_barrier_impl)
     100                 :             : #error "could not find an implementation of pg_compiler_barrier"
     101                 :             : #endif
     102                 :             : #if !defined(pg_memory_barrier_impl)
     103                 :             : #error "could not find an implementation of pg_memory_barrier_impl"
     104                 :             : #endif
     105                 :             : 
     106                 :             : 
     107                 :             : /*
     108                 :             :  * Provide a spinlock-based implementation of the 64 bit variants, if
     109                 :             :  * necessary.
     110                 :             :  */
     111                 :             : #include "port/atomics/fallback.h"
     112                 :             : 
     113                 :             : /*
     114                 :             :  * Provide additional operations using supported infrastructure. These are
     115                 :             :  * expected to be efficient if the underlying atomic operations are efficient.
     116                 :             :  */
     117                 :             : #include "port/atomics/generic.h"
     118                 :             : 
     119                 :             : 
     120                 :             : /*
     121                 :             :  * pg_compiler_barrier - prevent the compiler from moving code across
     122                 :             :  *
     123                 :             :  * A compiler barrier need not (and preferably should not) emit any actual
     124                 :             :  * machine code, but must act as an optimization fence: the compiler must not
     125                 :             :  * reorder loads or stores to main memory around the barrier.  However, the
     126                 :             :  * CPU may still reorder loads or stores at runtime, if the architecture's
     127                 :             :  * memory model permits this.
     128                 :             :  */
     129                 :             : #define pg_compiler_barrier()   pg_compiler_barrier_impl()
     130                 :             : 
     131                 :             : /*
     132                 :             :  * pg_memory_barrier - prevent the CPU from reordering memory access
     133                 :             :  *
     134                 :             :  * A memory barrier must act as a compiler barrier, and in addition must
     135                 :             :  * guarantee that all loads and stores issued prior to the barrier are
     136                 :             :  * completed before any loads or stores issued after the barrier.  Unless
     137                 :             :  * loads and stores are totally ordered (which is not the case on most
     138                 :             :  * architectures) this requires issuing some sort of memory fencing
     139                 :             :  * instruction.
     140                 :             :  */
     141                 :             : #define pg_memory_barrier() pg_memory_barrier_impl()
     142                 :             : 
     143                 :             : /*
     144                 :             :  * pg_(read|write)_barrier - prevent the CPU from reordering memory access
     145                 :             :  *
     146                 :             :  * A read barrier must act as a compiler barrier, and in addition must
     147                 :             :  * guarantee that any loads issued prior to the barrier are completed before
     148                 :             :  * any loads issued after the barrier.  Similarly, a write barrier acts
     149                 :             :  * as a compiler barrier, and also orders stores.  Read and write barriers
     150                 :             :  * are thus weaker than a full memory barrier, but stronger than a compiler
     151                 :             :  * barrier.  In practice, on machines with strong memory ordering, read and
     152                 :             :  * write barriers may require nothing more than a compiler barrier.
     153                 :             :  */
     154                 :             : #define pg_read_barrier()   pg_read_barrier_impl()
     155                 :             : #define pg_write_barrier()  pg_write_barrier_impl()
     156                 :             : 
     157                 :             : /*
     158                 :             :  * pg_atomic_init_flag - initialize atomic flag.
     159                 :             :  *
     160                 :             :  * No barrier semantics.
     161                 :             :  */
     162                 :             : static inline void
     163                 :       13755 : pg_atomic_init_flag(volatile pg_atomic_flag *ptr)
     164                 :             : {
     165                 :       13755 :     pg_atomic_init_flag_impl(ptr);
     166                 :       13755 : }
     167                 :             : 
     168                 :             : /*
     169                 :             :  * pg_atomic_test_set_flag - TAS()
     170                 :             :  *
     171                 :             :  * Returns true if the flag has successfully been set, false otherwise.
     172                 :             :  *
     173                 :             :  * Acquire (including read barrier) semantics.
     174                 :             :  */
     175                 :             : static inline bool
     176                 :      219543 : pg_atomic_test_set_flag(volatile pg_atomic_flag *ptr)
     177                 :             : {
     178                 :      219543 :     return pg_atomic_test_set_flag_impl(ptr);
     179                 :             : }
     180                 :             : 
     181                 :             : /*
     182                 :             :  * pg_atomic_unlocked_test_flag - Check if the lock is free
     183                 :             :  *
     184                 :             :  * Returns true if the flag currently is not set, false otherwise.
     185                 :             :  *
     186                 :             :  * No barrier semantics.
     187                 :             :  */
     188                 :             : static inline bool
     189                 :      450823 : pg_atomic_unlocked_test_flag(volatile pg_atomic_flag *ptr)
     190                 :             : {
     191                 :      450823 :     return pg_atomic_unlocked_test_flag_impl(ptr);
     192                 :             : }
     193                 :             : 
     194                 :             : /*
     195                 :             :  * pg_atomic_clear_flag - release lock set by TAS()
     196                 :             :  *
     197                 :             :  * Release (including write barrier) semantics.
     198                 :             :  */
     199                 :             : static inline void
     200                 :        1581 : pg_atomic_clear_flag(volatile pg_atomic_flag *ptr)
     201                 :             : {
     202                 :        1581 :     pg_atomic_clear_flag_impl(ptr);
     203                 :        1581 : }
     204                 :             : 
     205                 :             : 
     206                 :             : /*
     207                 :             :  * pg_atomic_init_u32 - initialize atomic variable
     208                 :             :  *
     209                 :             :  * Has to be done before any concurrent usage..
     210                 :             :  *
     211                 :             :  * No barrier semantics.
     212                 :             :  */
     213                 :             : static inline void
     214                 :     4036577 : pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
     215                 :             : {
     216                 :             :     AssertPointerAlignment(ptr, 4);
     217                 :             : 
     218                 :     4036577 :     pg_atomic_init_u32_impl(ptr, val);
     219                 :     4036577 : }
     220                 :             : 
     221                 :             : /*
     222                 :             :  * pg_atomic_read_u32 - unlocked read from atomic variable.
     223                 :             :  *
     224                 :             :  * The read is guaranteed to return a value as it has been written by this or
     225                 :             :  * another process at some point in the past. There's however no cache
     226                 :             :  * coherency interaction guaranteeing the value hasn't since been written to
     227                 :             :  * again.
     228                 :             :  *
     229                 :             :  * No barrier semantics.
     230                 :             :  */
     231                 :             : static inline uint32
     232                 :   376944980 : pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
     233                 :             : {
     234                 :             :     AssertPointerAlignment(ptr, 4);
     235                 :   376944980 :     return pg_atomic_read_u32_impl(ptr);
     236                 :             : }
     237                 :             : 
     238                 :             : /*
     239                 :             :  * pg_atomic_read_membarrier_u32 - read with barrier semantics.
     240                 :             :  *
     241                 :             :  * This read is guaranteed to return the current value, provided that the value
     242                 :             :  * is only ever updated via operations with barrier semantics, such as
     243                 :             :  * pg_atomic_compare_exchange_u32() and pg_atomic_write_membarrier_u32().
     244                 :             :  * While this may be less performant than pg_atomic_read_u32(), it may be
     245                 :             :  * easier to reason about correctness with this function in less performance-
     246                 :             :  * sensitive code.
     247                 :             :  *
     248                 :             :  * Full barrier semantics.
     249                 :             :  */
     250                 :             : static inline uint32
     251                 :          19 : pg_atomic_read_membarrier_u32(volatile pg_atomic_uint32 *ptr)
     252                 :             : {
     253                 :             :     AssertPointerAlignment(ptr, 4);
     254                 :             : 
     255                 :          19 :     return pg_atomic_read_membarrier_u32_impl(ptr);
     256                 :             : }
     257                 :             : 
     258                 :             : /*
     259                 :             :  * pg_atomic_write_u32 - write to atomic variable.
     260                 :             :  *
     261                 :             :  * The write is guaranteed to succeed as a whole, i.e. it's not possible to
     262                 :             :  * observe a partial write for any reader.  Note that this correctly interacts
     263                 :             :  * with pg_atomic_compare_exchange_u32, in contrast to
     264                 :             :  * pg_atomic_unlocked_write_u32().
     265                 :             :  *
     266                 :             :  * No barrier semantics.
     267                 :             :  */
     268                 :             : static inline void
     269                 :       77048 : pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
     270                 :             : {
     271                 :             :     AssertPointerAlignment(ptr, 4);
     272                 :             : 
     273                 :       77048 :     pg_atomic_write_u32_impl(ptr, val);
     274                 :       77048 : }
     275                 :             : 
     276                 :             : /*
     277                 :             :  * pg_atomic_unlocked_write_u32 - unlocked write to atomic variable.
     278                 :             :  *
     279                 :             :  * Write to an atomic variable, without atomicity guarantees. I.e. it is not
     280                 :             :  * guaranteed that a concurrent reader will not see a torn value, nor is this
     281                 :             :  * guaranteed to correctly interact with concurrent read-modify-write
     282                 :             :  * operations like pg_atomic_compare_exchange_u32.  This should only be used
     283                 :             :  * in cases where minor performance regressions due to atomic operations are
     284                 :             :  * unacceptable and where exclusive access is guaranteed via some external
     285                 :             :  * means.
     286                 :             :  *
     287                 :             :  * No barrier semantics.
     288                 :             :  */
     289                 :             : static inline void
     290                 :             : pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
     291                 :             : {
     292                 :             :     AssertPointerAlignment(ptr, 4);
     293                 :             : 
     294                 :             :     pg_atomic_unlocked_write_u32_impl(ptr, val);
     295                 :             : }
     296                 :             : 
     297                 :             : /*
     298                 :             :  * pg_atomic_write_membarrier_u32 - write with barrier semantics.
     299                 :             :  *
     300                 :             :  * The write is guaranteed to succeed as a whole, i.e., it's not possible to
     301                 :             :  * observe a partial write for any reader.  Note that this correctly interacts
     302                 :             :  * with both pg_atomic_compare_exchange_u32() and
     303                 :             :  * pg_atomic_read_membarrier_u32().  While this may be less performant than
     304                 :             :  * pg_atomic_write_u32(), it may be easier to reason about correctness with
     305                 :             :  * this function in less performance-sensitive code.
     306                 :             :  *
     307                 :             :  * Full barrier semantics.
     308                 :             :  */
     309                 :             : static inline void
     310                 :       24748 : pg_atomic_write_membarrier_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
     311                 :             : {
     312                 :             :     AssertPointerAlignment(ptr, 4);
     313                 :             : 
     314                 :       24748 :     pg_atomic_write_membarrier_u32_impl(ptr, val);
     315                 :       24748 : }
     316                 :             : 
     317                 :             : /*
     318                 :             :  * pg_atomic_exchange_u32 - exchange newval with current value
     319                 :             :  *
     320                 :             :  * Returns the old value of 'ptr' before the swap.
     321                 :             :  *
     322                 :             :  * Full barrier semantics.
     323                 :             :  */
     324                 :             : static inline uint32
     325                 :       18640 : pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
     326                 :             : {
     327                 :             :     AssertPointerAlignment(ptr, 4);
     328                 :             : 
     329                 :       18640 :     return pg_atomic_exchange_u32_impl(ptr, newval);
     330                 :             : }
     331                 :             : 
     332                 :             : /*
     333                 :             :  * pg_atomic_compare_exchange_u32 - CAS operation
     334                 :             :  *
     335                 :             :  * Atomically compare the current value of ptr with *expected and store newval
     336                 :             :  * iff ptr and *expected have the same value. The current value of *ptr will
     337                 :             :  * always be stored in *expected.
     338                 :             :  *
     339                 :             :  * Return true if values have been exchanged, false otherwise.
     340                 :             :  *
     341                 :             :  * Full barrier semantics.
     342                 :             :  */
     343                 :             : static inline bool
     344                 :   362906380 : pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr,
     345                 :             :                                uint32 *expected, uint32 newval)
     346                 :             : {
     347                 :             :     AssertPointerAlignment(ptr, 4);
     348                 :             :     AssertPointerAlignment(expected, 4);
     349                 :             : 
     350                 :   362906380 :     return pg_atomic_compare_exchange_u32_impl(ptr, expected, newval);
     351                 :             : }
     352                 :             : 
     353                 :             : /*
     354                 :             :  * pg_atomic_fetch_add_u32 - atomically add to variable
     355                 :             :  *
     356                 :             :  * Returns the value of ptr before the arithmetic operation.
     357                 :             :  *
     358                 :             :  * Full barrier semantics.
     359                 :             :  */
     360                 :             : static inline uint32
     361                 :     8524630 : pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
     362                 :             : {
     363                 :             :     AssertPointerAlignment(ptr, 4);
     364                 :     8524630 :     return pg_atomic_fetch_add_u32_impl(ptr, add_);
     365                 :             : }
     366                 :             : 
     367                 :             : /*
     368                 :             :  * pg_atomic_fetch_sub_u32 - atomically subtract from variable
     369                 :             :  *
     370                 :             :  * Returns the value of ptr before the arithmetic operation. Note that sub_
     371                 :             :  * may not be INT_MIN due to platform limitations.
     372                 :             :  *
     373                 :             :  * Full barrier semantics.
     374                 :             :  */
     375                 :             : static inline uint32
     376                 :     1170258 : pg_atomic_fetch_sub_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
     377                 :             : {
     378                 :             :     AssertPointerAlignment(ptr, 4);
     379                 :             :     Assert(sub_ != INT_MIN);
     380                 :     1170258 :     return pg_atomic_fetch_sub_u32_impl(ptr, sub_);
     381                 :             : }
     382                 :             : 
     383                 :             : /*
     384                 :             :  * pg_atomic_fetch_and_u32 - atomically bit-and and_ with variable
     385                 :             :  *
     386                 :             :  * Returns the value of ptr before the arithmetic operation.
     387                 :             :  *
     388                 :             :  * Full barrier semantics.
     389                 :             :  */
     390                 :             : static inline uint32
     391                 :    13177574 : pg_atomic_fetch_and_u32(volatile pg_atomic_uint32 *ptr, uint32 and_)
     392                 :             : {
     393                 :             :     AssertPointerAlignment(ptr, 4);
     394                 :    13177574 :     return pg_atomic_fetch_and_u32_impl(ptr, and_);
     395                 :             : }
     396                 :             : 
     397                 :             : /*
     398                 :             :  * pg_atomic_fetch_or_u32 - atomically bit-or or_ with variable
     399                 :             :  *
     400                 :             :  * Returns the value of ptr before the arithmetic operation.
     401                 :             :  *
     402                 :             :  * Full barrier semantics.
     403                 :             :  */
     404                 :             : static inline uint32
     405                 :    18222336 : pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
     406                 :             : {
     407                 :             :     AssertPointerAlignment(ptr, 4);
     408                 :    18222336 :     return pg_atomic_fetch_or_u32_impl(ptr, or_);
     409                 :             : }
     410                 :             : 
     411                 :             : /*
     412                 :             :  * pg_atomic_add_fetch_u32 - atomically add to variable
     413                 :             :  *
     414                 :             :  * Returns the value of ptr after the arithmetic operation.
     415                 :             :  *
     416                 :             :  * Full barrier semantics.
     417                 :             :  */
     418                 :             : static inline uint32
     419                 :         897 : pg_atomic_add_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
     420                 :             : {
     421                 :             :     AssertPointerAlignment(ptr, 4);
     422                 :         897 :     return pg_atomic_add_fetch_u32_impl(ptr, add_);
     423                 :             : }
     424                 :             : 
     425                 :             : /*
     426                 :             :  * pg_atomic_sub_fetch_u32 - atomically subtract from variable
     427                 :             :  *
     428                 :             :  * Returns the value of ptr after the arithmetic operation. Note that sub_ may
     429                 :             :  * not be INT_MIN due to platform limitations.
     430                 :             :  *
     431                 :             :  * Full barrier semantics.
     432                 :             :  */
     433                 :             : static inline uint32
     434                 :   347625019 : pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
     435                 :             : {
     436                 :             :     AssertPointerAlignment(ptr, 4);
     437                 :             :     Assert(sub_ != INT_MIN);
     438                 :   347625019 :     return pg_atomic_sub_fetch_u32_impl(ptr, sub_);
     439                 :             : }
     440                 :             : 
     441                 :             : /* ----
     442                 :             :  * The 64 bit operations have the same semantics as their 32bit counterparts
     443                 :             :  * if they are available. Check the corresponding 32bit function for
     444                 :             :  * documentation.
     445                 :             :  * ----
     446                 :             :  */
     447                 :             : static inline void
     448                 :    15630139 : pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
     449                 :             : {
     450                 :             :     /*
     451                 :             :      * Can't necessarily enforce alignment - and don't need it - when using
     452                 :             :      * the spinlock based fallback implementation. Therefore only assert when
     453                 :             :      * not using it.
     454                 :             :      */
     455                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     456                 :             :     AssertPointerAlignment(ptr, 8);
     457                 :             : #endif
     458                 :    15630139 :     pg_atomic_init_u64_impl(ptr, val);
     459                 :    15630139 : }
     460                 :             : 
     461                 :             : static inline uint64
     462                 :   574455799 : pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
     463                 :             : {
     464                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     465                 :             :     AssertPointerAlignment(ptr, 8);
     466                 :             : #endif
     467                 :   574455799 :     return pg_atomic_read_u64_impl(ptr);
     468                 :             : }
     469                 :             : 
     470                 :             : static inline uint64
     471                 :    11730995 : pg_atomic_read_membarrier_u64(volatile pg_atomic_uint64 *ptr)
     472                 :             : {
     473                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     474                 :             :     AssertPointerAlignment(ptr, 8);
     475                 :             : #endif
     476                 :    11730995 :     return pg_atomic_read_membarrier_u64_impl(ptr);
     477                 :             : }
     478                 :             : 
     479                 :             : static inline void
     480                 :    21199021 : pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
     481                 :             : {
     482                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     483                 :             :     AssertPointerAlignment(ptr, 8);
     484                 :             : #endif
     485                 :    21199021 :     pg_atomic_write_u64_impl(ptr, val);
     486                 :    21199021 : }
     487                 :             : 
     488                 :             : static inline void
     489                 :     5652574 : pg_atomic_unlocked_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
     490                 :             : {
     491                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     492                 :             :     AssertPointerAlignment(ptr, 8);
     493                 :             : #endif
     494                 :             : 
     495                 :     5652574 :     pg_atomic_unlocked_write_u64_impl(ptr, val);
     496                 :     5652574 : }
     497                 :             : 
     498                 :             : static inline void
     499                 :      126767 : pg_atomic_write_membarrier_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
     500                 :             : {
     501                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     502                 :             :     AssertPointerAlignment(ptr, 8);
     503                 :             : #endif
     504                 :      126767 :     pg_atomic_write_membarrier_u64_impl(ptr, val);
     505                 :      126767 : }
     506                 :             : 
     507                 :             : static inline uint64
     508                 :    27523306 : pg_atomic_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 newval)
     509                 :             : {
     510                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     511                 :             :     AssertPointerAlignment(ptr, 8);
     512                 :             : #endif
     513                 :    27523306 :     return pg_atomic_exchange_u64_impl(ptr, newval);
     514                 :             : }
     515                 :             : 
     516                 :             : static inline bool
     517                 :   259851185 : pg_atomic_compare_exchange_u64(volatile pg_atomic_uint64 *ptr,
     518                 :             :                                uint64 *expected, uint64 newval)
     519                 :             : {
     520                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     521                 :             :     AssertPointerAlignment(ptr, 8);
     522                 :             : #endif
     523                 :   259851185 :     return pg_atomic_compare_exchange_u64_impl(ptr, expected, newval);
     524                 :             : }
     525                 :             : 
     526                 :             : static inline uint64
     527                 :      333134 : pg_atomic_fetch_add_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
     528                 :             : {
     529                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     530                 :             :     AssertPointerAlignment(ptr, 8);
     531                 :             : #endif
     532                 :      333134 :     return pg_atomic_fetch_add_u64_impl(ptr, add_);
     533                 :             : }
     534                 :             : 
     535                 :             : static inline uint64
     536                 :    33513049 : pg_atomic_fetch_sub_u64(volatile pg_atomic_uint64 *ptr, int64 sub_)
     537                 :             : {
     538                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     539                 :             :     AssertPointerAlignment(ptr, 8);
     540                 :             : #endif
     541                 :             :     Assert(sub_ != PG_INT64_MIN);
     542                 :    33513049 :     return pg_atomic_fetch_sub_u64_impl(ptr, sub_);
     543                 :             : }
     544                 :             : 
     545                 :             : static inline uint64
     546                 :       22846 : pg_atomic_fetch_and_u64(volatile pg_atomic_uint64 *ptr, uint64 and_)
     547                 :             : {
     548                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     549                 :             :     AssertPointerAlignment(ptr, 8);
     550                 :             : #endif
     551                 :       22846 :     return pg_atomic_fetch_and_u64_impl(ptr, and_);
     552                 :             : }
     553                 :             : 
     554                 :             : static inline uint64
     555                 :    28789228 : pg_atomic_fetch_or_u64(volatile pg_atomic_uint64 *ptr, uint64 or_)
     556                 :             : {
     557                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     558                 :             :     AssertPointerAlignment(ptr, 8);
     559                 :             : #endif
     560                 :    28789228 :     return pg_atomic_fetch_or_u64_impl(ptr, or_);
     561                 :             : }
     562                 :             : 
     563                 :             : static inline uint64
     564                 :         711 : pg_atomic_add_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
     565                 :             : {
     566                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     567                 :             :     AssertPointerAlignment(ptr, 8);
     568                 :             : #endif
     569                 :         711 :     return pg_atomic_add_fetch_u64_impl(ptr, add_);
     570                 :             : }
     571                 :             : 
     572                 :             : static inline uint64
     573                 :   114589778 : pg_atomic_sub_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 sub_)
     574                 :             : {
     575                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     576                 :             :     AssertPointerAlignment(ptr, 8);
     577                 :             : #endif
     578                 :             :     Assert(sub_ != PG_INT64_MIN);
     579                 :   114589778 :     return pg_atomic_sub_fetch_u64_impl(ptr, sub_);
     580                 :             : }
     581                 :             : 
     582                 :             : /*
     583                 :             :  * Monotonically advance the given variable using only atomic operations until
     584                 :             :  * it's at least the target value.  Returns the latest value observed, which
     585                 :             :  * may or may not be the target value.
     586                 :             :  *
     587                 :             :  * Full barrier semantics (even when value is unchanged).
     588                 :             :  */
     589                 :             : static inline uint64
     590                 :      540673 : pg_atomic_monotonic_advance_u64(volatile pg_atomic_uint64 *ptr, uint64 target)
     591                 :             : {
     592                 :             :     uint64      currval;
     593                 :             : 
     594                 :             : #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
     595                 :             :     AssertPointerAlignment(ptr, 8);
     596                 :             : #endif
     597                 :             : 
     598                 :      540673 :     currval = pg_atomic_read_u64_impl(ptr);
     599         [ +  + ]:      540673 :     if (currval >= target)
     600                 :             :     {
     601                 :       98354 :         pg_memory_barrier();
     602                 :       98354 :         return currval;
     603                 :             :     }
     604                 :             : 
     605         [ +  + ]:      442606 :     while (currval < target)
     606                 :             :     {
     607         [ +  + ]:      442320 :         if (pg_atomic_compare_exchange_u64(ptr, &currval, target))
     608                 :      442033 :             return target;
     609                 :             :     }
     610                 :             : 
     611                 :         286 :     return currval;
     612                 :             : }
     613                 :             : 
     614                 :             : #undef INSIDE_ATOMICS_H
     615                 :             : 
     616                 :             : #endif                          /* ATOMICS_H */
        

Generated by: LCOV version 2.0-1