diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2020-09-23 11:56:46 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2020-09-23 16:07:44 +0100 |
commit | d73415a315471ac0b127ed3fad45c8ec5d711de1 (patch) | |
tree | bae20b3a39968fdfb4340b1a39b533333a8e6fd0 /docs/devel | |
parent | ed7db34b5aedba4487fd949b2e545eef954f093e (diff) |
qemu/atomic.h: rename atomic_ to qatomic_
clang's C11 atomic_fetch_*() functions only take a C11 atomic type
pointer argument. QEMU uses direct types (int, etc) and this causes a
compiler error when a QEMU code calls these functions in a source file
that also included <stdatomic.h> via a system header file:
$ CC=clang CXX=clang++ ./configure ... && make
../util/async.c:79:17: error: address argument to atomic operation must be a pointer to _Atomic type ('unsigned int *' invalid)
Avoid using atomic_*() names in QEMU's atomic.h since that namespace is
used by <stdatomic.h>. Prefix QEMU's APIs with 'q' so that atomic.h
and <stdatomic.h> can co-exist. I checked /usr/include on my machine and
searched GitHub for existing "qatomic_" users but there seem to be none.
This patch was generated using:
$ git grep -h -o '\<atomic\(64\)\?_[a-z0-9_]\+' include/qemu/atomic.h | \
sort -u >/tmp/changed_identifiers
$ for identifier in $(</tmp/changed_identifiers); do
sed -i "s%\<$identifier\>%q$identifier%g" \
$(git grep -I -l "\<$identifier\>")
done
I manually fixed line-wrap issues and misaligned rST tables.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200923105646.47864-1-stefanha@redhat.com>
Diffstat (limited to 'docs/devel')
-rw-r--r-- | docs/devel/atomics.rst | 136 | ||||
-rw-r--r-- | docs/devel/lockcnt.txt | 8 | ||||
-rw-r--r-- | docs/devel/rcu.txt | 34 |
3 files changed, 89 insertions, 89 deletions
diff --git a/docs/devel/atomics.rst b/docs/devel/atomics.rst index 445c3b3503..52baa0736d 100644 --- a/docs/devel/atomics.rst +++ b/docs/devel/atomics.rst @@ -23,9 +23,9 @@ provides macros that fall in three camps: - compiler barriers: ``barrier()``; -- weak atomic access and manual memory barriers: ``atomic_read()``, - ``atomic_set()``, ``smp_rmb()``, ``smp_wmb()``, ``smp_mb()``, ``smp_mb_acquire()``, - ``smp_mb_release()``, ``smp_read_barrier_depends()``; +- weak atomic access and manual memory barriers: ``qatomic_read()``, + ``qatomic_set()``, ``smp_rmb()``, ``smp_wmb()``, ``smp_mb()``, + ``smp_mb_acquire()``, ``smp_mb_release()``, ``smp_read_barrier_depends()``; - sequentially consistent atomic access: everything else. @@ -67,23 +67,23 @@ in the order specified by its program". ``qemu/atomic.h`` provides the following set of atomic read-modify-write operations:: - void atomic_inc(ptr) - void atomic_dec(ptr) - void atomic_add(ptr, val) - void atomic_sub(ptr, val) - void atomic_and(ptr, val) - void atomic_or(ptr, val) - - typeof(*ptr) atomic_fetch_inc(ptr) - typeof(*ptr) atomic_fetch_dec(ptr) - typeof(*ptr) atomic_fetch_add(ptr, val) - typeof(*ptr) atomic_fetch_sub(ptr, val) - typeof(*ptr) atomic_fetch_and(ptr, val) - typeof(*ptr) atomic_fetch_or(ptr, val) - typeof(*ptr) atomic_fetch_xor(ptr, val) - typeof(*ptr) atomic_fetch_inc_nonzero(ptr) - typeof(*ptr) atomic_xchg(ptr, val) - typeof(*ptr) atomic_cmpxchg(ptr, old, new) + void qatomic_inc(ptr) + void qatomic_dec(ptr) + void qatomic_add(ptr, val) + void qatomic_sub(ptr, val) + void qatomic_and(ptr, val) + void qatomic_or(ptr, val) + + typeof(*ptr) qatomic_fetch_inc(ptr) + typeof(*ptr) qatomic_fetch_dec(ptr) + typeof(*ptr) qatomic_fetch_add(ptr, val) + typeof(*ptr) qatomic_fetch_sub(ptr, val) + typeof(*ptr) qatomic_fetch_and(ptr, val) + typeof(*ptr) qatomic_fetch_or(ptr, val) + typeof(*ptr) qatomic_fetch_xor(ptr, val) + typeof(*ptr) qatomic_fetch_inc_nonzero(ptr) + typeof(*ptr) qatomic_xchg(ptr, val) + typeof(*ptr) qatomic_cmpxchg(ptr, old, new) all of which return the old value of ``*ptr``. These operations are polymorphic; they operate on any type that is as wide as a pointer or @@ -91,19 +91,19 @@ smaller. Similar operations return the new value of ``*ptr``:: - typeof(*ptr) atomic_inc_fetch(ptr) - typeof(*ptr) atomic_dec_fetch(ptr) - typeof(*ptr) atomic_add_fetch(ptr, val) - typeof(*ptr) atomic_sub_fetch(ptr, val) - typeof(*ptr) atomic_and_fetch(ptr, val) - typeof(*ptr) atomic_or_fetch(ptr, val) - typeof(*ptr) atomic_xor_fetch(ptr, val) + typeof(*ptr) qatomic_inc_fetch(ptr) + typeof(*ptr) qatomic_dec_fetch(ptr) + typeof(*ptr) qatomic_add_fetch(ptr, val) + typeof(*ptr) qatomic_sub_fetch(ptr, val) + typeof(*ptr) qatomic_and_fetch(ptr, val) + typeof(*ptr) qatomic_or_fetch(ptr, val) + typeof(*ptr) qatomic_xor_fetch(ptr, val) ``qemu/atomic.h`` also provides loads and stores that cannot be reordered with each other:: - typeof(*ptr) atomic_mb_read(ptr) - void atomic_mb_set(ptr, val) + typeof(*ptr) qatomic_mb_read(ptr) + void qatomic_mb_set(ptr, val) However these do not provide sequential consistency and, in particular, they do not participate in the total ordering enforced by @@ -115,11 +115,11 @@ easiest to hardest): - lightweight synchronization primitives such as ``QemuEvent`` -- RCU operations (``atomic_rcu_read``, ``atomic_rcu_set``) when publishing +- RCU operations (``qatomic_rcu_read``, ``qatomic_rcu_set``) when publishing or accessing a new version of a data structure -- other atomic accesses: ``atomic_read`` and ``atomic_load_acquire`` for - loads, ``atomic_set`` and ``atomic_store_release`` for stores, ``smp_mb`` +- other atomic accesses: ``qatomic_read`` and ``qatomic_load_acquire`` for + loads, ``qatomic_set`` and ``qatomic_store_release`` for stores, ``smp_mb`` to forbid reordering subsequent loads before a store. @@ -149,22 +149,22 @@ The only guarantees that you can rely upon in this case are: When using this model, variables are accessed with: -- ``atomic_read()`` and ``atomic_set()``; these prevent the compiler from +- ``qatomic_read()`` and ``qatomic_set()``; these prevent the compiler from optimizing accesses out of existence and creating unsolicited accesses, but do not otherwise impose any ordering on loads and stores: both the compiler and the processor are free to reorder them. -- ``atomic_load_acquire()``, which guarantees the LOAD to appear to +- ``qatomic_load_acquire()``, which guarantees the LOAD to appear to happen, with respect to the other components of the system, before all the LOAD or STORE operations specified afterwards. - Operations coming before ``atomic_load_acquire()`` can still be + Operations coming before ``qatomic_load_acquire()`` can still be reordered after it. -- ``atomic_store_release()``, which guarantees the STORE to appear to +- ``qatomic_store_release()``, which guarantees the STORE to appear to happen, with respect to the other components of the system, after all the LOAD or STORE operations specified before. - Operations coming after ``atomic_store_release()`` can still be + Operations coming after ``qatomic_store_release()`` can still be reordered before it. Restrictions to the ordering of accesses can also be specified @@ -229,7 +229,7 @@ They come in six kinds: dependency and a full read barrier or better is required. -Memory barriers and ``atomic_load_acquire``/``atomic_store_release`` are +Memory barriers and ``qatomic_load_acquire``/``qatomic_store_release`` are mostly used when a data structure has one thread that is always a writer and one thread that is always a reader: @@ -238,8 +238,8 @@ and one thread that is always a reader: +==================================+==================================+ | :: | :: | | | | - | atomic_store_release(&a, x); | y = atomic_load_acquire(&b); | - | atomic_store_release(&b, y); | x = atomic_load_acquire(&a); | + | qatomic_store_release(&a, x); | y = qatomic_load_acquire(&b); | + | qatomic_store_release(&b, y); | x = qatomic_load_acquire(&a); | +----------------------------------+----------------------------------+ In this case, correctness is easy to check for using the "pairing" @@ -258,14 +258,14 @@ outside a loop. For example: | | | | n = 0; | n = 0; | | for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) | - | n += atomic_load_acquire(&a[i]); | n += atomic_read(&a[i]); | + | n += qatomic_load_acquire(&a[i]); | n += qatomic_read(&a[i]); | | | smp_mb_acquire(); | +------------------------------------------+----------------------------------+ | :: | :: | | | | | | smp_mb_release(); | | for (i = 0; i < 10; i++) | for (i = 0; i < 10; i++) | - | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); | + | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); | +------------------------------------------+----------------------------------+ Splitting a loop can also be useful to reduce the number of barriers: @@ -277,11 +277,11 @@ Splitting a loop can also be useful to reduce the number of barriers: | | | | n = 0; | smp_mb_release(); | | for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) | - | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); | + | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); | | smp_mb(); | smb_mb(); | - | n += atomic_read(&b[i]); | n = 0; | + | n += qatomic_read(&b[i]); | n = 0; | | } | for (i = 0; i < 10; i++) | - | | n += atomic_read(&b[i]); | + | | n += qatomic_read(&b[i]); | +------------------------------------------+----------------------------------+ In this case, a ``smp_mb_release()`` is also replaced with a (possibly cheaper, and clearer @@ -294,10 +294,10 @@ as well) ``smp_wmb()``: | | | | | smp_mb_release(); | | for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) | - | atomic_store_release(&a[i], false); | atomic_set(&a[i], false); | - | atomic_store_release(&b[i], false); | smb_wmb(); | + | qatomic_store_release(&a[i], false); | qatomic_set(&a[i], false); | + | qatomic_store_release(&b[i], false); | smb_wmb(); | | } | for (i = 0; i < 10; i++) | - | | atomic_set(&b[i], false); | + | | qatomic_set(&b[i], false); | +------------------------------------------+----------------------------------+ @@ -306,7 +306,7 @@ as well) ``smp_wmb()``: Acquire/release pairing and the *synchronizes-with* relation ------------------------------------------------------------ -Atomic operations other than ``atomic_set()`` and ``atomic_read()`` have +Atomic operations other than ``qatomic_set()`` and ``qatomic_read()`` have either *acquire* or *release* semantics [#rmw]_. This has two effects: .. [#rmw] Read-modify-write operations can have both---acquire applies to the @@ -357,16 +357,16 @@ thread 2 is relying on the *synchronizes-with* relation between ``pthread_exit`` Synchronization between threads basically descends from this pairing of a release operation and an acquire operation. Therefore, atomic operations -other than ``atomic_set()`` and ``atomic_read()`` will almost always be +other than ``qatomic_set()`` and ``qatomic_read()`` will almost always be paired with another operation of the opposite kind: an acquire operation will pair with a release operation and vice versa. This rule of thumb is extremely useful; in the case of QEMU, however, note that the other operation may actually be in a driver that runs in the guest! ``smp_read_barrier_depends()``, ``smp_rmb()``, ``smp_mb_acquire()``, -``atomic_load_acquire()`` and ``atomic_rcu_read()`` all count +``qatomic_load_acquire()`` and ``qatomic_rcu_read()`` all count as acquire operations. ``smp_wmb()``, ``smp_mb_release()``, -``atomic_store_release()`` and ``atomic_rcu_set()`` all count as release +``qatomic_store_release()`` and ``qatomic_rcu_set()`` all count as release operations. ``smp_mb()`` counts as both acquire and release, therefore it can pair with any other atomic operation. Here is an example: @@ -375,11 +375,11 @@ it can pair with any other atomic operation. Here is an example: +======================+==============================+ | :: | :: | | | | - | atomic_set(&a, 1); | | + | qatomic_set(&a, 1);| | | smp_wmb(); | | - | atomic_set(&b, 2); | x = atomic_read(&b); | + | qatomic_set(&b, 2);| x = qatomic_read(&b); | | | smp_rmb(); | - | | y = atomic_read(&a); | + | | y = qatomic_read(&a); | +----------------------+------------------------------+ Note that a load-store pair only counts if the two operations access the @@ -393,9 +393,9 @@ correct synchronization: +================================+================================+ | :: | :: | | | | - | atomic_set(&a, 1); | | - | atomic_store_release(&b, 2); | x = atomic_load_acquire(&b); | - | | y = atomic_read(&a); | + | qatomic_set(&a, 1); | | + | qatomic_store_release(&b, 2);| x = qatomic_load_acquire(&b);| + | | y = qatomic_read(&a); | +--------------------------------+--------------------------------+ Acquire and release semantics of higher-level primitives can also be @@ -421,7 +421,7 @@ cannot be a data race: | smp_wmb(); | | | x->i = 2; | | | smp_wmb(); | | - | atomic_set(&a, x); | x = atomic_read(&a); | + | qatomic_set(&a, x);| x = qatomic_read(&a); | | | smp_read_barrier_depends(); | | | y = x->i; | | | smp_read_barrier_depends(); | @@ -442,7 +442,7 @@ and memory barriers, and the equivalents in QEMU: at all. Linux 4.1 updated them to implement volatile semantics via ``ACCESS_ONCE`` (or the more recent ``READ``/``WRITE_ONCE``). - QEMU's ``atomic_read`` and ``atomic_set`` implement C11 atomic relaxed + QEMU's ``qatomic_read`` and ``qatomic_set`` implement C11 atomic relaxed semantics if the compiler supports it, and volatile semantics otherwise. Both semantics prevent the compiler from doing certain transformations; the difference is that atomic accesses are guaranteed to be atomic, @@ -451,8 +451,8 @@ and memory barriers, and the equivalents in QEMU: since we assume the variables passed are machine-word sized and properly aligned. - No barriers are implied by ``atomic_read`` and ``atomic_set`` in either Linux - or QEMU. + No barriers are implied by ``qatomic_read`` and ``qatomic_set`` in either + Linux or QEMU. - atomic read-modify-write operations in Linux are of three kinds: @@ -469,7 +469,7 @@ and memory barriers, and the equivalents in QEMU: a different set of memory barriers; in QEMU, all of them enforce sequential consistency. -- in QEMU, ``atomic_read()`` and ``atomic_set()`` do not participate in +- in QEMU, ``qatomic_read()`` and ``qatomic_set()`` do not participate in the total ordering enforced by sequentially-consistent operations. This is because QEMU uses the C11 memory model. The following example is correct in Linux but not in QEMU: @@ -479,8 +479,8 @@ and memory barriers, and the equivalents in QEMU: +==================================+================================+ | :: | :: | | | | - | a = atomic_fetch_add(&x, 2); | a = atomic_fetch_add(&x, 2); | - | b = READ_ONCE(&y); | b = atomic_read(&y); | + | a = atomic_fetch_add(&x, 2); | a = qatomic_fetch_add(&x, 2);| + | b = READ_ONCE(&y); | b = qatomic_read(&y); | +----------------------------------+--------------------------------+ because the read of ``y`` can be moved (by either the processor or the @@ -495,10 +495,10 @@ and memory barriers, and the equivalents in QEMU: +================================+ | :: | | | - | a = atomic_read(&x); | - | atomic_set(&x, a + 2); | + | a = qatomic_read(&x); | + | qatomic_set(&x, a + 2); | | smp_mb(); | - | b = atomic_read(&y); | + | b = qatomic_read(&y); | +--------------------------------+ Sources diff --git a/docs/devel/lockcnt.txt b/docs/devel/lockcnt.txt index 7c099bc6c8..2d85462fe3 100644 --- a/docs/devel/lockcnt.txt +++ b/docs/devel/lockcnt.txt @@ -95,7 +95,7 @@ not just frees, though there could be cases where this is not necessary. Reads, instead, can be done without taking the mutex, as long as the readers and writers use the same macros that are used for RCU, for -example atomic_rcu_read, atomic_rcu_set, QLIST_FOREACH_RCU, etc. This is +example qatomic_rcu_read, qatomic_rcu_set, QLIST_FOREACH_RCU, etc. This is because the reads are done outside a lock and a set or QLIST_INSERT_HEAD can happen concurrently with the read. The RCU API ensures that the processor and the compiler see all required memory barriers. @@ -189,7 +189,7 @@ qemu_lockcnt_lock and qemu_lockcnt_unlock: if (!xyz) { new_xyz = g_new(XYZ, 1); ... - atomic_rcu_set(&xyz, new_xyz); + qatomic_rcu_set(&xyz, new_xyz); } qemu_lockcnt_unlock(&xyz_lockcnt); @@ -198,7 +198,7 @@ qemu_lockcnt_dec: qemu_lockcnt_inc(&xyz_lockcnt); if (xyz) { - XYZ *p = atomic_rcu_read(&xyz); + XYZ *p = qatomic_rcu_read(&xyz); ... /* Accesses can now be done through "p". */ } @@ -222,7 +222,7 @@ the decrement, the locking and the check on count as follows: qemu_lockcnt_inc(&xyz_lockcnt); if (xyz) { - XYZ *p = atomic_rcu_read(&xyz); + XYZ *p = qatomic_rcu_read(&xyz); ... /* Accesses can now be done through "p". */ } diff --git a/docs/devel/rcu.txt b/docs/devel/rcu.txt index 0ce15ba198..cdf002edd8 100644 --- a/docs/devel/rcu.txt +++ b/docs/devel/rcu.txt @@ -130,13 +130,13 @@ The core RCU API is small: g_free_rcu(&foo, rcu); - typeof(*p) atomic_rcu_read(p); + typeof(*p) qatomic_rcu_read(p); - atomic_rcu_read() is similar to atomic_load_acquire(), but it makes + qatomic_rcu_read() is similar to qatomic_load_acquire(), but it makes some assumptions on the code that calls it. This allows a more optimized implementation. - atomic_rcu_read assumes that whenever a single RCU critical + qatomic_rcu_read assumes that whenever a single RCU critical section reads multiple shared data, these reads are either data-dependent or need no ordering. This is almost always the case when using RCU, because read-side critical sections typically @@ -144,7 +144,7 @@ The core RCU API is small: every update) until reaching a data structure of interest, and then read from there. - RCU read-side critical sections must use atomic_rcu_read() to + RCU read-side critical sections must use qatomic_rcu_read() to read data, unless concurrent writes are prevented by another synchronization mechanism. @@ -152,18 +152,18 @@ The core RCU API is small: data structure in a single direction, opposite to the direction in which the updater initializes it. - void atomic_rcu_set(p, typeof(*p) v); + void qatomic_rcu_set(p, typeof(*p) v); - atomic_rcu_set() is similar to atomic_store_release(), though it also + qatomic_rcu_set() is similar to qatomic_store_release(), though it also makes assumptions on the code that calls it in order to allow a more optimized implementation. - In particular, atomic_rcu_set() suffices for synchronization + In particular, qatomic_rcu_set() suffices for synchronization with readers, if the updater never mutates a field within a data item that is already accessible to readers. This is the case when initializing a new copy of the RCU-protected data structure; just ensure that initialization of *p is carried out - before atomic_rcu_set() makes the data item visible to readers. + before qatomic_rcu_set() makes the data item visible to readers. If this rule is observed, writes will happen in the opposite order as reads in the RCU read-side critical sections (or if there is just one update), and there will be no need for other @@ -212,7 +212,7 @@ DIFFERENCES WITH LINUX programming; not allowing this would prevent upgrading an RCU read-side critical section to become an updater. -- atomic_rcu_read and atomic_rcu_set replace rcu_dereference and +- qatomic_rcu_read and qatomic_rcu_set replace rcu_dereference and rcu_assign_pointer. They take a _pointer_ to the variable being accessed. - call_rcu is a macro that has an extra argument (the name of the first @@ -257,7 +257,7 @@ may be used as a restricted reference-counting mechanism. For example, consider the following code fragment: rcu_read_lock(); - p = atomic_rcu_read(&foo); + p = qatomic_rcu_read(&foo); /* do something with p. */ rcu_read_unlock(); @@ -268,7 +268,7 @@ The write side looks simply like this (with appropriate locking): qemu_mutex_lock(&foo_mutex); old = foo; - atomic_rcu_set(&foo, new); + qatomic_rcu_set(&foo, new); qemu_mutex_unlock(&foo_mutex); synchronize_rcu(); free(old); @@ -277,7 +277,7 @@ If the processing cannot be done purely within the critical section, it is possible to combine this idiom with a "real" reference count: rcu_read_lock(); - p = atomic_rcu_read(&foo); + p = qatomic_rcu_read(&foo); foo_ref(p); rcu_read_unlock(); /* do something with p. */ @@ -287,7 +287,7 @@ The write side can be like this: qemu_mutex_lock(&foo_mutex); old = foo; - atomic_rcu_set(&foo, new); + qatomic_rcu_set(&foo, new); qemu_mutex_unlock(&foo_mutex); synchronize_rcu(); foo_unref(old); @@ -296,7 +296,7 @@ or with call_rcu: qemu_mutex_lock(&foo_mutex); old = foo; - atomic_rcu_set(&foo, new); + qatomic_rcu_set(&foo, new); qemu_mutex_unlock(&foo_mutex); call_rcu(foo_unref, old, rcu); @@ -307,7 +307,7 @@ last reference may be dropped on the read side. Hence you can use call_rcu() instead: foo_unref(struct foo *p) { - if (atomic_fetch_dec(&p->refcount) == 1) { + if (qatomic_fetch_dec(&p->refcount) == 1) { call_rcu(foo_destroy, p, rcu); } } @@ -375,7 +375,7 @@ Instead, we store the size of the array with the array itself: read side: rcu_read_lock(); - struct arr *array = atomic_rcu_read(&global_array); + struct arr *array = qatomic_rcu_read(&global_array); x = i < array->size ? array->data[i] : -1; rcu_read_unlock(); return x; @@ -392,7 +392,7 @@ Instead, we store the size of the array with the array itself: /* Removal phase. */ old_array = global_array; - atomic_rcu_set(&new_array->data, new_array); + qatomic_rcu_set(&new_array->data, new_array); synchronize_rcu(); /* Reclamation phase. */ |