ObjFW
atomic_builtins.h
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
3  * Jonathan Schleifer <js@heap.zone>
4  *
5  * All rights reserved.
6  *
7  * This file is part of ObjFW. It may be distributed under the terms of the
8  * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
9  * the packaging of this file.
10  *
11  * Alternatively, it may be distributed under the terms of the GNU General
12  * Public License, either version 2 or 3, which can be found in the file
13  * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
14  * file.
15  */
16 
17 static OF_INLINE int
18 of_atomic_int_add(volatile int *_Nonnull p, int i)
19 {
20  return __atomic_add_fetch(p, i, __ATOMIC_RELAXED);
21 }
22 
23 static OF_INLINE int32_t
24 of_atomic_int32_add(volatile int32_t *_Nonnull p, int32_t i)
25 {
26  return __atomic_add_fetch(p, i, __ATOMIC_RELAXED);
27 }
28 
29 static OF_INLINE void *_Nullable
30 of_atomic_ptr_add(void *volatile _Nullable *_Nonnull p, intptr_t i)
31 {
32  return __atomic_add_fetch(p, i, __ATOMIC_RELAXED);
33 }
34 
35 static OF_INLINE int
36 of_atomic_int_sub(volatile int *_Nonnull p, int i)
37 {
38  return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED);
39 }
40 
41 static OF_INLINE int32_t
42 of_atomic_int32_sub(volatile int32_t *_Nonnull p, int32_t i)
43 {
44  return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED);
45 }
46 
47 static OF_INLINE void *_Nullable
48 of_atomic_ptr_sub(void *volatile _Nullable *_Nonnull p, intptr_t i)
49 {
50  return __atomic_sub_fetch(p, i, __ATOMIC_RELAXED);
51 }
52 
53 static OF_INLINE int
54 of_atomic_int_inc(volatile int *_Nonnull p)
55 {
56  return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED);
57 }
58 
59 static OF_INLINE int32_t
60 of_atomic_int32_inc(volatile int32_t *_Nonnull p)
61 {
62  return __atomic_add_fetch(p, 1, __ATOMIC_RELAXED);
63 }
64 
65 static OF_INLINE int
66 of_atomic_int_dec(volatile int *_Nonnull p)
67 {
68  return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED);
69 }
70 
71 static OF_INLINE int32_t
72 of_atomic_int32_dec(volatile int32_t *_Nonnull p)
73 {
74  return __atomic_sub_fetch(p, 1, __ATOMIC_RELAXED);
75 }
76 
77 static OF_INLINE unsigned int
78 of_atomic_int_or(volatile unsigned int *_Nonnull p, unsigned int i)
79 {
80  return __atomic_or_fetch(p, i, __ATOMIC_RELAXED);
81 }
82 
83 static OF_INLINE uint32_t
84 of_atomic_int32_or(volatile uint32_t *_Nonnull p, uint32_t i)
85 {
86  return __atomic_or_fetch(p, i, __ATOMIC_RELAXED);
87 }
88 
89 static OF_INLINE unsigned int
90 of_atomic_int_and(volatile unsigned int *_Nonnull p, unsigned int i)
91 {
92  return __atomic_and_fetch(p, i, __ATOMIC_RELAXED);
93 }
94 
95 static OF_INLINE uint32_t
96 of_atomic_int32_and(volatile uint32_t *_Nonnull p, uint32_t i)
97 {
98  return __atomic_and_fetch(p, i, __ATOMIC_RELAXED);
99 }
100 
101 static OF_INLINE unsigned int
102 of_atomic_int_xor(volatile unsigned int *_Nonnull p, unsigned int i)
103 {
104  return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED);
105 }
106 
107 static OF_INLINE uint32_t
108 of_atomic_int32_xor(volatile uint32_t *_Nonnull p, uint32_t i)
109 {
110  return __atomic_xor_fetch(p, i, __ATOMIC_RELAXED);
111 }
112 
113 static OF_INLINE bool
114 of_atomic_int_cmpswap(volatile int *_Nonnull p, int o, int n)
115 {
116  return __atomic_compare_exchange(p, &o, &n, false,
117  __ATOMIC_RELAXED, __ATOMIC_RELAXED);
118 }
119 
120 static OF_INLINE bool
121 of_atomic_int32_cmpswap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
122 {
123  return __atomic_compare_exchange(p, &o, &n, false,
124  __ATOMIC_RELAXED, __ATOMIC_RELAXED);
125 }
126 
127 static OF_INLINE bool
128 of_atomic_ptr_cmpswap(void *volatile _Nullable *_Nonnull p,
129  void *_Nullable o, void *_Nullable n)
130 {
131  return __atomic_compare_exchange(p, &o, &n, false,
132  __ATOMIC_RELAXED, __ATOMIC_RELAXED);
133 }
134 
135 static OF_INLINE void
136 of_memory_barrier_full(void)
137 {
138  __atomic_thread_fence(__ATOMIC_SEQ_CST);
139 }
140 
141 static OF_INLINE void
142 of_memory_barrier_acquire(void)
143 {
144  __atomic_thread_fence(__ATOMIC_ACQUIRE);
145 }
146 
147 static OF_INLINE void
148 of_memory_barrier_release(void)
149 {
150  __atomic_thread_fence(__ATOMIC_RELEASE);
151 }