1 /*****************************************************************************/
4 * \brief atomic operations header and generic implementations
5 * \ingroup l4util_atomic
8 * \author Lars Reuther <reuther@os.inf.tu-dresden.de>,
9 * Jork Loeser <jork@os.inf.tu-dresden.de> */
11 * (c) 2000-2009 Author(s)
12 * economic rights: Technische Universität Dresden (Germany)
13 * This file is part of TUD:OS and distributed under the terms of the
14 * GNU Lesser General Public License 2.1.
15 * Please see the COPYING-LGPL-2.1 file for details.
18 /*****************************************************************************/
19 #ifndef __L4UTIL__INCLUDE__ATOMIC_H__
20 #define __L4UTIL__INCLUDE__ATOMIC_H__
22 #include <l4/sys/l4int.h>
23 #include <l4/sys/compiler.h>
25 /*****************************************************************************
27 *****************************************************************************/
32 * \defgroup l4util_atomic Atomic Instructions
37 * \brief Atomic compare and exchange (64 bit version)
38 * \ingroup l4util_atomic
40 * \param dest destination operand
41 * \param cmp_val compare value
42 * \param new_val new value for dest
44 * \return 0 if comparison failed, 1 otherwise
46 * Compare the value in \em dest with \em cmp_val, if equal set \em dest to
50 l4util_cmpxchg64(volatile l4_uint64_t * dest,
51 l4_uint64_t cmp_val, l4_uint64_t new_val);
54 * \brief Atomic compare and exchange (32 bit version)
55 * \ingroup l4util_atomic
57 * \param dest destination operand
58 * \param cmp_val compare value
59 * \param new_val new value for dest
61 * \return 0 if comparison failed, !=0 otherwise
63 * Compare the value in \em dest with \em cmp_val, if equal set \em dest to
67 l4util_cmpxchg32(volatile l4_uint32_t * dest,
68 l4_uint32_t cmp_val, l4_uint32_t new_val);
71 * \brief Atomic compare and exchange (16 bit version)
72 * \ingroup l4util_atomic
74 * \param dest destination operand
75 * \param cmp_val compare value
76 * \param new_val new value for dest
78 * \return 0 if comparison failed, !=0 otherwise
80 * Compare the value in \em dest with \em cmp_val, if equal set \em dest to
84 l4util_cmpxchg16(volatile l4_uint16_t * dest,
85 l4_uint16_t cmp_val, l4_uint16_t new_val);
88 * \brief Atomic compare and exchange (8 bit version)
89 * \ingroup l4util_atomic
91 * \param dest destination operand
92 * \param cmp_val compare value
93 * \param new_val new value for dest
95 * \return 0 if comparison failed, !=0 otherwise
97 * Compare the value in \em dest with \em cmp_val, if equal set \em dest to
101 l4util_cmpxchg8(volatile l4_uint8_t * dest,
102 l4_uint8_t cmp_val, l4_uint8_t new_val);
105 * \brief Atomic compare and exchange (machine wide fields)
106 * \ingroup l4util_atomic
108 * \param dest destination operand
109 * \param cmp_val compare value
110 * \param new_val new value for dest
112 * \return 0 if comparison failed, 1 otherwise
114 * Compare the value in \em dest with \em cmp_val, if equal set \em dest to
118 l4util_cmpxchg(volatile l4_umword_t * dest,
119 l4_umword_t cmp_val, l4_umword_t new_val);
122 * \brief Atomic exchange (32 bit version)
123 * \ingroup l4util_atomic
125 * \param dest destination operand
126 * \param val new value for dest
128 * \return old value at destination
130 L4_INLINE l4_uint32_t
131 l4util_xchg32(volatile l4_uint32_t * dest, l4_uint32_t val);
134 * \brief Atomic exchange (16 bit version)
135 * \ingroup l4util_atomic
137 * \param dest destination operand
138 * \param val new value for dest
140 * \return old value at destination
142 L4_INLINE l4_uint16_t
143 l4util_xchg16(volatile l4_uint16_t * dest, l4_uint16_t val);
146 * \brief Atomic exchange (8 bit version)
147 * \ingroup l4util_atomic
149 * \param dest destination operand
150 * \param val new value for dest
152 * \return old value at destination
155 l4util_xchg8(volatile l4_uint8_t * dest, l4_uint8_t val);
158 * \brief Atomic exchange (machine wide fields)
159 * \ingroup l4util_atomic
161 * \param dest destination operand
162 * \param val new value for dest
164 * \return old value at destination
166 L4_INLINE l4_umword_t
167 l4util_xchg(volatile l4_umword_t * dest, l4_umword_t val);
169 //!@name Atomic add/sub/and/or (8,16,32 bit version) without result
171 * \ingroup l4util_atomic
173 * \param dest destination operand
174 * \param val value to add/sub/and/or
177 l4util_add8(volatile l4_uint8_t *dest, l4_uint8_t val);
179 l4util_add16(volatile l4_uint16_t *dest, l4_uint16_t val);
181 l4util_add32(volatile l4_uint32_t *dest, l4_uint32_t val);
183 l4util_sub8(volatile l4_uint8_t *dest, l4_uint8_t val);
185 l4util_sub16(volatile l4_uint16_t *dest, l4_uint16_t val);
187 l4util_sub32(volatile l4_uint32_t *dest, l4_uint32_t val);
189 l4util_and8(volatile l4_uint8_t *dest, l4_uint8_t val);
191 l4util_and16(volatile l4_uint16_t *dest, l4_uint16_t val);
193 l4util_and32(volatile l4_uint32_t *dest, l4_uint32_t val);
195 l4util_or8(volatile l4_uint8_t *dest, l4_uint8_t val);
197 l4util_or16(volatile l4_uint16_t *dest, l4_uint16_t val);
199 l4util_or32(volatile l4_uint32_t *dest, l4_uint32_t val);
202 //!@name Atomic add/sub/and/or operations (8,16,32 bit) with result
204 * \ingroup l4util_atomic
206 * \param dest destination operand
207 * \param val value to add/sub/and/or
211 l4util_add8_res(volatile l4_uint8_t *dest, l4_uint8_t val);
212 L4_INLINE l4_uint16_t
213 l4util_add16_res(volatile l4_uint16_t *dest, l4_uint16_t val);
214 L4_INLINE l4_uint32_t
215 l4util_add32_res(volatile l4_uint32_t *dest, l4_uint32_t val);
217 l4util_sub8_res(volatile l4_uint8_t *dest, l4_uint8_t val);
218 L4_INLINE l4_uint16_t
219 l4util_sub16_res(volatile l4_uint16_t *dest, l4_uint16_t val);
220 L4_INLINE l4_uint32_t
221 l4util_sub32_res(volatile l4_uint32_t *dest, l4_uint32_t val);
223 l4util_and8_res(volatile l4_uint8_t *dest, l4_uint8_t val);
224 L4_INLINE l4_uint16_t
225 l4util_and16_res(volatile l4_uint16_t *dest, l4_uint16_t val);
226 L4_INLINE l4_uint32_t
227 l4util_and32_res(volatile l4_uint32_t *dest, l4_uint32_t val);
229 l4util_or8_res(volatile l4_uint8_t *dest, l4_uint8_t val);
230 L4_INLINE l4_uint16_t
231 l4util_or16_res(volatile l4_uint16_t *dest, l4_uint16_t val);
232 L4_INLINE l4_uint32_t
233 l4util_or32_res(volatile l4_uint32_t *dest, l4_uint32_t val);
236 //!@name Atomic inc/dec (8,16,32 bit) without result
238 * \ingroup l4util_atomic
240 * \param dest destination operand
243 l4util_inc8(volatile l4_uint8_t *dest);
245 l4util_inc16(volatile l4_uint16_t *dest);
247 l4util_inc32(volatile l4_uint32_t *dest);
249 l4util_dec8(volatile l4_uint8_t *dest);
251 l4util_dec16(volatile l4_uint16_t *dest);
253 l4util_dec32(volatile l4_uint32_t *dest);
256 //!@name Atomic inc/dec (8,16,32 bit) with result
258 * \ingroup l4util_atomic
260 * \param dest destination operand
264 l4util_inc8_res(volatile l4_uint8_t *dest);
265 L4_INLINE l4_uint16_t
266 l4util_inc16_res(volatile l4_uint16_t *dest);
267 L4_INLINE l4_uint32_t
268 l4util_inc32_res(volatile l4_uint32_t *dest);
270 l4util_dec8_res(volatile l4_uint8_t *dest);
271 L4_INLINE l4_uint16_t
272 l4util_dec16_res(volatile l4_uint16_t *dest);
273 L4_INLINE l4_uint32_t
274 l4util_dec32_res(volatile l4_uint32_t *dest);
279 * \ingroup l4util_atomic
281 * \param dest destination operand
282 * \param val value to add
285 l4util_atomic_add(volatile long *dest, long val);
288 * \brief Atomic increment
289 * \ingroup l4util_atomic
291 * \param dest destination operand
294 l4util_atomic_inc(volatile long *dest);
298 /*****************************************************************************
299 *** Get architecture specific implementations
300 *****************************************************************************/
301 #include <l4/util/atomic_arch.h>
305 /* Non-implemented version, catch with a linker warning */
307 extern int __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(void);
309 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC8
311 l4util_inc8(volatile l4_uint8_t *dest)
312 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
315 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC16
317 l4util_inc16(volatile l4_uint16_t *dest)
318 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
321 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC8
323 l4util_dec8(volatile l4_uint8_t *dest)
324 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
327 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC16
329 l4util_dec16(volatile l4_uint16_t *dest)
330 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
335 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC8_RES
337 l4util_inc8_res(volatile l4_uint8_t *dest)
338 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
341 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC16_RES
342 L4_INLINE l4_uint16_t
343 l4util_inc16_res(volatile l4_uint16_t *dest)
344 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
347 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC8_RES
349 l4util_dec8_res(volatile l4_uint8_t *dest)
350 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
353 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC16_RES
354 L4_INLINE l4_uint16_t
355 l4util_dec16_res(volatile l4_uint16_t *dest)
356 { (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
359 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG64
361 l4util_cmpxchg64(volatile l4_uint64_t * dest,
362 l4_uint64_t cmp_val, l4_uint64_t new_val)
363 { (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
366 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG8
368 l4util_cmpxchg8(volatile l4_uint8_t * dest,
369 l4_uint8_t cmp_val, l4_uint8_t new_val)
370 { (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
373 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG16
375 l4util_cmpxchg16(volatile l4_uint16_t * dest,
376 l4_uint16_t cmp_val, l4_uint16_t new_val)
377 { (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
380 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG
382 l4util_cmpxchg(volatile l4_umword_t * dest,
383 l4_umword_t cmp_val, l4_umword_t new_val)
384 { (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
387 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG32
388 L4_INLINE l4_uint32_t
389 l4util_xchg32(volatile l4_uint32_t * dest, l4_uint32_t val)
390 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
393 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG16
394 L4_INLINE l4_uint16_t
395 l4util_xchg16(volatile l4_uint16_t * dest, l4_uint16_t val)
396 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
399 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG8
401 l4util_xchg8(volatile l4_uint8_t * dest, l4_uint8_t val)
402 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
405 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG
406 L4_INLINE l4_umword_t
407 l4util_xchg(volatile l4_umword_t * dest, l4_umword_t val)
408 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; }
411 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD8
413 l4util_add8(volatile l4_uint8_t *dest, l4_uint8_t val)
414 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
417 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD16
419 l4util_add16(volatile l4_uint16_t *dest, l4_uint16_t val)
420 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
423 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD32
425 l4util_add32(volatile l4_uint32_t *dest, l4_uint32_t val)
426 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
430 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB8
432 l4util_sub8(volatile l4_uint8_t *dest, l4_uint8_t val)
433 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
436 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB16
438 l4util_sub16(volatile l4_uint16_t *dest, l4_uint16_t val)
439 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
442 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB32
444 l4util_sub32(volatile l4_uint32_t *dest, l4_uint32_t val)
445 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
448 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND8
450 l4util_and8(volatile l4_uint8_t *dest, l4_uint8_t val)
451 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
454 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND16
456 l4util_and16(volatile l4_uint16_t *dest, l4_uint16_t val)
457 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
460 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND32
462 l4util_and32(volatile l4_uint32_t *dest, l4_uint32_t val)
463 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
466 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR8
468 l4util_or8(volatile l4_uint8_t *dest, l4_uint8_t val)
469 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
472 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR16
474 l4util_or16(volatile l4_uint16_t *dest, l4_uint16_t val)
475 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
478 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR32
480 l4util_or32(volatile l4_uint32_t *dest, l4_uint32_t val)
481 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); }
484 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD8_RES
486 l4util_add8_res(volatile l4_uint8_t *dest, l4_uint8_t val)
487 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
490 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD16_RES
491 L4_INLINE l4_uint16_t
492 l4util_add16_res(volatile l4_uint16_t *dest, l4_uint16_t val)
493 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
496 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD32_RES
497 L4_INLINE l4_uint32_t
498 l4util_add32_res(volatile l4_uint32_t *dest, l4_uint32_t val)
499 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
502 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB8_RES
504 l4util_sub8_res(volatile l4_uint8_t *dest, l4_uint8_t val)
505 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
508 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB16_RES
509 L4_INLINE l4_uint16_t
510 l4util_sub16_res(volatile l4_uint16_t *dest, l4_uint16_t val)
511 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
514 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB32_RES
515 L4_INLINE l4_uint32_t
516 l4util_sub32_res(volatile l4_uint32_t *dest, l4_uint32_t val)
517 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
520 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND8_RES
522 l4util_and8_res(volatile l4_uint8_t *dest, l4_uint8_t val)
523 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
526 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND16_RES
527 L4_INLINE l4_uint16_t
528 l4util_and16_res(volatile l4_uint16_t *dest, l4_uint16_t val)
529 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
532 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND32_RES
533 L4_INLINE l4_uint32_t
534 l4util_and32_res(volatile l4_uint32_t *dest, l4_uint32_t val)
535 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
538 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR8_RES
540 l4util_or8_res(volatile l4_uint8_t *dest, l4_uint8_t val)
541 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
544 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR16_RES
545 L4_INLINE l4_uint16_t
546 l4util_or16_res(volatile l4_uint16_t *dest, l4_uint16_t val)
547 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
550 #ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR32_RES
551 L4_INLINE l4_uint32_t
552 l4util_or32_res(volatile l4_uint32_t *dest, l4_uint32_t val)
553 { (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;}
559 #endif /* ! __L4UTIL__INCLUDE__ATOMIC_H__ */