Source-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: src/sys/kern
Module Name: src
Committed By: riastradh
Date: Fri Feb 11 17:53:28 UTC 2022
Modified Files:
src/sys/kern: subr_copy.c
Log Message:
ucas(9): Membar audit.
- Omit needless membar_enter before ipi_trigger_broadcast. This was
presumably intended to imply a happens-before relation for the
following two CPUs:
/* CPU doing ucas */
ucas_critical_enter()
ucas_critical_pausing_cpus = ncpu - 1 (A)
ipi_trigger_broadcast()
/* other CPU walking by whistling innocently */
IPI handler
ucas_critical_cpu_gate()
load ucas_critical_pausing_cpus (B)
That is, this was presumably meant to ensure (A) happens-before (B).
This relation is already guaranteed by ipi(9), so there is no need
for any explicit memory barrier.
- Issue a store-release in ucas_critical_cpu_gate so we have the
following happens-before relation which was otherwise not guaranteed
except if __HAVE_ATOMIC_AS_MEMBAR:
/* other CPU walking by whistling innocently */
...other logic touching the target ucas word... (A)
IPI handler
ucas_critical_cpu_gate()
...
atomic_dec_uint(&ucas_critical_pausing_cpus)
happens-before
/* CPU doing ucas */
ucas_critical_enter() -> ucas_critical_wait();
...touching the word with ufetch/ustore... (B)
We need to ensure the logic (A) on another CPU touching the target
ucas word happens-before we actually do the ucas at (B).
(a) This requires the other CPU to do a store-release on
ucas_critical_pausing_cpus in ucas_critical_cpu_gate, and
(b) this requires the ucas CPU to do a load-acquire on
ucas_critical_pausing_cpus in ucas_critical_wait.
Without _both_ sides -- store-release and then load-acquire -- there
is no such happens-before guarantee; another CPU may have a buffered
store, for instance, that clobbers the ucas.
For now, do the store-release with membar_exit conditional on
__HAVE_ATOMIC_AS_MEMBAR and then atomic_dec_uint -- later with the
C11 API we can dispense with the #ifdef and just use
atomic_fetch_add_explicit(..., memory_order_release). The
load-acquire we can do with atomic_load_acquire.
- Issue a load-acquire in ucas_critical_cpu_gate so we have the
following happens-before relation which was otherwise not guaranteed:
/* CPU doing ucas */
...ufetch/ustore... (A)
ucas_critical_exit()
ucas_critical_pausing_cpus = -1;
/* other CPU walking by whistling innocently */
IPI handler
ucas_critical_cpu_gate()
...
while (ucas_critical_pausing_cpus != -1)
spin;
...other logic touching the target ucas word... (B)
We need to ensure the logic (A) to do the ucas happens-before logic
that might use it on another CPU at (B).
(a) This requires that the ucas CPU do a store-release on
ucas_critical_pausing_cpus in ucas_critical_exit, and
(b) this requires that the other CPU do a load-acquire on
ucas_critical_pausing_cpus in ucas_critical_cpu_gate.
Without _both_ sides -- store-release and then load-acquire -- there
is no such happens-before guarantee; the other CPU might witness a
cached stale value of the target location but a new value of some
other location in the wrong order.
- Use atomic_load/store_* to avoid the appearance of races, e.g. for
sanitizers.
- Document which barriers pair up with which barriers and what they're
doing.
To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/kern/subr_copy.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Home |
Main Index |
Thread Index |
Old Index