Quelle generic-gcc.h
Sprache: C
/*-------------------------------------------------------------------------
*
* generic - gcc . h
* Atomic operations , implemented using gcc ( or compatible ) intrinsics .
*
* Portions Copyright ( c ) 1996 - 2025 , PostgreSQL Global Development Group
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
* NOTES :
*
* Documentation :
* * Legacy _ _ sync Built - in Functions for Atomic Memory Access
* https : //gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fsync-Builtins.html
* * Built - in functions for memory model aware atomic operations
* https : //gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html
*
* src / include / port / atomics / generic - gcc . h
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/* intentionally no include guards, should only be included by atomics.h */
#ifndef INSIDE_ATOMICS_H
#error "should be included via atomics.h"
#endif
/*
* An empty asm block should be a sufficient compiler barrier .
*/
#define pg_compiler_barrier_impl() __asm__ __volatile__("" ::: "memory" )
/*
* If we ' re on GCC 4 . 1 . 0 or higher , we should be able to get a memory barrier
* out of this compiler built - in . But we prefer to rely on platform specific
* definitions where possible , and use this only as a fallback .
*/
#if !defined (pg_memory_barrier_impl)
# 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_INT32_CAS)
/* acquire semantics include read barrier semantics */
# define pg_read_barrier_impl() do \
{ \
pg_compiler_barrier_impl(); \
__atomic_thread_fence(__ATOMIC_ACQUIRE); \
} while (0 )
#endif
#if !defined (pg_write_barrier_impl) && defined (HAVE_GCC__ATOMIC_INT32_CAS)
/* release semantics include write barrier semantics */
# define pg_write_barrier_impl() do \
{ \
pg_compiler_barrier_impl(); \
__atomic_thread_fence(__ATOMIC_RELEASE); \
} while (0 )
#endif
/* generic gcc based atomic flag implementation */
#if !defined (PG_HAVE_ATOMIC_FLAG_SUPPORT) \
&& (defined (HAVE_GCC__SYNC_INT32_TAS) || defined (HAVE_GCC__SYNC_CHAR_TAS))
#define PG_HAVE_ATOMIC_FLAG_SUPPORT
typedef struct pg_atomic_flag
{
/*
* If we have a choice , use int - width TAS , because that is more efficient
* and / or more reliably implemented on most non - Intel platforms . ( Note
* that this code isn ' t used on x86 [ _ 64 ] ; see arch - x86 . h for that . )
*/
#ifdef HAVE_GCC__SYNC_INT32_TAS
volatile int value;
#else
volatile char value;
#endif
} pg_atomic_flag;
#endif /* !ATOMIC_FLAG_SUPPORT && SYNC_INT32_TAS */
/* generic gcc based atomic uint32 implementation */
#if !defined (PG_HAVE_ATOMIC_U32_SUPPORT) \
&& (defined (HAVE_GCC__ATOMIC_INT32_CAS) || defined (HAVE_GCC__SYNC_INT32_CAS))
#define PG_HAVE_ATOMIC_U32_SUPPORT
typedef struct pg_atomic_uint32
{
volatile uint32 value;
} pg_atomic_uint32;
#endif /* defined(HAVE_GCC__ATOMIC_INT32_CAS) || defined(HAVE_GCC__SYNC_INT32_CAS) */
/* generic gcc based atomic uint64 implementation */
#if !defined (PG_HAVE_ATOMIC_U64_SUPPORT) \
&& !defined (PG_DISABLE_64_BIT_ATOMICS) \
&& (defined (HAVE_GCC__ATOMIC_INT64_CAS) || defined (HAVE_GCC__SYNC_INT64_CAS))
#define PG_HAVE_ATOMIC_U64_SUPPORT
typedef struct pg_atomic_uint64
{
volatile uint64 value pg_attribute_aligned(8 );
} pg_atomic_uint64;
#endif /* defined(HAVE_GCC__ATOMIC_INT64_CAS) || defined(HAVE_GCC__SYNC_INT64_CAS) */
#ifdef PG_HAVE_ATOMIC_FLAG_SUPPORT
#if defined (HAVE_GCC__SYNC_CHAR_TAS) || defined (HAVE_GCC__SYNC_INT32_TAS)
#ifndef PG_HAVE_ATOMIC_TEST_SET_FLAG
#define PG_HAVE_ATOMIC_TEST_SET_FLAG
static inline bool
pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
{
/* NB: only an acquire barrier, not a full one */
/* some platform only support a 1 here */
return __sync_lock_test_and_set(&ptr->value, 1 ) == 0 ;
}
#endif
#endif /* defined(HAVE_GCC__SYNC_*_TAS) */
#ifndef PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
static inline bool
pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
{
return ptr->value == 0 ;
}
#endif
#ifndef PG_HAVE_ATOMIC_CLEAR_FLAG
#define PG_HAVE_ATOMIC_CLEAR_FLAG
static inline void
pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
{
__sync_lock_release(&ptr->value);
}
#endif
#ifndef PG_HAVE_ATOMIC_INIT_FLAG
#define PG_HAVE_ATOMIC_INIT_FLAG
static inline void
pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
{
pg_atomic_clear_flag_impl(ptr);
}
#endif
#endif /* defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) */
/* prefer __atomic, it has a better API */
#if !defined (PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined (HAVE_GCC__ATOMIC_INT32_CAS)
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
static inline bool
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
uint32 *expected, uint32 newval)
{
/* FIXME: we can probably use a lower consistency model */
return __atomic_compare_exchange_n(&ptr->value, expected, newval, false ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
}
#endif
#if !defined (PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined (HAVE_GCC__SYNC_INT32_CAS)
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
static inline bool
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
uint32 *expected, uint32 newval)
{
bool ret;
uint32 current;
current = __sync_val_compare_and_swap(&ptr->value, *expected, newval);
ret = current == *expected;
*expected = current;
return ret;
}
#endif
/*
* _ _ sync_lock_test_and_set ( ) only supports setting the value to 1 on some
* platforms , so we only provide an _ _ atomic implementation for
* pg_atomic_exchange .
*
* We assume the availability of 32 - bit _ _ atomic_compare_exchange_n ( ) implies
* the availability of 32 - bit _ _ atomic_exchange_n ( ) .
*/
#if !defined (PG_HAVE_ATOMIC_EXCHANGE_U32) && defined (HAVE_GCC__ATOMIC_INT32_CAS)
#define PG_HAVE_ATOMIC_EXCHANGE_U32
static inline uint32
pg_atomic_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 newval)
{
return __atomic_exchange_n(&ptr->value, newval, __ATOMIC_SEQ_CST);
}
#endif
/* if we have 32-bit __sync_val_compare_and_swap, assume we have these too: */
#if !defined (PG_HAVE_ATOMIC_FETCH_ADD_U32) && defined (HAVE_GCC__SYNC_INT32_CAS)
#define PG_HAVE_ATOMIC_FETCH_ADD_U32
static inline uint32
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
{
return __sync_fetch_and_add(&ptr->value, add_);
}
#endif
#if !defined (PG_HAVE_ATOMIC_FETCH_SUB_U32) && defined (HAVE_GCC__SYNC_INT32_CAS)
#define PG_HAVE_ATOMIC_FETCH_SUB_U32
static inline uint32
pg_atomic_fetch_sub_u32_impl(volatile pg_atomic_uint32 *ptr, int32 sub_)
{
return __sync_fetch_and_sub(&ptr->value, sub_);
}
#endif
#if !defined (PG_HAVE_ATOMIC_FETCH_AND_U32) && defined (HAVE_GCC__SYNC_INT32_CAS)
#define PG_HAVE_ATOMIC_FETCH_AND_U32
static inline uint32
pg_atomic_fetch_and_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 and_)
{
return __sync_fetch_and_and(&ptr->value, and_);
}
#endif
#if !defined (PG_HAVE_ATOMIC_FETCH_OR_U32) && defined (HAVE_GCC__SYNC_INT32_CAS)
#define PG_HAVE_ATOMIC_FETCH_OR_U32
static inline uint32
pg_atomic_fetch_or_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 or_)
{
return __sync_fetch_and_or(&ptr->value, or_);
}
#endif
#if !defined (PG_DISABLE_64_BIT_ATOMICS)
#if !defined (PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64) && defined (HAVE_GCC__ATOMIC_INT64_CAS)
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
static inline bool
pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
uint64 *expected, uint64 newval)
{
AssertPointerAlignment(expected, 8 );
return __atomic_compare_exchange_n(&ptr->value, expected, newval, false ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
}
#endif
#if !defined (PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64) && defined (HAVE_GCC__SYNC_INT64_CAS)
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
static inline bool
pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
uint64 *expected, uint64 newval)
{
bool ret;
uint64 current;
AssertPointerAlignment(expected, 8 );
current = __sync_val_compare_and_swap(&ptr->value, *expected, newval);
ret = current == *expected;
*expected = current;
return ret;
}
#endif
/*
* _ _ sync_lock_test_and_set ( ) only supports setting the value to 1 on some
* platforms , so we only provide an _ _ atomic implementation for
* pg_atomic_exchange .
*
* We assume the availability of 64 - bit _ _ atomic_compare_exchange_n ( ) implies
* the availability of 64 - bit _ _ atomic_exchange_n ( ) .
*/
#if !defined (PG_HAVE_ATOMIC_EXCHANGE_U64) && defined (HAVE_GCC__ATOMIC_INT64_CAS)
#define PG_HAVE_ATOMIC_EXCHANGE_U64
static inline uint64
pg_atomic_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 newval)
{
return __atomic_exchange_n(&ptr->value, newval, __ATOMIC_SEQ_CST);
}
#endif
/* if we have 64-bit __sync_val_compare_and_swap, assume we have these too: */
#if !defined (PG_HAVE_ATOMIC_FETCH_ADD_U64) && defined (HAVE_GCC__SYNC_INT64_CAS)
#define PG_HAVE_ATOMIC_FETCH_ADD_U64
static inline uint64
pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
{
return __sync_fetch_and_add(&ptr->value, add_);
}
#endif
#if !defined (PG_HAVE_ATOMIC_FETCH_SUB_U64) && defined (HAVE_GCC__SYNC_INT64_CAS)
#define PG_HAVE_ATOMIC_FETCH_SUB_U64
static inline uint64
pg_atomic_fetch_sub_u64_impl(volatile pg_atomic_uint64 *ptr, int64 sub_)
{
return __sync_fetch_and_sub(&ptr->value, sub_);
}
#endif
#if !defined (PG_HAVE_ATOMIC_FETCH_AND_U64) && defined (HAVE_GCC__SYNC_INT64_CAS)
#define PG_HAVE_ATOMIC_FETCH_AND_U64
static inline uint64
pg_atomic_fetch_and_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 and_)
{
return __sync_fetch_and_and(&ptr->value, and_);
}
#endif
#if !defined (PG_HAVE_ATOMIC_FETCH_OR_U64) && defined (HAVE_GCC__SYNC_INT64_CAS)
#define PG_HAVE_ATOMIC_FETCH_OR_U64
static inline uint64
pg_atomic_fetch_or_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 or_)
{
return __sync_fetch_and_or(&ptr->value, or_);
}
#endif
#endif /* !defined(PG_DISABLE_64_BIT_ATOMICS) */
Messung V0.5 in Prozent C=83 H=96 G=89
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland
2026-08-25
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=277311
#Domains=752002