aboutsummaryrefslogtreecommitdiff
path: root/include/odp/api/spec/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/odp/api/spec/atomic.h')
-rw-r--r--include/odp/api/spec/atomic.h177
1 files changed, 153 insertions, 24 deletions
diff --git a/include/odp/api/spec/atomic.h b/include/odp/api/spec/atomic.h
index 408829df2..3a098ead1 100644
--- a/include/odp/api/spec/atomic.h
+++ b/include/odp/api/spec/atomic.h
@@ -1,7 +1,6 @@
-/* Copyright (c) 2013, Linaro Limited
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2013-2018 Linaro Limited
+ * Copyright (c) 2021 ARM Limited
*/
/**
@@ -10,8 +9,8 @@
* ODP atomic operations
*/
-#ifndef ODP_API_ATOMIC_H_
-#define ODP_API_ATOMIC_H_
+#ifndef ODP_API_SPEC_ATOMIC_H_
+#define ODP_API_SPEC_ATOMIC_H_
#include <odp/visibility_begin.h>
#ifdef __cplusplus
@@ -20,16 +19,18 @@ extern "C" {
/**
* @defgroup odp_atomic ODP ATOMIC
+ * Atomic variables.
+ *
* @details
* <b> Atomic integers using relaxed memory ordering </b>
*
- * Atomic integer types (odp_atomic_u32_t and odp_atomic_u64_t) can be used to
- * implement e.g. shared counters. If not otherwise documented, operations in
- * this API are implemented using <b> RELAXED memory ordering </b> (see memory
- * order descriptions in the C11 specification). Relaxed operations do not
- * provide synchronization or ordering for other memory accesses (initiated
- * before or after the operation), only atomicity of the operation itself is
- * guaranteed.
+ * Atomic integer types (odp_atomic_u32_t, odp_atomic_u64_t and
+ * odp_atomic_u128_t) can be used to implement e.g. shared counters. If not
+ * otherwise documented, operations in this API are implemented using
+ * <b> RELAXED memory ordering </b> (see memory order descriptions in
+ * the C11 specification). Relaxed operations do not provide synchronization or
+ * ordering for other memory accesses (initiated before or after the operation),
+ * only atomicity of the operation itself is guaranteed.
*
* <b> Operations with non-relaxed memory ordering </b>
*
@@ -52,6 +53,9 @@ extern "C" {
*/
/**
+ * @typedef odp_atomic_u128_t
+ * Atomic 128-bit unsigned integer
+ *
* @typedef odp_atomic_u64_t
* Atomic 64-bit unsigned integer
*
@@ -187,9 +191,10 @@ void odp_atomic_min_u32(odp_atomic_u32_t *atom, uint32_t new_min);
* Compare and swap atomic uint32 variable
*
* Compares value of atomic variable to the value pointed by 'old_val'.
- * If values are equal, the operation writes 'new_val' into the atomic variable
- * and returns success. If they are not equal, the operation writes current
- * value of atomic variable into 'old_val' and returns failure.
+ * If the values are equal, the operation writes 'new_val' into the atomic variable
+ * and returns success. The operation returns failure only when the values are
+ * not equal (strong CAS operation). The current value of atomic variable is written
+ * into 'old_val' on failure.
*
* @param atom Pointer to atomic variable
* @param[in,out] old_val Pointer to the old value of the atomic variable.
@@ -197,10 +202,8 @@ void odp_atomic_min_u32(odp_atomic_u32_t *atom, uint32_t new_min);
* @param new_val New value to be written into the atomic variable
*
* @return 0 on failure, !0 on success
- *
*/
-int odp_atomic_cas_u32(odp_atomic_u32_t *atom, uint32_t *old_val,
- uint32_t new_val);
+int odp_atomic_cas_u32(odp_atomic_u32_t *atom, uint32_t *old_val, uint32_t new_val);
/**
* Exchange value of atomic uint32 variable
@@ -343,9 +346,10 @@ void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min);
* Compare and swap atomic uint64 variable
*
* Compares value of atomic variable to the value pointed by 'old_val'.
- * If values are equal, the operation writes 'new_val' into the atomic variable
- * and returns success. If they are not equal, the operation writes current
- * value of atomic variable into 'old_val' and returns failure.
+ * If the values are equal, the operation writes 'new_val' into the atomic variable
+ * and returns success. The operation returns failure only when the values are
+ * not equal (strong CAS operation). The current value of atomic variable is written
+ * into 'old_val' on failure.
*
* @param atom Pointer to atomic variable
* @param[in,out] old_val Pointer to the old value of the atomic variable.
@@ -354,8 +358,7 @@ void odp_atomic_min_u64(odp_atomic_u64_t *atom, uint64_t new_min);
*
* @return 0 on failure, !0 on success
*/
-int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val,
- uint64_t new_val);
+int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val, uint64_t new_val);
/**
* Exchange value of atomic uint64 variable
@@ -371,6 +374,58 @@ int odp_atomic_cas_u64(odp_atomic_u64_t *atom, uint64_t *old_val,
uint64_t odp_atomic_xchg_u64(odp_atomic_u64_t *atom, uint64_t new_val);
/*
+ * 128-bit operations in RELAXED memory ordering
+ * --------------------------------------------
+ */
+
+/**
+ * Initialize atomic odp_u128_t variable
+ *
+ * Initializes the atomic variable with 'val'. This operation is not atomic.
+ * Application must ensure that there's no race condition while initializing
+ * the variable.
+ *
+ * @param atom Pointer to atomic variable
+ * @param val Value to initialize the variable with
+ */
+void odp_atomic_init_u128(odp_atomic_u128_t *atom, odp_u128_t val);
+
+/**
+ * Load value of atomic odp_u128_t variable
+ *
+ * @param atom Pointer to atomic variable
+ *
+ * @return Value of the variable
+ */
+odp_u128_t odp_atomic_load_u128(odp_atomic_u128_t *atom);
+
+/**
+ * Store value to atomic odp_u128_t variable
+ *
+ * @param atom Pointer to atomic variable
+ * @param val Value to store in the variable
+ */
+void odp_atomic_store_u128(odp_atomic_u128_t *atom, odp_u128_t val);
+
+/**
+ * Compare and swap atomic odp_u128_t variable
+ *
+ * Compares value of atomic variable to the value pointed by 'old_val'.
+ * If the values are equal, the operation writes 'new_val' into the atomic variable
+ * and returns success. The operation returns failure only when the values are
+ * not equal (strong CAS operation). The current value of atomic variable is written
+ * into 'old_val' on failure.
+ *
+ * @param atom Pointer to atomic variable
+ * @param[in,out] old_val Pointer to the old value of the atomic variable.
+ * Operation updates this value on failure.
+ * @param new_val New value to be written into the atomic variable
+ *
+ * @return 0 on failure, !0 on success
+ */
+int odp_atomic_cas_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val, odp_u128_t new_val);
+
+/*
* 32-bit operations in non-RELAXED memory ordering
* ------------------------------------------------
*/
@@ -620,6 +675,80 @@ typedef union odp_atomic_op_t {
*/
int odp_atomic_lock_free_u64(odp_atomic_op_t *atomic_op);
+/*
+ * 128-bit operations in non-RELAXED memory ordering
+ * ------------------------------------------------
+ */
+
+/**
+ * Compare and swap atomic odp_u128_t variable using ACQUIRE memory ordering
+ *
+ * Otherwise identical to odp_atomic_cas_u128() but ensures ACQUIRE memory
+ * ordering on success. Memory ordering is RELAXED on failure.
+ *
+ * @param atom Pointer to atomic variable
+ * @param[in,out] old_val Pointer to the old value of the atomic variable.
+ * Operation updates this value on failure.
+ * @param new_val New value to be written into the atomic variable
+ *
+ * @return 0 on failure, !0 on success
+ */
+int odp_atomic_cas_acq_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val,
+ odp_u128_t new_val);
+
+/**
+ * Compare and swap atomic odp_u128_t variable using RELEASE memory ordering
+ *
+ * Otherwise identical to odp_atomic_cas_u128() but ensures RELEASE memory
+ * ordering on success. Memory ordering is RELAXED on failure.
+ *
+ * @param atom Pointer to atomic variable
+ * @param[in,out] old_val Pointer to the old value of the atomic variable.
+ * Operation updates this value on failure.
+ * @param new_val New value to be written into the atomic variable
+ *
+ * @return 0 on failure, !0 on success
+ */
+int odp_atomic_cas_rel_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val,
+ odp_u128_t new_val);
+
+/**
+ * Compare and swap atomic odp_u128_t variable using ACQUIRE-and-RELEASE memory
+ * ordering
+ *
+ * Otherwise identical to odp_atomic_cas_u128() but ensures ACQUIRE-and-RELEASE
+ * memory ordering on success. Memory ordering is RELAXED on failure.
+ *
+ * @param atom Pointer to atomic variable
+ * @param[in,out] old_val Pointer to the old value of the atomic variable.
+ * Operation updates this value on failure.
+ * @param new_val New value to be written into the atomic variable
+ *
+ * @return 0 on failure, !0 on success
+ */
+int odp_atomic_cas_acq_rel_u128(odp_atomic_u128_t *atom, odp_u128_t *old_val,
+ odp_u128_t new_val);
+
+/**
+ * Query which atomic odp_atomic_u128_t operations are lock-free
+ *
+ * Lock-free implementations have higher performance and scale better than
+ * implementations using locks.
+ *
+ * Init operations (e.g. odp_atomic_init_u128()) are not atomic. This function
+ * clears the op.init bit but will never set it to one.
+ *
+ * Note: 128-bit atomic API includes only init, load, store and CAS operations.
+ *
+ * @param atomic_op Pointer to atomic operation structure for storing
+ * operation flags. All bits are initialized to zero during
+ * the operation. The parameter is ignored when NULL.
+ * @retval 0 None of the 128-bit atomic operations are lock-free
+ * @retval 1 Some of the 128-bit atomic operations are lock-free
+ * @retval 2 All 128-bit atomic operations are lock-free
+ */
+int odp_atomic_lock_free_u128(odp_atomic_op_t *atomic_op);
+
/**
* @}
*/