FreeRTOS: Platform
Platform portability layer
Return to main page ↑
atomic.h
Go to the documentation of this file.
1 /*
2  * FreeRTOS Kernel V10.3.0
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 
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
48 extern "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
88 #define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U
90 /*----------------------------- Swap && CAS ------------------------------*/
91 
107 static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
108  uint32_t ulExchange,
109  uint32_t ulComparand )
110 {
111 uint32_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 
143 static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
144  void * pvExchange )
145 {
146 void * 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 
175 static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
176  void * pvExchange,
177  void * pvComparand )
178 {
179 uint32_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 
208 static 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 
236 static 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 
262 static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
263 {
264 uint32_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 
287 static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
288 {
289 uint32_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 
314 static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
315  uint32_t ulValue )
316 {
317 uint32_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 
341 static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
342  uint32_t ulValue )
343 {
344 uint32_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 
368 static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
369  uint32_t ulValue )
370 {
371 uint32_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 
395 static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
396  uint32_t ulValue )
397 {
398 uint32_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 */
Atomic_Add_u32
static portFORCE_INLINE uint32_t Atomic_Add_u32(uint32_t volatile *pulAddend, uint32_t ulCount)
Atomically adds count to the value of the specified pointer points to.
Definition: atomic.h:208
ATOMIC_COMPARE_AND_SWAP_SUCCESS
#define ATOMIC_COMPARE_AND_SWAP_SUCCESS
Definition: atomic.h:87
Atomic_AND_u32
static portFORCE_INLINE uint32_t Atomic_AND_u32(uint32_t volatile *pulDestination, uint32_t ulValue)
Performs an atomic AND operation on the specified values.
Definition: atomic.h:341
Atomic_SwapPointers_p32
static portFORCE_INLINE void * Atomic_SwapPointers_p32(void *volatile *ppvDestination, void *pvExchange)
Atomically sets the address pointed to by *ppvDestination to the value of *pvExchange.
Definition: atomic.h:143
Atomic_XOR_u32
static portFORCE_INLINE uint32_t Atomic_XOR_u32(uint32_t volatile *pulDestination, uint32_t ulValue)
Performs an atomic XOR operation on the specified values.
Definition: atomic.h:395
Atomic_NAND_u32
static portFORCE_INLINE uint32_t Atomic_NAND_u32(uint32_t volatile *pulDestination, uint32_t ulValue)
Performs an atomic NAND operation on the specified values.
Definition: atomic.h:368
Atomic_CompareAndSwapPointers_p32
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32(void *volatile *ppvDestination, void *pvExchange, void *pvComparand)
Performs an atomic compare-and-swap operation on the specified pointer values.
Definition: atomic.h:175
Atomic_Decrement_u32
static portFORCE_INLINE uint32_t Atomic_Decrement_u32(uint32_t volatile *pulAddend)
Atomically decrements the value of the specified pointer points to.
Definition: atomic.h:287
ATOMIC_COMPARE_AND_SWAP_FAILURE
#define ATOMIC_COMPARE_AND_SWAP_FAILURE
Definition: atomic.h:88
Atomic_Subtract_u32
static portFORCE_INLINE uint32_t Atomic_Subtract_u32(uint32_t volatile *pulAddend, uint32_t ulCount)
Atomically subtracts count from the value of the specified pointer pointers to.
Definition: atomic.h:236
Atomic_OR_u32
static portFORCE_INLINE uint32_t Atomic_OR_u32(uint32_t volatile *pulDestination, uint32_t ulValue)
Performs an atomic OR operation on the specified values.
Definition: atomic.h:314
Atomic_CompareAndSwap_u32
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32(uint32_t volatile *pulDestination, uint32_t ulExchange, uint32_t ulComparand)
Performs an atomic compare-and-swap operation on the specified values.
Definition: atomic.h:107
Atomic_Increment_u32
static portFORCE_INLINE uint32_t Atomic_Increment_u32(uint32_t volatile *pulAddend)
Atomically increments the value of the specified pointer points to.
Definition: atomic.h:262