ObjFW
OFAtomic.h
1 /*
2  * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
3  *
4  * All rights reserved.
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License version 3.0 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13  * version 3.0 for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * version 3.0 along with this program. If not, see
17  * <https://www.gnu.org/licenses/>.
18  */
19 
20 #include <stdlib.h>
21 
22 #import "macros.h"
23 
24 #ifndef OF_HAVE_ATOMIC_OPS
25 # error No atomic operations available!
26 #endif
27 
28 #if !defined(OF_HAVE_THREADS)
29 static OF_INLINE int
30 OFAtomicIntAdd(volatile int *_Nonnull p, int i)
31 {
32  return (*p += i);
33 }
34 
35 static OF_INLINE int32_t
36 OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
37 {
38  return (*p += i);
39 }
40 
41 static OF_INLINE void *_Nullable
42 OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
43 {
44  return (*(char *volatile *)p += i);
45 }
46 
47 static OF_INLINE int
48 OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
49 {
50  return (*p -= i);
51 }
52 
53 static OF_INLINE int32_t
54 OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
55 {
56  return (*p -= i);
57 }
58 
59 static OF_INLINE void *_Nullable
60 OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
61 {
62  return (*(char *volatile *)p -= i);
63 }
64 
65 static OF_INLINE int
66 OFAtomicIntIncrease(volatile int *_Nonnull p)
67 {
68  return ++*p;
69 }
70 
71 static OF_INLINE int32_t
72 OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
73 {
74  return ++*p;
75 }
76 
77 static OF_INLINE int
78 OFAtomicIntDecrease(volatile int *_Nonnull p)
79 {
80  return --*p;
81 }
82 
83 static OF_INLINE int32_t
84 OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
85 {
86  return --*p;
87 }
88 
89 static OF_INLINE unsigned int
90 OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
91 {
92  return (*p |= i);
93 }
94 
95 static OF_INLINE uint32_t
96 OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
97 {
98  return (*p |= i);
99 }
100 
101 static OF_INLINE unsigned int
102 OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
103 {
104  return (*p &= i);
105 }
106 
107 static OF_INLINE uint32_t
108 OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
109 {
110  return (*p &= i);
111 }
112 
113 static OF_INLINE unsigned int
114 OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
115 {
116  return (*p ^= i);
117 }
118 
119 static OF_INLINE uint32_t
120 OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
121 {
122  return (*p ^= i);
123 }
124 
125 static OF_INLINE bool
126 OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
127 {
128  if (*p == o) {
129  *p = n;
130  return true;
131  }
132 
133  return false;
134 }
135 
136 static OF_INLINE bool
137 OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
138 {
139  if (*p == o) {
140  *p = n;
141  return true;
142  }
143 
144  return false;
145 }
146 
147 static OF_INLINE bool
148 OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
149  void *_Nullable o, void *_Nullable n)
150 {
151  if (*p == o) {
152  *p = n;
153  return true;
154  }
155 
156  return false;
157 }
158 
159 static OF_INLINE void
160 OFMemoryBarrier(void)
161 {
162  /* nop */
163 }
164 
165 static OF_INLINE void
166 OFAcquireMemoryBarrier(void)
167 {
168  /* nop */
169 }
170 
171 static OF_INLINE void
172 OFReleaseMemoryBarrier(void)
173 {
174  /* nop */
175 }
176 #elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
177 # import "platform/x86/OFAtomic.h"
178 #elif defined(OF_POWERPC) && defined(__GNUC__) && !defined(__APPLE_CC__) && \
179  !defined(OF_AIX)
180 # import "platform/PowerPC/OFAtomic.h"
181 #elif defined(OF_HAVE_ATOMIC_BUILTINS)
182 # import "platform/GCC4.7/OFAtomic.h"
183 #elif defined(OF_HAVE_SYNC_BUILTINS)
184 # import "platform/GCC4/OFAtomic.h"
185 #elif defined(OF_HAVE_OSATOMIC)
186 # import "platform/macOS/OFAtomic.h"
187 #else
188 # error No atomic operations available!
189 #endif