PostgreSQL Source Code git master
Loading...
Searching...
No Matches
generic.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * generic.h
4 * Implement higher level operations based on some lower level atomic
5 * operations.
6 *
7 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * src/include/port/atomics/generic.h
11 *
12 *-------------------------------------------------------------------------
13 */
14
15/* intentionally no include guards, should only be included by atomics.h */
16#ifndef INSIDE_ATOMICS_H
17# error "should be included via atomics.h"
18#endif
19
20/*
21 * If read or write barriers are undefined, we upgrade them to full memory
22 * barriers.
23 */
24#if !defined(pg_read_barrier_impl)
25# define pg_read_barrier_impl pg_memory_barrier_impl
26#endif
27#if !defined(pg_write_barrier_impl)
28# define pg_write_barrier_impl pg_memory_barrier_impl
29#endif
30
31/* provide fallback */
32#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) && defined(PG_HAVE_ATOMIC_U32_SUPPORT)
33#define PG_HAVE_ATOMIC_FLAG_SUPPORT
35#endif
36
37#ifndef PG_HAVE_ATOMIC_READ_U32
38#define PG_HAVE_ATOMIC_READ_U32
39static inline uint32
41{
42 return ptr->value;
43}
44#endif
45
46#ifndef PG_HAVE_ATOMIC_WRITE_U32
47#define PG_HAVE_ATOMIC_WRITE_U32
48static inline void
50{
51 ptr->value = val;
52}
53#endif
54
55#ifndef PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32
56#define PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32
57static inline void
62#endif
63
64/*
65 * provide fallback for test_and_set using atomic_exchange if available
66 */
67#if !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) && defined(PG_HAVE_ATOMIC_EXCHANGE_U32)
68
69#define PG_HAVE_ATOMIC_INIT_FLAG
70static inline void
72{
74}
75
76#define PG_HAVE_ATOMIC_TEST_SET_FLAG
77static inline bool
79{
80 return pg_atomic_exchange_u32_impl(ptr, 1) == 0;
81}
82
83#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
84static inline bool
86{
87 return pg_atomic_read_u32_impl(ptr) == 0;
88}
89
90
91#define PG_HAVE_ATOMIC_CLEAR_FLAG
92static inline void
94{
95 /* XXX: release semantics suffice? */
98}
99
100/*
101 * provide fallback for test_and_set using atomic_compare_exchange if
102 * available.
103 */
104#elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
105
106#define PG_HAVE_ATOMIC_INIT_FLAG
107static inline void
109{
111}
112
113#define PG_HAVE_ATOMIC_TEST_SET_FLAG
114static inline bool
116{
117 uint32 value = 0;
119}
120
121#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
122static inline bool
124{
125 return pg_atomic_read_u32_impl(ptr) == 0;
126}
127
128#define PG_HAVE_ATOMIC_CLEAR_FLAG
129static inline void
131{
132 /* XXX: release semantics suffice? */
135}
136
137#elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG)
138# error "No pg_atomic_test_and_set provided"
139#endif /* !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) */
140
141
142#ifndef PG_HAVE_ATOMIC_INIT_U32
143#define PG_HAVE_ATOMIC_INIT_U32
144static inline void
146{
147 ptr->value = val_;
148}
149#endif
150
151#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
152#define PG_HAVE_ATOMIC_EXCHANGE_U32
153static inline uint32
155{
156 uint32 old;
157 old = ptr->value; /* ok if read is not atomic */
159 /* skip */;
160 return old;
161}
162#endif
163
164#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
165#define PG_HAVE_ATOMIC_FETCH_ADD_U32
166static inline uint32
168{
169 uint32 old;
170 old = ptr->value; /* ok if read is not atomic */
172 /* skip */;
173 return old;
174}
175#endif
176
177#if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
178#define PG_HAVE_ATOMIC_FETCH_SUB_U32
179static inline uint32
181{
183}
184#endif
185
186#if !defined(PG_HAVE_ATOMIC_FETCH_AND_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
187#define PG_HAVE_ATOMIC_FETCH_AND_U32
188static inline uint32
190{
191 uint32 old;
192 old = ptr->value; /* ok if read is not atomic */
194 /* skip */;
195 return old;
196}
197#endif
198
199#if !defined(PG_HAVE_ATOMIC_FETCH_OR_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
200#define PG_HAVE_ATOMIC_FETCH_OR_U32
201static inline uint32
203{
204 uint32 old;
205 old = ptr->value; /* ok if read is not atomic */
207 /* skip */;
208 return old;
209}
210#endif
211
212#if !defined(PG_HAVE_ATOMIC_ADD_FETCH_U32) && defined(PG_HAVE_ATOMIC_FETCH_ADD_U32)
213#define PG_HAVE_ATOMIC_ADD_FETCH_U32
214static inline uint32
216{
218}
219#endif
220
221#if !defined(PG_HAVE_ATOMIC_SUB_FETCH_U32) && defined(PG_HAVE_ATOMIC_FETCH_SUB_U32)
222#define PG_HAVE_ATOMIC_SUB_FETCH_U32
223static inline uint32
225{
227}
228#endif
229
230#if !defined(PG_HAVE_ATOMIC_READ_MEMBARRIER_U32) && defined(PG_HAVE_ATOMIC_FETCH_ADD_U32)
231#define PG_HAVE_ATOMIC_READ_MEMBARRIER_U32
232static inline uint32
234{
235 return pg_atomic_fetch_add_u32_impl(ptr, 0);
236}
237#endif
238
239#if !defined(PG_HAVE_ATOMIC_WRITE_MEMBARRIER_U32) && defined(PG_HAVE_ATOMIC_EXCHANGE_U32)
240#define PG_HAVE_ATOMIC_WRITE_MEMBARRIER_U32
241static inline void
243{
245}
246#endif
247
248#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
249#define PG_HAVE_ATOMIC_EXCHANGE_U64
250static inline uint64
252{
253 uint64 old;
254 old = ptr->value; /* ok if read is not atomic */
256 /* skip */;
257 return old;
258}
259#endif
260
261#ifndef PG_HAVE_ATOMIC_WRITE_U64
262#define PG_HAVE_ATOMIC_WRITE_U64
263
264#if defined(PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY) && \
265 !defined(PG_HAVE_ATOMIC_U64_SIMULATION)
266
267static inline void
269{
270 /*
271 * On this platform aligned 64bit writes are guaranteed to be atomic,
272 * except if using the fallback implementation, where can't guarantee the
273 * required alignment.
274 */
276 ptr->value = val;
277}
278
279#else
280
281static inline void
283{
284 /*
285 * 64 bit writes aren't safe on all platforms. In the generic
286 * implementation implement them as an atomic exchange.
287 */
289}
290
291#endif /* PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY && !PG_HAVE_ATOMIC_U64_SIMULATION */
292#endif /* PG_HAVE_ATOMIC_WRITE_U64 */
293
294#ifndef PG_HAVE_ATOMIC_UNLOCKED_WRITE_U64
295#define PG_HAVE_ATOMIC_UNLOCKED_WRITE_U64
296static inline void
301#endif
302
303#ifndef PG_HAVE_ATOMIC_READ_U64
304#define PG_HAVE_ATOMIC_READ_U64
305
306#if defined(PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY) && \
307 !defined(PG_HAVE_ATOMIC_U64_SIMULATION)
308
309static inline uint64
311{
312 /*
313 * On this platform aligned 64-bit reads are guaranteed to be atomic.
314 */
316 return ptr->value;
317}
318
319#else
320
321static inline uint64
323{
324 uint64 old = 0;
325
326 /*
327 * 64-bit reads aren't atomic on all platforms. In the generic
328 * implementation implement them as a compare/exchange with 0. That'll
329 * fail or succeed, but always return the old value. Possibly might store
330 * a 0, but only if the previous value also was a 0 - i.e. harmless.
331 */
333
334 return old;
335}
336#endif /* PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY && !PG_HAVE_ATOMIC_U64_SIMULATION */
337#endif /* PG_HAVE_ATOMIC_READ_U64 */
338
339#ifndef PG_HAVE_ATOMIC_INIT_U64
340#define PG_HAVE_ATOMIC_INIT_U64
341static inline void
343{
344 ptr->value = val_;
345}
346#endif
347
348#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
349#define PG_HAVE_ATOMIC_FETCH_ADD_U64
350static inline uint64
352{
353 uint64 old;
354 old = ptr->value; /* ok if read is not atomic */
356 /* skip */;
357 return old;
358}
359#endif
360
361#if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
362#define PG_HAVE_ATOMIC_FETCH_SUB_U64
363static inline uint64
365{
367}
368#endif
369
370#if !defined(PG_HAVE_ATOMIC_FETCH_AND_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
371#define PG_HAVE_ATOMIC_FETCH_AND_U64
372static inline uint64
374{
375 uint64 old;
376 old = ptr->value; /* ok if read is not atomic */
378 /* skip */;
379 return old;
380}
381#endif
382
383#if !defined(PG_HAVE_ATOMIC_FETCH_OR_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
384#define PG_HAVE_ATOMIC_FETCH_OR_U64
385static inline uint64
387{
388 uint64 old;
389 old = ptr->value; /* ok if read is not atomic */
391 /* skip */;
392 return old;
393}
394#endif
395
396#if !defined(PG_HAVE_ATOMIC_ADD_FETCH_U64) && defined(PG_HAVE_ATOMIC_FETCH_ADD_U64)
397#define PG_HAVE_ATOMIC_ADD_FETCH_U64
398static inline uint64
400{
402}
403#endif
404
405#if !defined(PG_HAVE_ATOMIC_SUB_FETCH_U64) && defined(PG_HAVE_ATOMIC_FETCH_SUB_U64)
406#define PG_HAVE_ATOMIC_SUB_FETCH_U64
407static inline uint64
409{
411}
412#endif
413
414#if !defined(PG_HAVE_ATOMIC_READ_MEMBARRIER_U64) && defined(PG_HAVE_ATOMIC_FETCH_ADD_U64)
415#define PG_HAVE_ATOMIC_READ_MEMBARRIER_U64
416static inline uint64
418{
419 return pg_atomic_fetch_add_u64_impl(ptr, 0);
420}
421#endif
422
423#if !defined(PG_HAVE_ATOMIC_WRITE_MEMBARRIER_U64) && defined(PG_HAVE_ATOMIC_EXCHANGE_U64)
424#define PG_HAVE_ATOMIC_WRITE_MEMBARRIER_U64
425static inline void
427{
429}
430#endif
static bool pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition arch-ppc.h:80
static uint32 pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition arch-ppc.h:131
uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
Definition atomics.c:62
bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval)
Definition atomics.c:34
#define AssertPointerAlignment(ptr, bndr)
Definition c.h:1037
int64_t int64
Definition c.h:680
int32_t int32
Definition c.h:679
uint64_t uint64
Definition c.h:684
uint32_t uint32
Definition c.h:683
#define pg_memory_barrier_impl()
static uint32 pg_atomic_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 newval)
static void pg_atomic_unlocked_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition generic.h:58
static uint64 pg_atomic_read_u64_impl(volatile pg_atomic_uint64 *ptr)
Definition generic.h:322
static void pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition generic.h:49
static void pg_atomic_unlocked_write_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition generic.h:297
static void pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_)
Definition generic.h:342
static void pg_atomic_write_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition generic.h:282
static uint32 pg_atomic_read_u32_impl(volatile pg_atomic_uint32 *ptr)
Definition generic.h:40
static void pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_)
Definition generic.h:145
long val
Definition informix.c:689
static struct @175 value
static int fb(int x)
volatile uint32 value
Definition arch-ppc.h:31
volatile uint64 value
Definition fallback.h:29