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