PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
atomics.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * atomics.c
4  * Non-Inline parts of the atomics implementation
5  *
6  * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/port/atomics.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "miscadmin.h"
17 #include "port/atomics.h"
18 #include "storage/spin.h"
19 
20 
21 #ifdef PG_HAVE_ATOMIC_U64_SIMULATION
22 
23 void
24 pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_)
25 {
26  StaticAssertDecl(sizeof(ptr->sema) >= sizeof(slock_t),
27  "size mismatch of atomic_uint64 vs slock_t");
28 
29  SpinLockInit((slock_t *) &ptr->sema);
30  ptr->value = val_;
31 }
32 
33 bool
35  uint64 *expected, uint64 newval)
36 {
37  bool ret;
38 
39  /*
40  * Do atomic op under a spinlock. It might look like we could just skip
41  * the cmpxchg if the lock isn't available, but that'd just emulate a
42  * 'weak' compare and swap. I.e. one that allows spurious failures. Since
43  * several algorithms rely on a strong variant and that is efficiently
44  * implementable on most major architectures let's emulate it here as
45  * well.
46  */
47  SpinLockAcquire((slock_t *) &ptr->sema);
48 
49  /* perform compare/exchange logic */
50  ret = ptr->value == *expected;
51  *expected = ptr->value;
52  if (ret)
53  ptr->value = newval;
54 
55  /* and release lock */
56  SpinLockRelease((slock_t *) &ptr->sema);
57 
58  return ret;
59 }
60 
61 uint64
63 {
64  uint64 oldval;
65 
66  SpinLockAcquire((slock_t *) &ptr->sema);
67  oldval = ptr->value;
68  ptr->value += add_;
69  SpinLockRelease((slock_t *) &ptr->sema);
70  return oldval;
71 }
72 
73 #endif /* PG_HAVE_ATOMIC_U64_SIMULATION */
uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
Definition: atomics.c:62
void pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_)
Definition: atomics.c:24
bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval)
Definition: atomics.c:34
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:915
#define newval
#define SpinLockInit(lock)
Definition: spin.h:57
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
volatile uint64 value
Definition: fallback.h:29