/* * (c) Copyright, Real-Time Innovations, 2024. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef osapi_atomic_h #define osapi_atomic_h /** * @brief This header implements macros to perform atomic operations for all RTI * supported platforms by using C11 Atomics, GCC built-in atomic support, * Windows atomic intrinsics. * @see https://en.cppreference.com/w/c/atomic for reference on C11 Atomics. * @see * https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins * for reference on GCC built-in atomic support. * @see * https://learn.microsoft.com/en-us/cpp/intrinsics/intrinsics-available-on-all-architectures?view=msvc-140 * for reference on Windows atomic intrinsics. */ /* * Check if the compiler supports C11 Atomics. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ && !defined(__STDC_NO_ATOMICS__) #define RTI_C11_ATOMIC_PRIMITIVES_ARE_SUPPORTED #endif /* * Check if GCC's built-in atomic support is available (GCC >= 4.7). */ #if defined(__GNUC__) \ && (__GNUC__ >= 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) #define RTI_GCC_ATOMIC_PRIMITIVES_ARE_SUPPORTED #endif /* * Check if Windows' atomic intrinsics are available (VS2012 or higher) */ #if defined(_MSC_VER) && _MSC_VER >= 1700 #define RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED #endif /* * PURIFY_ATOMIC_OPERATIONS introduces the atomic variables in an anonymous * struct to avoid using regular operations over atomic variables. The option is * only enabled with PURIFY_TEST so it is not used in production, and it is * disabled when ThreadSanitizer is enabled to allow annotations over atomic * variables. */ #if defined(PURIFY_TEST) && !defined(RTI_THREAD_SANITIZER_IS_ENABLED) #define PURIFY_ATOMIC_OPERATIONS #endif #if defined(RTI_C11_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #include #endif #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #include #endif #include "osapi/osapi_dll.h" #include "osapi/osapi_type.h" #include "osapi/osapi_heap.h" #ifdef __cplusplus extern "C" { #endif /** * @brief The memory order for memory barriers and atomic operations. * @details There are five options of memory barrier to choose: * - Relaxed: no ordering constraints. * - Acquire: a load operation with this memory order performs the acquire * operation on the affected memory location: no reads or writes in the * current thread can be reordered before this load. All writes in other * threads that release the same atomic variable are visible in the current * thread. * - Release: a store operation with this memory order performs the release * operation: no reads or writes in the current thread can be reordered after * this store. All writes in the current thread are visible in other threads * that acquire the same atomic variable (see Release-Acquire ordering below) * and writes that carry a dependency into the atomic variable become visible * in other threads that consume the same atomic. * - Acquire-release: A read-modify-write operation with this memory order is * both an acquire operation and a release operation. No memory reads or * writes in the current thread can be reordered before the load, nor after * the store. All writes in other threads that release the same atomic * variable are visible before the modification and the modification is * visible in other threads that acquire the same atomic variable. * - Sequentially consistent: acquire-release memory barrier + all memory * modifications before the barrier are ensured to be visible in all threads. * * Using these options in atomic operations allows three kind of approaches for * memory ordering synchronization between threads: * - Relaxed: no ordering constraints, only atomicity is guaranteed. * - Acquire-release: all memory accesses (included non-atomic and relaxed * atomic) before an atomic store tagged release are guaranteed to happen * before an atomic load (in the same memory address) tagged acquire. This * affects only to the involved threads, and no ordering is guaranteed between * other threads. * - Sequentially consistent: all memory accesses (included non-atomic and all * atomic) are guaranteed to happen in a single total order, and this order * is the same for all threads. * * Note we are ignoring consume memory order since most of the compilers have * reported that they cannot implement it safely so, since it is mostly the * acquire, we avoid using it. * @see https://en.cppreference.com/w/c/atomic/memory_order for reference. */ typedef RTI_INT32 RTIOsapiAtomic_memoryOrder; #if defined(RTI_C11_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED memory_order_relaxed #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE memory_order_acquire #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE memory_order_release #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE_RELEASE memory_order_acq_rel #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT memory_order_seq_cst #elif defined(RTI_GCC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED __ATOMIC_RELAXED #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE __ATOMIC_ACQUIRE #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE __ATOMIC_RELEASE #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE_RELEASE __ATOMIC_ACQ_REL #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT __ATOMIC_SEQ_CST #else #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED 0 #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE 1 #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE 2 #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE_RELEASE 3 #define RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT 4 #endif /** * @brief Establishes memory synchronization ordering of non-atomic and relaxed * atomic accesses, ensuring at least the memory order constraints specified by * the memoryOrder__ argument. * @param memoryOrder__ \b In. The memory order constraints to be established. */ RTIOsapiDllExport void RTIOsapiAtomic_memoryBarrier( RTIOsapiAtomic_memoryOrder memoryOrder); /** * @brief Declare a variable of type type__ as atomic. * @details This variable cannot be initialized directly but using * RTIOsapiAtomic_initialize. */ #if defined(PURIFY_ATOMIC_OPERATIONS) /* * Define atomic types as an struct in malloc plan (non-production build) so * we do not mix atomic and non-atomic operations. */ #if defined(RTI_C11_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTI_ATOMIC(type__) \ struct { \ _Atomic(type__) value; \ } #elif defined(RTI_GCC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) \ || defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTI_ATOMIC(type__) \ struct { \ type__ value; \ } #else #error "No atomic primitives are supported" #endif #else #if defined(RTI_C11_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTI_ATOMIC(type__) _Atomic(type__) #elif defined(RTI_GCC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) \ || defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTI_ATOMIC(type__) type__ #else #error "No atomic primitives are supported" #endif #endif /** * @brief Initializes an atomic variable, perform a non-atomic store. * @param var__ \b In. A pointer to the variable to be initialized. * @param value__ \b In. The value to initialize the variable with. * @details Note that this operation is not thread-safe, it is not an atomic * operation. This operation is needed because an atomic object can contain more * fields than the underlying type to make atomicity and synchronization work, * and this API ensures the correct initialization of these other fields. This * is mandatory only for variables with automatic storage duration, since static * or thread-local storage duration variables are guaranteed to be initialized * in a valid state with the default (zero) initialization. * Note this is also a way to perform a non-atomic store operation. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_initialize(var__, value__) \ RTIOsapiAtomic_initializeI(&(var__)->value, value__) #else #define RTIOsapiAtomic_initialize(var__, value__) \ RTIOsapiAtomic_initializeI(var__, value__) #endif /** * @brief Placeholder initializer to allow structs with atomic types to be * initialized with compound literal initializers. As this is only a * placeholder, RTIOsapiAtomic_initialize SHALL be called to initialize all * atomic variables in the struct. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTI_OSAPI_ATOMIC_LITERAL_PLACEHOLDER(value__) \ { \ value__ \ } #else #define RTI_OSAPI_ATOMIC_LITERAL_PLACEHOLDER(value__) (value__) #endif /**************************** Atomic add operation ****************************/ /** * @brief Atomically adds value__ to the 8 bits (RTI_UINT8 or RTI_INT8) variable * pointed by var__. * @param var__ \b In/Out. The pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be added. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_add8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_add8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add8I(var__, value__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_add8. It should be used * whenever the return value is used in an operation. * @details Signed chars needs to be casted to unsigned before convert to a * larger type. See SEI CERT STR34-C rule for more details. This is a problem in * Windows where, even if atomic APIs can be used for both unsigned and signed * types, they accept only signed types (the sign is ignore). When the return * value of an atomic operation over an unsigned char is compare against another * unsigned char, it is considered as a signed char - unsigned char comparison, * and a integer promotion is performed. It breaks the STR34-C rule, since the * signed char is promoted to a larger size directly. * * @see RTIOsapiAtomic_add8 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_add8u(var__, value__, memoryOrder__) \ ((RTI_UINT8) RTIOsapiAtomic_add8(var__, value__, memoryOrder__)) #else #define RTIOsapiAtomic_add8u(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add8(var__, value__, memoryOrder__) #endif /** * @brief Atomically adds value__ to the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__. * @param var__ \b In/Out. The pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be added. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_add16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_add16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add16I(var__, value__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_add16. It should be used * whenever the return value is used in an operation. * @details On Windows, even if atomic APIs can be used for both unsigned and * signed types, they accept only signed types (the sign is ignored). When the * return value of an atomic operation over an unsigned short is compared * against another unsigned short, it is treated as a signed short - unsigned * short comparison, and integer promotion is performed. The signed short is * promoted to a larger signed integer, causing sign-extension for values with * bit 15 set (i.e., any value >= 32768). This breaks SEI CERT INT02-C and can * cause the comparison to yield incorrect results. * * @see RTIOsapiAtomic_add16 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_add16u(var__, value__, memoryOrder__) \ ((RTI_UINT16) RTIOsapiAtomic_add16(var__, value__, memoryOrder__)) #else #define RTIOsapiAtomic_add16u(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add16(var__, value__, memoryOrder__) #endif /** * @brief Atomically adds value__ to the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__. * @param var__ \b In/Out. The pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be added. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_add32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_add32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically adds value__ to the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__. * @param var__ \b In/Out. The pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be added. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_add64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_add64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_add64I(var__, value__, memoryOrder__) #endif /** * @brief Atomically adds value__ to the pointer pointed by var__. * @param var__ \b In/Out. The pointer to the pointer to be modified. Cannot be * NULL. * @param type__ \b In. The type of the pointer to be modified. * @param value__ \b In. The value to be added. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_addPtr(var__, type__, value__, memoryOrder__) \ RTIOsapiAtomic_addPtrI(&(var__)->value, type__, value__, memoryOrder__) #else #define RTIOsapiAtomic_addPtr(var__, type__, value__, memoryOrder__) \ RTIOsapiAtomic_addPtrI(var__, type__, value__, memoryOrder__) #endif /**************************** Atomic sub operation ****************************/ /** * @brief Atomically subtract value__ to the 8 bits (RTI_UINT8 or RTI_INT8) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be subtract. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_sub8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_sub8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub8I(var__, value__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_sub8. It should be used * whenever the return value is used in an operation. * @details Signed chars needs to be casted to unsigned before convert to a * larger type. See SEI CERT STR34-C rule for more details. This is a problem in * Windows where, even if atomic APIs can be used for both unsigned and signed * types, they accept only signed types (the sign is ignore). When the return * value of an atomic operation over an unsigned char is compare against another * unsigned char, it is considered as a signed char - unsigned char comparison, * and a integer promotion is performed. It breaks the STR34-C rule, since the * signed char is promoted to a larger size directly. * * @see RTIOsapiAtomic_sub8 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_sub8u(var__, value__, memoryOrder__) \ ((RTI_UINT8) RTIOsapiAtomic_sub8(var__, value__, memoryOrder__)) #else #define RTIOsapiAtomic_sub8u(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub8(var__, value__, memoryOrder__) #endif /** * @brief Atomically subtract value__ to the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be subtract. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_sub16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_sub16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub16I(var__, value__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_sub16. It should be used * whenever the return value is used in an operation. * @details On Windows, even if atomic APIs can be used for both unsigned and * signed types, they accept only signed types (the sign is ignored). When the * return value of an atomic operation over an unsigned short is compared * against another unsigned short, it is treated as a signed short - unsigned * short comparison, and integer promotion is performed. The signed short is * promoted to a larger signed integer, causing sign-extension for values with * bit 15 set (i.e., any value >= 32768). This breaks SEI CERT INT02-C and can * cause the comparison to yield incorrect results. * * @see RTIOsapiAtomic_sub16 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_sub16u(var__, value__, memoryOrder__) \ ((RTI_UINT16) RTIOsapiAtomic_sub16(var__, value__, memoryOrder__)) #else #define RTIOsapiAtomic_sub16u(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub16(var__, value__, memoryOrder__) #endif /** * @brief Atomically subtract value__ to the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be subtract. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_sub32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_sub32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically subtract value__ to the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be subtract. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_sub64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_sub64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_sub64I(var__, value__, memoryOrder__) #endif /** * @brief Atomically subtract value__ to pointer pointed by var__. * @param var__ \b In/Out. A pointer to the pointer to be modified. Cannot be * NULL. * @param type__ \b In. The type of the pointer to be modified. * @param value__ \b In. The value to be subtract. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_subPtr(var__, type__, value__, memoryOrder__) \ RTIOsapiAtomic_subPtrI(&(var__)->value, type__, value__, memoryOrder__) #else #define RTIOsapiAtomic_subPtr(var__, type__, value__, memoryOrder__) \ RTIOsapiAtomic_subPtrI(var__, type__, value__, memoryOrder__) #endif /*************************** Atomic store operation ***************************/ /** * @brief Atomically store value__ to the 8 bits (RTI_UINT8 or RTI_INT8) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. * Cannot be NULL. * @param value__ \b In. The value to be stored. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_store8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_store8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store8I(var__, value__, memoryOrder__) #endif /** * @brief Atomically store value__ to the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. * Cannot be NULL. * @param value__ \b In. The value to be stored. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_store16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_store16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store16I(var__, value__, memoryOrder__) #endif /** * @brief Atomically store value__ to the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. * Cannot be NULL. * @param value__ \b In. The value to be stored. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_store32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_store32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically store value__ to the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. * Cannot be NULL. * @param value__ \b In. The value to be stored. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_store64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_store64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_store64I(var__, value__, memoryOrder__) #endif /** * @brief Atomically store the pointer value__ to the pointer-to-pointer var__. * @param var__ \b In/Out. A pointer to the pointer to be modified. Cannot be * NULL. * @param value__ \b In. The value to be stored. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELEASE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_storePtr(var__, value__, memoryOrder__) \ RTIOsapiAtomic_storePtrI(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_storePtr(var__, value__, memoryOrder__) \ RTIOsapiAtomic_storePtrI(var__, value__, memoryOrder__) #endif /*************************** Atomic load operation ****************************/ /** * @brief Atomically load the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable pointed by var__. Cannot be NULL. * @param var__ \b In. A pointer to the variable to load from. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. * @return The value loaded from var__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_load8(var__, memoryOrder__) \ RTIOsapiAtomic_load8I(&(var__)->value, memoryOrder__) #else #define RTIOsapiAtomic_load8(var__, memoryOrder__) \ RTIOsapiAtomic_load8I(var__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_load8. It should be used * whenever the return value is used in an operation. * @details Signed chars needs to be casted to unsigned before convert to a * larger type. See SEI CERT STR34-C rule for more details. This is a problem in * Windows where, even if atomic APIs can be used for both unsigned and signed * types, they accept only signed types (the sign is ignore). When the return * value of an atomic operation over an unsigned char is compare against another * unsigned char, it is considered as a signed char - unsigned char comparison, * and a integer promotion is performed. It breaks the STR34-C rule, since the * signed char is promoted to a larger size directly. * * @see RTIOsapiAtomic_load8 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_load8u(var__, memoryOrder__) \ ((RTI_UINT8) RTIOsapiAtomic_load8(var__, memoryOrder__)) #else #define RTIOsapiAtomic_load8u(var__, memoryOrder__) \ RTIOsapiAtomic_load8(var__, memoryOrder__) #endif /** * @brief Atomically load the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__. Cannot be NULL. * @param var__ \b In. A pointer to the variable to load from. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. * @return The value loaded from var__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_load16(var__, memoryOrder__) \ RTIOsapiAtomic_load16I(&(var__)->value, memoryOrder__) #else #define RTIOsapiAtomic_load16(var__, memoryOrder__) \ RTIOsapiAtomic_load16I(var__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_load16. It should be used * whenever the return value is used in an operation. * @details On Windows, even if atomic APIs can be used for both unsigned and * signed types, they accept only signed types (the sign is ignored). When the * return value of an atomic operation over an unsigned short is compared * against another unsigned short, it is treated as a signed short - unsigned * short comparison, and integer promotion is performed. The signed short is * promoted to a larger signed integer, causing sign-extension for values with * bit 15 set (i.e., any value >= 32768). This breaks SEI CERT INT02-C and can * cause the comparison to yield incorrect results. * * @see RTIOsapiAtomic_load16 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_load16u(var__, memoryOrder__) \ ((RTI_UINT16) RTIOsapiAtomic_load16(var__, memoryOrder__)) #else #define RTIOsapiAtomic_load16u(var__, memoryOrder__) \ RTIOsapiAtomic_load16(var__, memoryOrder__) #endif /** * @brief Atomically load the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__. Cannot be NULL. * @param var__ \b In. A pointer to the variable to load from. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. * @return The value loaded from var__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_load32(var__, memoryOrder__) \ RTIOsapiAtomic_load32I(&(var__)->value, memoryOrder__) #else #define RTIOsapiAtomic_load32(var__, memoryOrder__) \ RTIOsapiAtomic_load32I(var__, memoryOrder__) #endif /** * @brief Atomically load the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__. Cannot be NULL. * @param var__ \b In. A pointer to the variable to load from. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. * @return The value loaded from var__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_load64(var__, memoryOrder__) \ RTIOsapiAtomic_load64I(&(var__)->value, memoryOrder__) #else #define RTIOsapiAtomic_load64(var__, memoryOrder__) \ RTIOsapiAtomic_load64I(var__, memoryOrder__) #endif /** * @brief Atomically load the pointer pointed by var__. Cannot be NULL. * @param type__ \b In. The type of the pointer to be modified. * @param var__ \b In. A pointer to the pointer to load. * @param memoryOrder__ \b In. The memory order constraints to be established. * Only RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, * RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, and * RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. * @return The pointer loaded from var__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_loadPtr(var__, type__, memoryOrder__) \ RTIOsapiAtomic_loadPtrI(&(var__)->value, type__, memoryOrder__) #else #define RTIOsapiAtomic_loadPtr(var__, type__, memoryOrder__) \ RTIOsapiAtomic_loadPtrI(var__, type__, memoryOrder__) #endif /*************************** Atomic exchange operation ************************/ /** * @brief Atomically exchange the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable pointed by var__ with value__ and returns the value previously hold * by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be exchanged. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_exchange8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_exchange8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange8I(var__, value__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_exchange8. It should be used * whenever the return value is used in an operation. * @details Signed chars needs to be casted to unsigned before convert to a * larger type. See SEI CERT STR34-C rule for more details. This is a problem in * Windows where, even if atomic APIs can be used for both unsigned and signed * types, they accept only signed types (the sign is ignore). When the return * value of an atomic operation over an unsigned char is compare against another * unsigned char, it is considered as a signed char - unsigned char comparison, * and a integer promotion is performed. It breaks the STR34-C rule, since the * signed char is promoted to a larger size directly. * * @see RTIOsapiAtomic_exchange8 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_exchange8u(var__, value__, memoryOrder__) \ ((RTI_UINT8) RTIOsapiAtomic_exchange8(var__, value__, memoryOrder__)) #else #define RTIOsapiAtomic_exchange8u(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange8(var__, value__, memoryOrder__) #endif /** * @brief Atomically exchange the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__ with value__ and returns the value previously hold * by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be exchanged. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_exchange16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_exchange16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange16I(var__, value__, memoryOrder__) #endif /** * @brief The unsigned version of RTIOsapiAtomic_exchange16. It should be used * whenever the return value is used in an operation. * @details On Windows, even if atomic APIs can be used for both unsigned and * signed types, they accept only signed types (the sign is ignored). When the * return value of an atomic operation over an unsigned short is compared * against another unsigned short, it is treated as a signed short - unsigned * short comparison, and integer promotion is performed. The signed short is * promoted to a larger signed integer, causing sign-extension for values with * bit 15 set (i.e., any value >= 32768). This breaks SEI CERT INT02-C and can * cause the comparison to yield incorrect results. For example, any UDP port >= * 32768 (including all ephemeral ports 49152-65535) will trigger a spurious * false inequality when its exchanged value is compared against the original. * * @see RTIOsapiAtomic_exchange16 */ #if defined(RTI_MSVC_ATOMIC_PRIMITIVES_ARE_SUPPORTED) #define RTIOsapiAtomic_exchange16u(var__, value__, memoryOrder__) \ ((RTI_UINT16) RTIOsapiAtomic_exchange16(var__, value__, memoryOrder__)) #else #define RTIOsapiAtomic_exchange16u(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange16(var__, value__, memoryOrder__) #endif /** * @brief Atomically exchange the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__ with value__ and returns the value previously hold * by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be exchanged. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_exchange32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_exchange32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically exchange the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__ with value__ and returns the value previously hold * by var__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to be exchanged. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_exchange64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_exchange64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_exchange64I(var__, value__, memoryOrder__) #endif /** * @brief Atomically exchange the pointer pointed by var__ with value__ and * returns the value previously hold by var__. * @param var__ \b In/Out. A pointer to the pointer to be modified. Cannot be * NULL. * @param type__ \b In. The type of the pointer to be modified. * @param value__ \b In. The value to be exchanged. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_exchangePtr(var__, type__, value__, memoryOrder__) \ RTIOsapiAtomic_exchangePtrI( \ &(var__)->value, \ type__, \ value__, \ memoryOrder__) #else #define RTIOsapiAtomic_exchangePtr(var__, type__, value__, memoryOrder__) \ RTIOsapiAtomic_exchangePtrI(var__, type__, value__, memoryOrder__) #endif /*************************** Atomic compare-exchange operation ****************/ /** * @brief Atomically compare the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Weak means that the operation * may fail spuriously, but the operation will not block if the value of var__ * is not in cache. Because of that, this API shall be always used within a loop * (see SEI CERT CON41-C). * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeWeak8( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak8I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeWeak8( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak8I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Weak means that the operation * may fail spuriously, but the operation will not block if the value of var__ * is not in cache. Because of that, this API shall be always used within a loop * (see SEI CERT CON41-C). * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeWeak16( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak16I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeWeak16( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak16I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Weak means that the operation * may fail spuriously, but the operation will not block if the value of var__ * is not in cache. Because of that, this API shall be always used within a loop * (see SEI CERT CON41-C). * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeWeak32( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak32I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeWeak32( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak32I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__.Weak means that the operation * may fail spuriously, but the operation will not block if the value of var__ * is not in cache. Because of that, this API shall be always used within a loop * (see SEI CERT CON41-C). * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. The variable to compare with. * @param desired__ \b In. A pointer to the value to store if the comparison is * successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeWeak64( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak64I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeWeak64( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeak64I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the pointer pointed by var__ with expected__ and if * equal, store desired__ in var__. If not equal, store var__ in expected__. * Weak means that the operation may fail spuriously, but the operation will not * block if the value of var__ is not in cache. Because of that, this API shall * be always used within a loop (see SEI CERT CON41-C). * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeWeakPtr( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeakPtrI( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeWeakPtr( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeWeakPtrI( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Strong means that the * operation will not fail spuriously, but the operation will block until the * value of var__ is in cache. If you are using this API within a loop, consider * the weak version. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeStrong8( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong8I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeStrong8( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong8I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Strong means that the * operation will not fail spuriously, but the operation will block until the * value of var__ is in cache. If you are using this API within a loop, consider * the weak version. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeStrong16( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong16I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeStrong16( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong16I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Strong means that the * operation will not fail spuriously, but the operation will block until the * value of var__ is in cache. If you are using this API within a loop, consider * the weak version. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeStrong32( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong32I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeStrong32( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong32I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable pointed by var__ with expected__ and if equal, store desired__ in * var__. If not equal, store var__ in expected__. Strong means that the * operation will not fail spuriously, but the operation will block until the * value of var__ is in cache. If you are using this API within a loop, consider * the weak version. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeStrong64( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong64I( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeStrong64( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrong64I( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /** * @brief Atomically compare the pointer pointed by var__ with expected__ and if * equal, store desired__ in var__. If not equal, store var__ in expected__. * Strong means that the operation will not fail spuriously, but the operation * will block until the value of var__ is in cache. If you are using this API * within a loop, consider the weak version. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param expected__ \b In. A pointer to the variable to compare with. * @param desired__ \b In. The value to store if the comparison is successful. * @param memoryOrderSuccess__ \b In. The memory order constraints to be * established when operation success (read-modify-write operation over var__). * All memory orderings are allowed. * @param memoryOrderFail__ \b In. The memory order constraints to be * established when operation fails (only read var__). Only * RTI_OSAPI_ATOMIC_MEMORY_ORDER_RELAXED, RTI_OSAPI_ATOMIC_MEMORY_ORDER_ACQUIRE, * and RTI_OSAPI_ATOMIC_MEMORY_ORDER_SEQ_CONSISTENT are allowed. Cannot specify * an stronger memory order than memoryOrderSuccess__. * @return RTI_TRUE if the operation succeed and desired__ has been copied to * var__, RTI_FALSE when the operation failed and var__ has been copied to * expected__. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_compareExchangeStrongPtr( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrongPtrI( \ &(var__)->value, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #else #define RTIOsapiAtomic_compareExchangeStrongPtr( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) \ RTIOsapiAtomic_compareExchangeStrongPtrI( \ var__, \ expected__, \ desired__, \ memoryOrderSuccess__, \ memoryOrderFail__) #endif /*********************** Atomic fetch-and-or operation ************************/ /** * @brief Atomically replaces the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable var__ with the result of bitwise OR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to OR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_or8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_or8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or8I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable var__ with the result of bitwise OR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to OR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_or16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_or16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or16I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable var__ with the result of bitwise OR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to OR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_or32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_or32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable var__ with the result of bitwise OR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to OR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_or64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_or64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_or64I(var__, value__, memoryOrder__) #endif /*********************** Atomic fetch-and-xor operation ***********************/ /** * @brief Atomically replaces the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable var__ with the result of bitwise XOR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to XOR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_xor8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_xor8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor8I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable var__ with the result of bitwise XOR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to XOR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_xor16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_xor16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor16I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable var__ with the result of bitwise XOR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to XOR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_xor32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_xor32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable var__ with the result of bitwise XOR between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to XOR with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_xor64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_xor64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_xor64I(var__, value__, memoryOrder__) #endif /*********************** Atomic fetch-and-and operation ***********************/ /** * @brief Atomically replaces the value of the 8 bits (RTI_UINT8 or RTI_INT8) * variable var__ with the result of bitwise AND between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to AND with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_and8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and8I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_and8(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and8I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 16 bits (RTI_UINT16 or RTI_INT16) * variable var__ with the result of bitwise AND between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to AND with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_and16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and16I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_and16(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and16I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 32 bits (RTI_UINT32 or RTI_INT32) * variable var__ with the result of bitwise AND between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to AND with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_and32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and32I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_and32(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and32I(var__, value__, memoryOrder__) #endif /** * @brief Atomically replaces the value of the 64 bits (RTI_UINT64 or RTI_INT64) * variable var__ with the result of bitwise AND between the old value of var__ * and value__. * @param var__ \b In/Out. A pointer to the variable to be modified. Cannot be * NULL. * @param value__ \b In. The value to AND with the value pointed by var__. * @param memoryOrder__ \b In. The memory order constraints to be established. * All memory orderings are allowed. * @return The value held previously by the atomic object. */ #if defined(PURIFY_ATOMIC_OPERATIONS) #define RTIOsapiAtomic_and64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and64I(&(var__)->value, value__, memoryOrder__) #else #define RTIOsapiAtomic_and64(var__, value__, memoryOrder__) \ RTIOsapiAtomic_and64I(var__, value__, memoryOrder__) #endif #ifdef __cplusplus } /* extern "C" */ #endif #include "osapi/osapi_atomic_impl.h" #endif /* osapi_atomic_h */