File: uatomic-api.md

package info (click to toggle)
liburcu 0.15.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,356 kB
  • sloc: ansic: 23,361; xml: 23,227; sh: 6,480; makefile: 1,045; cpp: 15
file content (131 lines) | stat: -rw-r--r-- 4,506 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!--
SPDX-FileCopyrightText: 2023 EfficiOS Inc.

SPDX-License-Identifier: CC-BY-4.0
-->

Userspace RCU Atomic Operations API
===================================

by Mathieu Desnoyers and Paul E. McKenney

This document describes the `<urcu/uatomic.h>` API. Those are the atomic
operations provided by the Userspace RCU library. The general rule
regarding memory barriers is that only `uatomic_xchg()`,
`uatomic_cmpxchg()`, `uatomic_add_return()`, and `uatomic_sub_return()` imply
full memory barriers before and after the atomic operation. Other
primitives don't guarantee any memory barrier.

Only atomic operations performed on integers (`int` and `long`, signed
and unsigned) are supported on all architectures. Some architectures
also support 1-byte, 2-byte and 8-byte atomic operations. Those respectively
have `UATOMIC_HAS_ATOMIC_BYTE`, `UATOMIC_HAS_ATOMIC_SHORT` and
`UATOMIC_HAS_ATOMIC_LLONG` defined when `uatomic.h` is included. Trying to
perform an atomic operation on a type size not supported by the architecture
will result in a static assert at compile time.

In the description below, `type` is a type that can be atomically
written to by the architecture. It needs to be at most word-sized, and
its alignment needs to greater or equal to its size.


API
---

```c
void uatomic_set(type *addr, type v);
```

Atomically write `v` into `addr`. By "atomically", we mean that no
concurrent operation that reads from addr will see partial
effects of `uatomic_set()`.


```c
type uatomic_read(type *addr);
```

Atomically read `v` from `addr`. By "atomically", we mean that
`uatomic_read()` cannot see a partial effect of any concurrent
uatomic update.


```c
type uatomic_cmpxchg(type *addr, type old, type new);
```

An atomic read-modify-write operation that performs this
sequence of operations atomically: check if `addr` contains `old`.
If true, then replace the content of `addr` by `new`. Return the
value previously contained by `addr`. This function implies a full
memory barrier before and after the atomic operation on success.
On failure, no memory order is guaranteed.


```c
type uatomic_xchg(type *addr, type new);
```

An atomic read-modify-write operation that performs this sequence
of operations atomically: replace the content of `addr` by `new`,
and return the value previously contained by `addr`. This
function implies a full memory barrier before and after the atomic
operation.


```c
type uatomic_add_return(type *addr, type v);
type uatomic_sub_return(type *addr, type v);
```

An atomic read-modify-write operation that performs this
sequence of operations atomically: increment/decrement the
content of `addr` by `v`, and return the resulting value. This
function implies a full memory barrier before and after the atomic
operation.


```c
void uatomic_and(type *addr, type mask);
void uatomic_or(type *addr, type mask);
```

Atomically write the result of bitwise "and"/"or" between the
content of `addr` and `mask` into `addr`.

These operations do not necessarily imply memory barriers.
If memory barriers are needed, they may be provided by explicitly using
`cmm_smp_mb__before_uatomic_and()`, `cmm_smp_mb__after_uatomic_and()`,
`cmm_smp_mb__before_uatomic_or()`, and `cmm_smp_mb__after_uatomic_or()`.
These explicit barriers are no-ops on architectures in which the underlying
atomic instructions implicitly supply the needed memory barriers.


```c
void uatomic_add(type *addr, type v);
void uatomic_sub(type *addr, type v);
```

Atomically increment/decrement the content of `addr` by `v`.
These operations do not necessarily imply memory barriers.
If memory barriers are needed, they may be provided by
explicitly using `cmm_smp_mb__before_uatomic_add()`,
`cmm_smp_mb__after_uatomic_add()`, `cmm_smp_mb__before_uatomic_sub()`, and
`cmm_smp_mb__after_uatomic_sub()`. These explicit barriers are
no-ops on architectures in which the underlying atomic
instructions implicitly supply the needed memory barriers.


```c
void uatomic_inc(type *addr);
void uatomic_dec(type *addr);
```

Atomically increment/decrement the content of `addr` by 1.
These operations do not necessarily imply memory barriers.
If memory barriers are needed, they may be provided by
explicitly using `cmm_smp_mb__before_uatomic_inc()`,
`cmm_smp_mb__after_uatomic_inc()`, `cmm_smp_mb__before_uatomic_dec()`,
and `cmm_smp_mb__after_uatomic_dec()`. These explicit barriers are
no-ops on architectures in which the underlying atomic
instructions implicitly supply the needed memory barriers.