1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
3 * Description : los atomic.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice, this list of
7 * conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
9 * of conditions and the following disclaimer in the documentation and/or other materials
10 * provided with the distribution.
11 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
12 * to endorse or promote products derived from this software without specific prior written
13 * permission.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * ---------------------------------------------------------------------------- */
26
27 /**
28 * @defgroup los_atomic Atomic
29 * @ingroup kernel
30 */
31
32 #ifndef _LOS_ATOMIC_H
33 #define _LOS_ATOMIC_H
34
35 #include "los_hwi.h"
36 #include "los_typedef.h"
37
38 #ifdef __cplusplus
39 #if __cplusplus
40 extern "C" {
41 #endif /* __cplusplus */
42 #endif /* __cplusplus */
43
44 /**
45 * @ingroup los_atomic
46 * @brief Atomic addition.
47 *
48 * @par Description:
49 * This API is used to implement the atomic addition and return the result value of the augend.
50 * @attention
51 * <ul>
52 * <li>The pointer val must not be NULL.</li>
53 * <li>If the addtion result is not in the range of representable values for 32-bit signed integer,
54 * an int integer overflow may occur to the return value</li>
55 * </ul>
56 *
57 * @param val [IN] The augend pointer.
58 * @param addVal [IN] The addend.
59 *
60 * @retval #INT32 The result value of the augend.
61 * @par Dependency:
62 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
63 * @see
64 */
LOS_AtomicAdd(volatile INT32 * val,INT32 addVal)65 static inline INT32 LOS_AtomicAdd(volatile INT32 *val, INT32 addVal)
66 {
67 INT32 tmp;
68 UINT32 intStatus;
69 intStatus = LOS_IntLock();
70 tmp = *val;
71 tmp += addVal;
72 *val = tmp;
73 LOS_IntRestore(intStatus);
74 return tmp;
75 }
76
77 /**
78 * @ingroup los_atomic
79 * @brief Atomic subtraction.
80 *
81 * @par Description:
82 * This API is used to implement the atomic subtraction and return the result value of the minuend.
83 * @attention
84 * <ul>
85 * <li>The pointer val must not be NULL.</li>
86 * <li>If the subtraction result is not in the range of representable values for 32-bit signed integer,
87 * an int integer overflow may occur to the return value</li>
88 * </ul>
89 *
90 * @param val [IN] The minuend pointer.
91 * @param addVal [IN] The subtrahend.
92 *
93 * @retval #INT32 The result value of the minuend.
94 * @par Dependency:
95 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
96 * @see
97 */
LOS_AtomicSub(volatile INT32 * val,INT32 addVal)98 static inline INT32 LOS_AtomicSub(volatile INT32 *val, INT32 addVal)
99 {
100 INT32 tmp;
101 UINT32 intStatus;
102 intStatus = LOS_IntLock();
103 tmp = *val;
104 tmp -= addVal;
105 *val = tmp;
106 LOS_IntRestore(intStatus);
107 return tmp;
108 }
109 /**
110 * @ingroup los_atomic
111 * @brief Atomic addSelf.
112 *
113 * @par Description:
114 * This API is used to implement the atomic addSelf .
115 * @attention
116 * <ul>
117 * <li>The pointer addr must not be NULL.</li>
118 * <li>The value which addr point to must not be INT_MAX to avoid integer overflow after adding 1.</li>
119 * </ul>
120 *
121 * @param addr [IN] The addSelf variable pointer.
122 *
123 * @retval none.
124 * @par Dependency:
125 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
126 * @see
127 */
LOS_AtomicInc(volatile INT32 * addr)128 static inline VOID LOS_AtomicInc(volatile INT32 *addr)
129 {
130 UINT32 intStatus;
131 intStatus = LOS_IntLock();
132 (*addr)++;
133 LOS_IntRestore(intStatus);
134 }
135
136 /**
137 * @ingroup los_atomic
138 * @brief Atomic addSelf.
139 *
140 * @par Description:
141 * This API is used to implement the atomic addSelf and return the result of addSelf.
142 * @attention
143 * <ul>
144 * <li>The pointer addr must not be NULL.</li>
145 * <li>The value which pswAddr point to must not be INT_MAX to avoid integer overflow after adding 1.</li>
146 * </ul>
147 *
148 * @param addr [IN] The addSelf variable pointer.
149 *
150 * @retval #INT32 The return value of variable addSelf.
151 * @par Dependency:
152 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
153 * @see
154 */
LOS_AtomicIncRet(volatile INT32 * addr)155 static inline INT32 LOS_AtomicIncRet(volatile INT32 *addr)
156 {
157 INT32 tmp;
158 UINT32 intStatus;
159 intStatus = LOS_IntLock();
160 tmp = *addr;
161 tmp++;
162 *addr = tmp;
163 LOS_IntRestore(intStatus);
164 return tmp;
165 }
166
167 /**
168 * @ingroup los_atomic
169 * @brief Atomic auto-decrement.
170 *
171 * @par Description:
172 * This API is used to implementating the atomic auto-decrement.
173 * @attention
174 * <ul>
175 * <li>The pointer addr must not be NULL.</li>
176 * <li>The value which pswAddr point to must not be INT_MIN to avoid overflow after reducing 1.</li>
177 * </ul>
178 *
179 * @param addr [IN] The auto-decrement variable pointer.
180 *
181 * @retval none.
182 * @par Dependency:
183 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
184 * @see
185 */
LOS_AtomicDec(volatile INT32 * addr)186 static inline VOID LOS_AtomicDec(volatile INT32 *addr)
187 {
188 UINT32 intStatus;
189 intStatus = LOS_IntLock();
190 (*addr)--;
191 LOS_IntRestore(intStatus);
192 }
193
194 /**
195 * @ingroup los_atomic
196 * @brief Atomic auto-decrement.
197 *
198 * @par Description:
199 * This API is used to implementating the atomic auto-decrement and return the result of auto-decrement.
200 * @attention
201 * <ul>
202 * <li>The pointer addr must not be NULL.</li>
203 * <li>The value which pswAddr point to must not be INT_MIN to avoid overflow after reducing 1.</li>
204 * </ul>
205 *
206 * @param addr [IN] The addSelf variable pointer.
207 *
208 * @retval #INT32 The return value of variable auto-decrement.
209 * @par Dependency:
210 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
211 * @see
212 */
LOS_AtomicDecRet(volatile INT32 * addr)213 static inline INT32 LOS_AtomicDecRet(volatile INT32 *addr)
214 {
215 INT32 tmp;
216 UINT32 intStatus;
217 intStatus = LOS_IntLock();
218 tmp = *addr;
219 tmp--;
220 *addr = tmp;
221 LOS_IntRestore(intStatus);
222 return tmp;
223 }
224
225 /**
226 * @ingroup los_atomic
227 * @brief Atomic exchange for 32-bit variable.
228 *
229 * @par Description:
230 * This API is used to implement the atomic exchange for 32-bit variable and return the previous value of
231 * the atomic variable.
232 * @attention
233 * <ul>The pointer addr must not be NULL.</ul>
234 *
235 * @param addr [IN] The variable pointer.
236 * @param value [IN] The exchange value.
237 *
238 * @retval #INT32 The previous value of the atomic variable
239 * @par Dependency:
240 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
241 * @see
242 */
LOS_AtomicXchg32bits(volatile INT32 * addr,INT32 value)243 static inline INT32 LOS_AtomicXchg32bits(volatile INT32 *addr, INT32 value)
244 {
245 INT32 prevVal;
246 UINT32 intStatus;
247 intStatus = LOS_IntLock();
248 prevVal = *addr;
249 *addr = value;
250 LOS_IntRestore(intStatus);
251 return prevVal;
252 }
253
254 /**
255 * @ingroup los_atomic
256 * @brief Atomic exchange for 32-bit variable with compare.
257 *
258 * @par Description:
259 * This API is used to implement the atomic exchange for 32-bit variable, if the value of variable is equal to swOldVal.
260 * @attention
261 * <ul>The pointer addr must not be NULL.</ul>
262 *
263 * @param addr [IN] The variable pointer.
264 * @param newVal [IN] The new value.
265 * @param oldVal [IN] The old value.
266 *
267 * @retval TRUE The previous value of the atomic variable is not equal to swOldVal.
268 * @retval FALSE The previous value of the atomic variable is equal to swOldVal.
269 * @par Dependency:
270 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
271 * @see
272 */
LOS_AtomicCmpXchg32bits(volatile INT32 * addr,INT32 newVal,INT32 oldVal)273 static inline BOOL LOS_AtomicCmpXchg32bits(volatile INT32 *addr, INT32 newVal, INT32 oldVal)
274 {
275 INT32 prevVal;
276 UINT32 intStatus = LOS_IntLock();
277 prevVal = *addr;
278 if (*addr == oldVal) {
279 *addr = newVal;
280 }
281 LOS_IntRestore(intStatus);
282 return (prevVal != oldVal);
283 }
284
285 #ifdef __cplusplus
286 #if __cplusplus
287 }
288 #endif /* __cplusplus */
289 #endif /* __cplusplus */
290
291 #endif /* _LOS_ATOMIC_H */
292