247 lines
8.0 KiB
C
247 lines
8.0 KiB
C
// Copyright(c) 2006 to 2019 ZettaScale Technology and others
|
|
//
|
|
// This program and the accompanying materials are made available under the
|
|
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
// http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
|
// v. 1.0 which is available at
|
|
// http://www.eclipse.org/org/documents/edl-v10.php.
|
|
//
|
|
// SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
|
|
|
#ifndef DDSRT_ATOMICS_H
|
|
#define DDSRT_ATOMICS_H
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "dds/export.h"
|
|
#include "dds/ddsrt/arch.h"
|
|
#include "dds/ddsrt/endian.h"
|
|
#include "dds/ddsrt/types.h"
|
|
|
|
/**
|
|
* @file atomics.h
|
|
* @brief Contains functions and types for atomic operations on various types
|
|
*
|
|
* This header file declares functions and types for atomic operations on uint32_t,
|
|
* uint64_t, uintptr_t, and void* types.
|
|
*
|
|
* 64-bit atomics are not supported by all hardware, but it would be a shame not to use them when
|
|
* they are available. That necessitates an alternative implementation when they are not, either in
|
|
* the form of a different implementation where it is used, or as an emulation using a mutex in
|
|
* ddsrt. It seems that the places where they'd be used end up adding a mutex, so an emulation in
|
|
* ddsrt while being able to check whether it is supported by hardware is a sensible approach.
|
|
*/
|
|
|
|
#if defined (__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief Types on which atomic operations are defined.
|
|
*
|
|
* @note 64-bit types are defined even if atomic operations on them are not
|
|
* really supported.
|
|
*/
|
|
typedef struct { uint32_t v; } ddsrt_atomic_uint32_t; /**< Type for atomic operations on uint32_t */
|
|
typedef struct { uint64_t v; } ddsrt_atomic_uint64_t; /**< Type for atomic operations on uint64_t */
|
|
typedef struct { uintptr_t v; } ddsrt_atomic_uintptr_t; /**< Type for atomic operations on uintptr_t */
|
|
typedef ddsrt_atomic_uintptr_t ddsrt_atomic_voidp_t; /**< Convenience type for atomic operations on void pointers */
|
|
|
|
#if DDSRT_64BIT
|
|
# define DDSRT_HAVE_ATOMIC64 1
|
|
#endif
|
|
|
|
/**
|
|
* @brief Initializers for the types on which atomic operations are defined.
|
|
*/
|
|
#define DDSRT_ATOMIC_UINT32_INIT(v) { (v) } /**< Initializer for ddsrt_atomic_uint32_t */
|
|
#define DDSRT_ATOMIC_UINT64_INIT(v) { (v) } /**< Initializer for ddsrt_atomic_uint64_t */
|
|
#define DDSRT_ATOMIC_UINTPTR_INIT(v) { (v) } /**< Initializer for ddsrt_atomic_uintptr_t */
|
|
#define DDSRT_ATOMIC_VOIDP_INIT(v) { (uintptr_t) (v) } /**< Initializer for ddsrt_atomic_voidp_t */
|
|
|
|
|
|
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40100
|
|
#include "dds/ddsrt/atomics/gcc.h"
|
|
#elif defined(_WIN32)
|
|
#include "dds/ddsrt/atomics/msvc.h"
|
|
#elif defined(__sun)
|
|
#include "dds/ddsrt/atomics/sun.h"
|
|
#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
|
|
#include "dds/ddsrt/atomics/arm.h"
|
|
#else
|
|
#error "Atomic operations are not supported"
|
|
#endif
|
|
|
|
#if ! DDSRT_HAVE_ATOMIC64
|
|
|
|
/**
|
|
* @brief Fetch the value of a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in] x Pointer to the variable to fetch the value of
|
|
*
|
|
* @return The value of the fetched variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x);
|
|
|
|
/**
|
|
* @brief Assign a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[out] x Pointer to the variable to update
|
|
* @param[in] v The new value to assign to the variable
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Increment (by one) a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in,out] x Pointer to the variable to increment
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x);
|
|
|
|
/**
|
|
* @brief Increment (by one) a 64-bit unsigned integer atomically and return its new value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to increment
|
|
*
|
|
* @return The new value of the incremented variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x);
|
|
|
|
/**
|
|
* @brief Decrement (by one) a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in,out] x Pointer to the variable to decrement
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x);
|
|
|
|
/**
|
|
* @brief Decrement (by one) a 64-bit unsigned integer atomically and return its new value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to increment
|
|
*
|
|
* @return The new value of the decremented variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x);
|
|
|
|
/**
|
|
* @brief Increment (by given amount) a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in,out] x Pointer to the variable to increment
|
|
* @param[in] v The value to increment by
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Increment (by given amount) a 64-bit unsigned integer atomically and return its new value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to increment
|
|
* @param[in] v The value to increment by
|
|
*
|
|
* @return The new value of the incremented variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Decrement (by given amount) a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in,out] x Pointer to the variable to decrement
|
|
* @param[in] v The value to decrement by
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Decrement (by given amount) a 64-bit unsigned integer atomically and return its new value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to decrement
|
|
* @param[in] v The value to decrement by
|
|
*
|
|
* @return The new value of the decremented variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Bitwise AND a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in,out] x Pointer to the variable to AND
|
|
* @param[in] v The value to AND with the variable
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Bitwise AND a 64-bit unsigned integer atomically and return the old value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to AND
|
|
* @param[in] v The value to AND with the variable
|
|
*
|
|
* @return The old value of the ANDed variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Bitwise AND a 64-bit unsigned integer atomically and return the new value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to AND
|
|
* @param[in] v The value to AND with the variable
|
|
*
|
|
* @return The new value of the ANDed variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Bitwise OR a 64-bit unsigned integer atomically
|
|
*
|
|
* @param[in,out] x Pointer to the variable to OR
|
|
* @param[in] v The value to OR with the variable
|
|
*/
|
|
DDS_EXPORT void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Bitwise OR a 64-bit unsigned integer atomically and return the old value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to OR
|
|
* @param[in] v The value to OR with the variable
|
|
*
|
|
* @return The old value of the ORed variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Bitwise OR a 64-bit unsigned integer atomically and return the new value
|
|
*
|
|
* @param[in,out] x Pointer to the variable to OR
|
|
* @param[in] v The value to OR with the variable
|
|
*
|
|
* @return The new value of the ORed variable
|
|
*/
|
|
DDS_EXPORT uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
|
|
|
/**
|
|
* @brief Compare and swap a 64-bit unsigned integer atomically
|
|
*
|
|
* Assigns des to x iff x == exp
|
|
*
|
|
* @param[in,out] x Pointer to the variable whose value to swap
|
|
* @param[in] exp the value to test x for
|
|
* @param[in] des the value to assign to the variable
|
|
*
|
|
* @return int meant to be interpreted as bool (swapped: 1; not swapped: 0)
|
|
*/
|
|
DDS_EXPORT int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des);
|
|
#endif
|
|
|
|
/**
|
|
* @brief Initialize mutexes for atomics
|
|
*/
|
|
void ddsrt_atomics_init (void);
|
|
|
|
/**
|
|
* @brief Destroy mutexes for atomics
|
|
*/
|
|
void ddsrt_atomics_fini (void);
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif /* DDSRT_ATOMICS_H */
|