source: S-port/trunk/Middlewares/Third_Party/FreeRTOS/Source/include/atomic.h

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 12.0 KB
Line 
1/*
2 * FreeRTOS Kernel V10.3.1
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
24 *
25 * 1 tab == 4 spaces!
26 */
27
28/**
29 * @file atomic.h
30 * @brief FreeRTOS atomic operation support.
31 *
32 * This file implements atomic functions by disabling interrupts globally.
33 * Implementations with architecture specific atomic instructions can be
34 * provided under each compiler directory.
35 */
36
37#ifndef ATOMIC_H
38#define ATOMIC_H
39
40#ifndef INC_FREERTOS_H
41 #error "include FreeRTOS.h must appear in source files before include atomic.h"
42#endif
43
44/* Standard includes. */
45#include <stdint.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/*
52 * Port specific definitions -- entering/exiting critical section.
53 * Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
54 *
55 * Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
56 * ATOMIC_ENTER_CRITICAL().
57 *
58 */
59#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
60
61 /* Nested interrupt scheme is supported in this port. */
62 #define ATOMIC_ENTER_CRITICAL() \
63 UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
64
65 #define ATOMIC_EXIT_CRITICAL() \
66 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
67
68#else
69
70 /* Nested interrupt scheme is NOT supported in this port. */
71 #define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
72 #define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
73
74#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
75
76/*
77 * Port specific definition -- "always inline".
78 * Inline is compiler specific, and may not always get inlined depending on your
79 * optimization level. Also, inline is considered as performance optimization
80 * for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
81 * instead of resulting error, simply define it away.
82 */
83#ifndef portFORCE_INLINE
84 #define portFORCE_INLINE
85#endif
86
87#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */
88#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
89
90/*----------------------------- Swap && CAS ------------------------------*/
91
92/**
93 * Atomic compare-and-swap
94 *
95 * @brief Performs an atomic compare-and-swap operation on the specified values.
96 *
97 * @param[in, out] pulDestination Pointer to memory location from where value is
98 * to be loaded and checked.
99 * @param[in] ulExchange If condition meets, write this value to memory.
100 * @param[in] ulComparand Swap condition.
101 *
102 * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
103 *
104 * @note This function only swaps *pulDestination with ulExchange, if previous
105 * *pulDestination value equals ulComparand.
106 */
107static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
108 uint32_t ulExchange,
109 uint32_t ulComparand )
110{
111uint32_t ulReturnValue;
112
113 ATOMIC_ENTER_CRITICAL();
114 {
115 if( *pulDestination == ulComparand )
116 {
117 *pulDestination = ulExchange;
118 ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
119 }
120 else
121 {
122 ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
123 }
124 }
125 ATOMIC_EXIT_CRITICAL();
126
127 return ulReturnValue;
128}
129/*-----------------------------------------------------------*/
130
131/**
132 * Atomic swap (pointers)
133 *
134 * @brief Atomically sets the address pointed to by *ppvDestination to the value
135 * of *pvExchange.
136 *
137 * @param[in, out] ppvDestination Pointer to memory location from where a pointer
138 * value is to be loaded and written back to.
139 * @param[in] pvExchange Pointer value to be written to *ppvDestination.
140 *
141 * @return The initial value of *ppvDestination.
142 */
143static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
144 void * pvExchange )
145{
146void * pReturnValue;
147
148 ATOMIC_ENTER_CRITICAL();
149 {
150 pReturnValue = *ppvDestination;
151 *ppvDestination = pvExchange;
152 }
153 ATOMIC_EXIT_CRITICAL();
154
155 return pReturnValue;
156}
157/*-----------------------------------------------------------*/
158
159/**
160 * Atomic compare-and-swap (pointers)
161 *
162 * @brief Performs an atomic compare-and-swap operation on the specified pointer
163 * values.
164 *
165 * @param[in, out] ppvDestination Pointer to memory location from where a pointer
166 * value is to be loaded and checked.
167 * @param[in] pvExchange If condition meets, write this value to memory.
168 * @param[in] pvComparand Swap condition.
169 *
170 * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
171 *
172 * @note This function only swaps *ppvDestination with pvExchange, if previous
173 * *ppvDestination value equals pvComparand.
174 */
175static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
176 void * pvExchange,
177 void * pvComparand )
178{
179uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
180
181 ATOMIC_ENTER_CRITICAL();
182 {
183 if( *ppvDestination == pvComparand )
184 {
185 *ppvDestination = pvExchange;
186 ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
187 }
188 }
189 ATOMIC_EXIT_CRITICAL();
190
191 return ulReturnValue;
192}
193
194
195/*----------------------------- Arithmetic ------------------------------*/
196
197/**
198 * Atomic add
199 *
200 * @brief Atomically adds count to the value of the specified pointer points to.
201 *
202 * @param[in,out] pulAddend Pointer to memory location from where value is to be
203 * loaded and written back to.
204 * @param[in] ulCount Value to be added to *pulAddend.
205 *
206 * @return previous *pulAddend value.
207 */
208static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
209 uint32_t ulCount )
210{
211 uint32_t ulCurrent;
212
213 ATOMIC_ENTER_CRITICAL();
214 {
215 ulCurrent = *pulAddend;
216 *pulAddend += ulCount;
217 }
218 ATOMIC_EXIT_CRITICAL();
219
220 return ulCurrent;
221}
222/*-----------------------------------------------------------*/
223
224/**
225 * Atomic subtract
226 *
227 * @brief Atomically subtracts count from the value of the specified pointer
228 * pointers to.
229 *
230 * @param[in,out] pulAddend Pointer to memory location from where value is to be
231 * loaded and written back to.
232 * @param[in] ulCount Value to be subtract from *pulAddend.
233 *
234 * @return previous *pulAddend value.
235 */
236static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
237 uint32_t ulCount )
238{
239 uint32_t ulCurrent;
240
241 ATOMIC_ENTER_CRITICAL();
242 {
243 ulCurrent = *pulAddend;
244 *pulAddend -= ulCount;
245 }
246 ATOMIC_EXIT_CRITICAL();
247
248 return ulCurrent;
249}
250/*-----------------------------------------------------------*/
251
252/**
253 * Atomic increment
254 *
255 * @brief Atomically increments the value of the specified pointer points to.
256 *
257 * @param[in,out] pulAddend Pointer to memory location from where value is to be
258 * loaded and written back to.
259 *
260 * @return *pulAddend value before increment.
261 */
262static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
263{
264uint32_t ulCurrent;
265
266 ATOMIC_ENTER_CRITICAL();
267 {
268 ulCurrent = *pulAddend;
269 *pulAddend += 1;
270 }
271 ATOMIC_EXIT_CRITICAL();
272
273 return ulCurrent;
274}
275/*-----------------------------------------------------------*/
276
277/**
278 * Atomic decrement
279 *
280 * @brief Atomically decrements the value of the specified pointer points to
281 *
282 * @param[in,out] pulAddend Pointer to memory location from where value is to be
283 * loaded and written back to.
284 *
285 * @return *pulAddend value before decrement.
286 */
287static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
288{
289uint32_t ulCurrent;
290
291 ATOMIC_ENTER_CRITICAL();
292 {
293 ulCurrent = *pulAddend;
294 *pulAddend -= 1;
295 }
296 ATOMIC_EXIT_CRITICAL();
297
298 return ulCurrent;
299}
300
301/*----------------------------- Bitwise Logical ------------------------------*/
302
303/**
304 * Atomic OR
305 *
306 * @brief Performs an atomic OR operation on the specified values.
307 *
308 * @param [in, out] pulDestination Pointer to memory location from where value is
309 * to be loaded and written back to.
310 * @param [in] ulValue Value to be ORed with *pulDestination.
311 *
312 * @return The original value of *pulDestination.
313 */
314static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
315 uint32_t ulValue )
316{
317uint32_t ulCurrent;
318
319 ATOMIC_ENTER_CRITICAL();
320 {
321 ulCurrent = *pulDestination;
322 *pulDestination |= ulValue;
323 }
324 ATOMIC_EXIT_CRITICAL();
325
326 return ulCurrent;
327}
328/*-----------------------------------------------------------*/
329
330/**
331 * Atomic AND
332 *
333 * @brief Performs an atomic AND operation on the specified values.
334 *
335 * @param [in, out] pulDestination Pointer to memory location from where value is
336 * to be loaded and written back to.
337 * @param [in] ulValue Value to be ANDed with *pulDestination.
338 *
339 * @return The original value of *pulDestination.
340 */
341static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
342 uint32_t ulValue )
343{
344uint32_t ulCurrent;
345
346 ATOMIC_ENTER_CRITICAL();
347 {
348 ulCurrent = *pulDestination;
349 *pulDestination &= ulValue;
350 }
351 ATOMIC_EXIT_CRITICAL();
352
353 return ulCurrent;
354}
355/*-----------------------------------------------------------*/
356
357/**
358 * Atomic NAND
359 *
360 * @brief Performs an atomic NAND operation on the specified values.
361 *
362 * @param [in, out] pulDestination Pointer to memory location from where value is
363 * to be loaded and written back to.
364 * @param [in] ulValue Value to be NANDed with *pulDestination.
365 *
366 * @return The original value of *pulDestination.
367 */
368static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
369 uint32_t ulValue )
370{
371uint32_t ulCurrent;
372
373 ATOMIC_ENTER_CRITICAL();
374 {
375 ulCurrent = *pulDestination;
376 *pulDestination = ~( ulCurrent & ulValue );
377 }
378 ATOMIC_EXIT_CRITICAL();
379
380 return ulCurrent;
381}
382/*-----------------------------------------------------------*/
383
384/**
385 * Atomic XOR
386 *
387 * @brief Performs an atomic XOR operation on the specified values.
388 *
389 * @param [in, out] pulDestination Pointer to memory location from where value is
390 * to be loaded and written back to.
391 * @param [in] ulValue Value to be XORed with *pulDestination.
392 *
393 * @return The original value of *pulDestination.
394 */
395static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
396 uint32_t ulValue )
397{
398uint32_t ulCurrent;
399
400 ATOMIC_ENTER_CRITICAL();
401 {
402 ulCurrent = *pulDestination;
403 *pulDestination ^= ulValue;
404 }
405 ATOMIC_EXIT_CRITICAL();
406
407 return ulCurrent;
408}
409
410#ifdef __cplusplus
411}
412#endif
413
414#endif /* ATOMIC_H */
Note: See TracBrowser for help on using the repository browser.