]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/include/atomic.h
Formatting changes only.
[freertos] / FreeRTOS / Source / include / atomic.h
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 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  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /**\r
29  * @file atomic.h\r
30  * @brief FreeRTOS atomic operation support.\r
31  *\r
32  * This file implements atomic by disabling interrupts globally.\r
33  * Implementation with architecture specific atomic instructions\r
34  * are to be provided under each compiler directory.\r
35  */\r
36 \r
37 #ifndef ATOMIC_H\r
38 #define ATOMIC_H\r
39 \r
40 #ifndef INC_FREERTOS_H\r
41         #error "include FreeRTOS.h must appear in source files before include atomic.h"\r
42 #endif\r
43 \r
44 /* Standard includes. */\r
45 #include <stdint.h>\r
46 \r
47 #ifdef __cplusplus\r
48 extern "C" {\r
49 #endif\r
50 \r
51 /* Port specific definitions -- entering/exiting critical section.\r
52  * Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h\r
53  *\r
54  * Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with\r
55  * ATOMIC_ENTER_CRITICAL().\r
56  *  */\r
57 #if defined( portSET_INTERRUPT_MASK_FROM_ISR )\r
58 \r
59         /* Nested interrupt scheme is supported in this port. */\r
60         #define ATOMIC_ENTER_CRITICAL()  \\r
61                 UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()\r
62 \r
63         #define ATOMIC_EXIT_CRITICAL()    \\r
64                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )\r
65 \r
66 #else\r
67 \r
68         /* Nested interrupt scheme is NOT supported in this port. */\r
69         #define ATOMIC_ENTER_CRITICAL()  portENTER_CRITICAL()\r
70         #define ATOMIC_EXIT_CRITICAL()    portEXIT_CRITICAL()\r
71 \r
72 #endif /* portSET_INTERRUPT_MASK_FROM_ISR() */\r
73 \r
74 /* Port specific definition -- "always inline".\r
75  * Inline is compiler specific, and may not always get inlined depending on your optimization level.\r
76  * Also, inline is considerred as performance optimization for atomic.\r
77  * Thus, if portFORCE_INLINE is not provided by portmacro.h, instead of resulting error,\r
78  * simply define it.\r
79  */\r
80 #ifndef portFORCE_INLINE\r
81         #define portFORCE_INLINE\r
82 #endif\r
83 \r
84 #define ATOMIC_COMPARE_AND_SWAP_SUCCESS  0x1U           /**< Compare and swap succeeded, swapped. */\r
85 #define ATOMIC_COMPARE_AND_SWAP_FAILURE  0x0U           /**< Compare and swap failed, did not swap. */\r
86 \r
87 /*----------------------------- Swap && CAS ------------------------------*/\r
88 \r
89 /**\r
90  * Atomic compare-and-swap\r
91  *\r
92  * @brief Performs an atomic compare-and-swap operation on the specified values.\r
93  *\r
94  * @param[in, out] pDestination  Pointer to memory location from where value is\r
95  *                                                         to be loaded and checked.\r
96  * @param[in] ulExchange                 If condition meets, write this value to memory.\r
97  * @param[in] ulComparand               Swap condition.\r
98  *\r
99  * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.\r
100  *\r
101  * @note This function only swaps *pDestination with ulExchange, if previous\r
102  *         *pDestination value equals ulComparand.\r
103  */\r
104 static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32(\r
105                 uint32_t volatile * pDestination,\r
106                 uint32_t ulExchange,\r
107                 uint32_t ulComparand )\r
108 {\r
109 \r
110         uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;\r
111 \r
112         ATOMIC_ENTER_CRITICAL();\r
113 \r
114         if ( *pDestination == ulComparand )\r
115         {\r
116                 *pDestination = ulExchange;\r
117                 ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;\r
118         }\r
119 \r
120         ATOMIC_EXIT_CRITICAL();\r
121 \r
122         return ulReturnValue;\r
123 \r
124 }\r
125 \r
126 /**\r
127  * Atomic swap (pointers)\r
128  *\r
129  * @brief Atomically sets the address pointed to by *ppDestination to the value\r
130  *              of *pExchange.\r
131  *\r
132  * @param[in, out] ppDestination  Pointer to memory location from where a pointer\r
133  *                                                              value is to be loaded and written back to.\r
134  * @param[in] pExchange            Pointer value to be written to *ppDestination.\r
135  *\r
136  * @return The initial value of *ppDestination.\r
137  */\r
138 static portFORCE_INLINE void * Atomic_SwapPointers_p32(\r
139                 void * volatile * ppDestination,\r
140                 void * pExchange )\r
141 {\r
142         void * pReturnValue;\r
143 \r
144         ATOMIC_ENTER_CRITICAL();\r
145 \r
146         pReturnValue = *ppDestination;\r
147 \r
148         *ppDestination = pExchange;\r
149 \r
150         ATOMIC_EXIT_CRITICAL();\r
151 \r
152         return pReturnValue;\r
153 }\r
154 \r
155 /**\r
156  * Atomic compare-and-swap (pointers)\r
157  *\r
158  * @brief Performs an atomic compare-and-swap operation on the specified pointer\r
159  *              values.\r
160  *\r
161  * @param[in, out] ppDestination  Pointer to memory location from where a pointer\r
162  *                                                              value is to be loaded and checked.\r
163  * @param[in] pExchange            If condition meets, write this value to memory.\r
164  * @param[in] pComparand                  Swap condition.\r
165  *\r
166  * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.\r
167  *\r
168  * @note This function only swaps *ppDestination with pExchange, if previous\r
169  *         *ppDestination value equals pComparand.\r
170  */\r
171 static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32(\r
172                 void * volatile * ppDestination,\r
173                 void * pExchange, void * pComparand )\r
174 {\r
175         uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;\r
176 \r
177         ATOMIC_ENTER_CRITICAL();\r
178 \r
179         if ( *ppDestination == pComparand )\r
180         {\r
181                 *ppDestination = pExchange;\r
182                 ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;\r
183         }\r
184 \r
185         ATOMIC_EXIT_CRITICAL();\r
186 \r
187         return ulReturnValue;\r
188 }\r
189 \r
190 \r
191 /*----------------------------- Arithmetic ------------------------------*/\r
192 \r
193 /**\r
194  * Atomic add\r
195  *\r
196  * @brief Atomically adds count to the value of the specified pointer points to.\r
197  *\r
198  * @param[in,out] pAddend  Pointer to memory location from where value is to be\r
199  *                                               loaded and written back to.\r
200  * @param[in] ulCount     Value to be added to *pAddend.\r
201  *\r
202  * @return previous *pAddend value.\r
203  */\r
204 static portFORCE_INLINE uint32_t Atomic_Add_u32(\r
205                 uint32_t volatile * pAddend,\r
206                 uint32_t ulCount )\r
207 {\r
208         uint32_t ulCurrent;\r
209 \r
210         ATOMIC_ENTER_CRITICAL();\r
211 \r
212         ulCurrent = *pAddend;\r
213 \r
214         *pAddend += ulCount;\r
215 \r
216         ATOMIC_EXIT_CRITICAL();\r
217 \r
218         return ulCurrent;\r
219 }\r
220 \r
221 /**\r
222  * Atomic subtract\r
223  *\r
224  * @brief Atomically subtracts count from the value of the specified pointer\r
225  *              pointers to.\r
226  *\r
227  * @param[in,out] pAddend  Pointer to memory location from where value is to be\r
228  *                                               loaded and written back to.\r
229  * @param[in] ulCount     Value to be subtract from *pAddend.\r
230  *\r
231  * @return previous *pAddend value.\r
232  */\r
233 static portFORCE_INLINE uint32_t Atomic_Subtract_u32(\r
234                 uint32_t volatile * pAddend,\r
235                 uint32_t ulCount )\r
236 {\r
237         uint32_t ulCurrent;\r
238 \r
239         ATOMIC_ENTER_CRITICAL();\r
240 \r
241         ulCurrent = *pAddend;\r
242 \r
243         *pAddend -= ulCount;\r
244 \r
245         ATOMIC_EXIT_CRITICAL();\r
246 \r
247         return ulCurrent;\r
248 }\r
249 \r
250 /**\r
251  * Atomic increment\r
252  *\r
253  * @brief Atomically increments the value of the specified pointer points to.\r
254  *\r
255  * @param[in,out] pAddend  Pointer to memory location from where value is to be\r
256  *                                               loaded and written back to.\r
257  *\r
258  * @return *pAddend value before increment.\r
259  */\r
260 static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pAddend )\r
261 {\r
262         uint32_t ulCurrent;\r
263 \r
264         ATOMIC_ENTER_CRITICAL();\r
265 \r
266         ulCurrent = *pAddend;\r
267 \r
268         *pAddend += 1;\r
269 \r
270         ATOMIC_EXIT_CRITICAL();\r
271 \r
272         return ulCurrent;\r
273 }\r
274 \r
275 /**\r
276  * Atomic decrement\r
277  *\r
278  * @brief Atomically decrements the value of the specified pointer points to\r
279  *\r
280  * @param[in,out] pAddend  Pointer to memory location from where value is to be\r
281  *                                               loaded and written back to.\r
282  *\r
283  * @return *pAddend value before decrement.\r
284  */\r
285 static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAddend )\r
286 {\r
287         uint32_t ulCurrent;\r
288 \r
289         ATOMIC_ENTER_CRITICAL();\r
290 \r
291         ulCurrent = *pAddend;\r
292 \r
293         *pAddend -= 1;\r
294 \r
295         ATOMIC_EXIT_CRITICAL();\r
296 \r
297         return ulCurrent;\r
298 }\r
299 \r
300 /*----------------------------- Bitwise Logical ------------------------------*/\r
301 \r
302 /**\r
303  * Atomic OR\r
304  *\r
305  * @brief Performs an atomic OR operation on the specified values.\r
306  *\r
307  * @param [in, out] pDestination  Pointer to memory location from where value is\r
308  *                                                              to be loaded and written back to.\r
309  * @param [in] ulValue                  Value to be ORed with *pDestination.\r
310  *\r
311  * @return The original value of *pDestination.\r
312  */\r
313 static portFORCE_INLINE uint32_t Atomic_OR_u32(\r
314                 uint32_t volatile * pDestination,\r
315                 uint32_t ulValue )\r
316 {\r
317         uint32_t ulCurrent;\r
318 \r
319         ATOMIC_ENTER_CRITICAL();\r
320 \r
321         ulCurrent = *pDestination;\r
322 \r
323         *pDestination |= ulValue;\r
324 \r
325         ATOMIC_EXIT_CRITICAL();\r
326 \r
327         return ulCurrent;\r
328 }\r
329 \r
330 /**\r
331  * Atomic AND\r
332  *\r
333  * @brief Performs an atomic AND operation on the specified values.\r
334  *\r
335  * @param [in, out] pDestination  Pointer to memory location from where value is\r
336  *                                                              to be loaded and written back to.\r
337  * @param [in] ulValue                  Value to be ANDed with *pDestination.\r
338  *\r
339  * @return The original value of *pDestination.\r
340  */\r
341 static portFORCE_INLINE uint32_t Atomic_AND_u32(\r
342                 uint32_t volatile * pDestination,\r
343                 uint32_t ulValue )\r
344 {\r
345         uint32_t ulCurrent;\r
346 \r
347         ATOMIC_ENTER_CRITICAL();\r
348 \r
349         ulCurrent = *pDestination;\r
350 \r
351         *pDestination &= ulValue;\r
352 \r
353         ATOMIC_EXIT_CRITICAL();\r
354 \r
355         return ulCurrent;\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] pDestination  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 *pDestination.\r
366  *\r
367  * @return The original value of *pDestination.\r
368  */\r
369 static portFORCE_INLINE uint32_t Atomic_NAND_u32(\r
370                 uint32_t volatile * pDestination,\r
371                 uint32_t ulValue )\r
372 {\r
373         uint32_t ulCurrent;\r
374 \r
375         ATOMIC_ENTER_CRITICAL();\r
376 \r
377         ulCurrent = *pDestination;\r
378 \r
379         *pDestination = ~(ulCurrent & ulValue);\r
380 \r
381         ATOMIC_EXIT_CRITICAL();\r
382 \r
383         return ulCurrent;\r
384 }\r
385 \r
386 /**\r
387  * Atomic XOR\r
388  *\r
389  * @brief Performs an atomic XOR operation on the specified values.\r
390  *\r
391  * @param [in, out] pDestination  Pointer to memory location from where value is\r
392  *                                                              to be loaded and written back to.\r
393  * @param [in] ulValue                  Value to be XORed with *pDestination.\r
394  *\r
395  * @return The original value of *pDestination.\r
396  */\r
397 static portFORCE_INLINE uint32_t Atomic_XOR_u32(\r
398                 uint32_t volatile * pDestination,\r
399                 uint32_t ulValue )\r
400 {\r
401         uint32_t ulCurrent;\r
402 \r
403         ATOMIC_ENTER_CRITICAL();\r
404 \r
405         ulCurrent = *pDestination;\r
406 \r
407         *pDestination ^= ulValue;\r
408 \r
409         ATOMIC_EXIT_CRITICAL();\r
410 \r
411         return ulCurrent;\r
412 }\r
413 \r
414 #ifdef __cplusplus\r
415 }\r
416 #endif\r
417 \r
418 #endif /* ATOMIC_H */\r