mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 08:13:54 -06:00
Pull request
This includes the atomic_ -> qatomic_ rename that touches many files and is prone to conflicts. -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEhpWov9P5fNqsNXdanKSrs4Grc8gFAl9rcwsACgkQnKSrs4Gr c8hpqQf+OTxEVXMS/RfXRVjsM0RsgDYWyyW1OoA3/XEOt+OrJn4VrEbs7gbe3qxL rql73g1fysRSdoLBK1m4hJgZ2Ak5Bbwz26nnyA/quVZWKHqMXQaPTEQpJcGNvwiz WlZJvNLVkl3kTnM+eguad7TOoWfp9Uz/f/2Q8mbQ5Y9LZm3rEBZC2hG5KNJWRV1Y kdN6D1Y2l85LKd8219XChNCFJdj+ktGFQOIiWb8JG98shH2G+0rv9vhgYmat7qrh sSv2Ii+9ZGzxDCUYgpcSiu5CJVe3tqLBgzGnAKtohywGqzvdiZaHJJQipPn51W80 YyaDuuMObLwzkSOcfxK7DPM8IuJQVg== =+5d4 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging Pull request This includes the atomic_ -> qatomic_ rename that touches many files and is prone to conflicts. # gpg: Signature made Wed 23 Sep 2020 17:08:43 BST # gpg: using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [full] # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" [full] # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/block-pull-request: qemu/atomic.h: rename atomic_ to qatomic_ tests: add test-fdmon-epoll fdmon-poll: reset npfd when upgrading to fdmon-epoll gitmodules: add qemu.org vbootrom submodule gitmodules: switch to qemu.org meson mirror gitmodules: switch to qemu.org qboot mirror docs/system: clarify deprecation schedule virtio-crypto: don't modify elem->in/out_sg virtio-blk: undo destructive iov_discard_*() operations util/iov: add iov_discard_undo() virtio: add vhost-user-fs-ccw device libvhost-user: handle endianness as mandated by the spec MAINTAINERS: add Stefan Hajnoczi as block/nvme.c maintainer Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8c1c07929f
147 changed files with 1508 additions and 1069 deletions
|
@ -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)
|
||||
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) 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)
|
||||
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
|
||||
|
|
|
@ -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". */
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -3,10 +3,11 @@ Deprecated features
|
|||
|
||||
In general features are intended to be supported indefinitely once
|
||||
introduced into QEMU. In the event that a feature needs to be removed,
|
||||
it will be listed in this section. The feature will remain functional
|
||||
for 2 releases prior to actual removal. Deprecated features may also
|
||||
generate warnings on the console when QEMU starts up, or if activated
|
||||
via a monitor command, however, this is not a mandatory requirement.
|
||||
it will be listed in this section. The feature will remain functional for the
|
||||
release in which it was deprecated and one further release. After these two
|
||||
releases, the feature is liable to be removed. Deprecated features may also
|
||||
generate warnings on the console when QEMU starts up, or if activated via a
|
||||
monitor command, however, this is not a mandatory requirement.
|
||||
|
||||
Prior to the 2.10.0 release there was no official policy on how
|
||||
long features would be deprecated prior to their removal, nor
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue