1#ifndef AWS_COMMON_ATOMICS_INL
2#define AWS_COMMON_ATOMICS_INL
3
4/*
5 * Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License").
8 * You may not use this file except in compliance with the License.
9 * A copy of the License is located at
10 *
11 * http://aws.amazon.com/apache2.0
12 *
13 * or in the "license" file accompanying this file. This file is distributed
14 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
15 * express or implied. See the License for the specific language governing
16 * permissions and limitations under the License.
17 */
18
19#include <aws/common/atomics.h>
20#include <aws/common/common.h>
21
22AWS_EXTERN_C_BEGIN
23
24/**
25 * Reads an atomic var as an integer, using sequentially consistent ordering, and returns the result.
26 */
27AWS_STATIC_IMPL
28size_t aws_atomic_load_int(volatile const struct aws_atomic_var *var) {
29 return aws_atomic_load_int_explicit(var, aws_memory_order_seq_cst);
30}
31
32/**
33 * Reads an atomic var as a pointer, using sequentially consistent ordering, and returns the result.
34 */
35AWS_STATIC_IMPL
36void *aws_atomic_load_ptr(volatile const struct aws_atomic_var *var) {
37 return aws_atomic_load_ptr_explicit(var, aws_memory_order_seq_cst);
38}
39
40/**
41 * Stores an integer into an atomic var, using sequentially consistent ordering.
42 */
43AWS_STATIC_IMPL
44void aws_atomic_store_int(volatile struct aws_atomic_var *var, size_t n) {
45 aws_atomic_store_int_explicit(var, n, aws_memory_order_seq_cst);
46}
47
48/**
49 * Stores a pointer into an atomic var, using sequentially consistent ordering.
50 */
51AWS_STATIC_IMPL
52void aws_atomic_store_ptr(volatile struct aws_atomic_var *var, void *p) {
53 aws_atomic_store_ptr_explicit(var, p, aws_memory_order_seq_cst);
54}
55
56/**
57 * Exchanges an integer with the value in an atomic_var, using sequentially consistent ordering.
58 * Returns the value that was previously in the atomic_var.
59 */
60AWS_STATIC_IMPL
61size_t aws_atomic_exchange_int(volatile struct aws_atomic_var *var, size_t n) {
62 return aws_atomic_exchange_int_explicit(var, n, aws_memory_order_seq_cst);
63}
64
65/**
66 * Exchanges an integer with the value in an atomic_var, using sequentially consistent ordering.
67 * Returns the value that was previously in the atomic_var.
68 */
69AWS_STATIC_IMPL
70void *aws_atomic_exchange_ptr(volatile struct aws_atomic_var *var, void *p) {
71 return aws_atomic_exchange_ptr_explicit(var, p, aws_memory_order_seq_cst);
72}
73
74/**
75 * Atomically compares *var to *expected; if they are equal, atomically sets *var = desired. Otherwise, *expected is set
76 * to the value in *var. Uses sequentially consistent memory ordering, regardless of success or failure.
77 * Returns true if the compare was successful and the variable updated to desired.
78 */
79AWS_STATIC_IMPL
80bool aws_atomic_compare_exchange_int(volatile struct aws_atomic_var *var, size_t *expected, size_t desired) {
81 return aws_atomic_compare_exchange_int_explicit(
82 var, expected, desired, aws_memory_order_seq_cst, aws_memory_order_seq_cst);
83}
84
85/**
86 * Atomically compares *var to *expected; if they are equal, atomically sets *var = desired. Otherwise, *expected is set
87 * to the value in *var. Uses sequentially consistent memory ordering, regardless of success or failure.
88 * Returns true if the compare was successful and the variable updated to desired.
89 */
90AWS_STATIC_IMPL
91bool aws_atomic_compare_exchange_ptr(volatile struct aws_atomic_var *var, void **expected, void *desired) {
92 return aws_atomic_compare_exchange_ptr_explicit(
93 var, expected, desired, aws_memory_order_seq_cst, aws_memory_order_seq_cst);
94}
95
96/**
97 * Atomically adds n to *var, and returns the previous value of *var.
98 * Uses sequentially consistent ordering.
99 */
100AWS_STATIC_IMPL
101size_t aws_atomic_fetch_add(volatile struct aws_atomic_var *var, size_t n) {
102 return aws_atomic_fetch_add_explicit(var, n, aws_memory_order_seq_cst);
103}
104
105/**
106 * Atomically subtracts n from *var, and returns the previous value of *var.
107 * Uses sequentially consistent ordering.
108 */
109AWS_STATIC_IMPL
110size_t aws_atomic_fetch_sub(volatile struct aws_atomic_var *var, size_t n) {
111 return aws_atomic_fetch_sub_explicit(var, n, aws_memory_order_seq_cst);
112}
113
114/**
115 * Atomically ands n into *var, and returns the previous value of *var.
116 * Uses sequentially consistent ordering.
117 */
118AWS_STATIC_IMPL
119size_t aws_atomic_fetch_and(volatile struct aws_atomic_var *var, size_t n) {
120 return aws_atomic_fetch_and_explicit(var, n, aws_memory_order_seq_cst);
121}
122
123/**
124 * Atomically ors n into *var, and returns the previous value of *var.
125 * Uses sequentially consistent ordering.
126 */
127AWS_STATIC_IMPL
128size_t aws_atomic_fetch_or(volatile struct aws_atomic_var *var, size_t n) {
129 return aws_atomic_fetch_or_explicit(var, n, aws_memory_order_seq_cst);
130}
131
132/**
133 * Atomically xors n into *var, and returns the previous value of *var.
134 * Uses sequentially consistent ordering.
135 */
136AWS_STATIC_IMPL
137size_t aws_atomic_fetch_xor(volatile struct aws_atomic_var *var, size_t n) {
138 return aws_atomic_fetch_xor_explicit(var, n, aws_memory_order_seq_cst);
139}
140
141/* Include the backend implementation now, because we'll use its typedefs and #defines below */
142#if defined(__GNUC__) || defined(__clang__)
143# if defined(__ATOMIC_RELAXED)
144# include <aws/common/atomics_gnu.inl>
145# else
146# include <aws/common/atomics_gnu_old.inl>
147# endif /* __ATOMIC_RELAXED */
148#elif defined(_MSC_VER)
149# include <aws/common/atomics_msvc.inl>
150#else
151# error No atomics implementation for your compiler is available
152#endif
153
154#include <aws/common/atomics_fallback.inl>
155
156AWS_EXTERN_C_END
157
158#endif /* AWS_COMMON_ATOMICS_INL */
159