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