Module Name:    src
Committed By:   riastradh
Date:           Sat Apr  9 23:32:53 UTC 2022

Modified Files:
        src/common/lib/libc/arch/aarch64/atomic: membar_ops.S
        src/common/lib/libc/arch/alpha/atomic: membar_ops.S
        src/common/lib/libc/arch/arm/atomic: membar_ops.S
        src/common/lib/libc/arch/hppa/atomic: membar_ops.S
        src/common/lib/libc/arch/i386/atomic: atomic.S
        src/common/lib/libc/arch/ia64/atomic: atomic.S
        src/common/lib/libc/arch/mips/atomic: membar_ops.S
        src/common/lib/libc/arch/or1k/atomic: membar_ops.S
        src/common/lib/libc/arch/powerpc/atomic: membar_ops.S
        src/common/lib/libc/arch/riscv/atomic: membar_ops.S
        src/common/lib/libc/arch/sparc/atomic: membar_ops.S
        src/common/lib/libc/arch/sparc64/atomic: membar_ops.S
        src/common/lib/libc/arch/x86_64/atomic: atomic.S
        src/common/lib/libc/atomic: membar_ops_nop.c
        src/distrib/sets/lists/comp: mi
        src/lib/libc/atomic: Makefile.inc membar_ops.3
        src/share/man/man9: atomic_loadstore.9
        src/sys/sys: atomic.h
        src/tests/lib/libc/membar: t_dekker.c t_spinlock.c

Log Message:
Introduce membar_acquire/release.  Deprecate membar_enter/exit.

The names membar_enter/exit were unclear, and the documentation of
membar_enter has disagreed with the implementations on sparc,
powerpc, and even x86(!) for the entire time it has been in NetBSD.

The terms `acquire' and `release' are ubiquitous in the literature
today, and have been adopted in the C and C++ standards to mean
load-before-load/store and load/store-before-store, respectively,
which are exactly the orderings required by acquiring and releasing a
mutex, as well as other useful applications like decrementing a
reference count and then freeing the underlying object if it went to
zero.

Originally I proposed changing one word in the documentation for
membar_enter to make it load-before-load/store instead of
store-before-load/store, i.e., to make it an acquire barrier.  I
proposed this on the grounds that

(a) all implementations guarantee load-before-load/store,
(b) some implementations fail to guarantee store-before-load/store,
and
(c) all uses in-tree assume load-before-load/store.

I verified parts (a) and (b) (except, for (a), powerpc didn't even
guarantee load-before-load/store -- isync isn't necessarily enough;
need lwsync in general -- but it _almost_ did, and it certainly didn't
guarantee store-before-load/store).

Part (c) might not be correct, however: under the mistaken assumption
that atomic-r/m/w then membar-w/rw is equivalent to atomic-r/m/w then
membar-r/rw, I only audited the cases of membar_enter that _aren't_
immediately after an atomic-r/m/w.  All of those cases assume
load-before-load/store.  But my assumption was wrong -- there are
cases of atomic-r/m/w then membar-w/rw that would be broken by
changing to atomic-r/m/w then membar-r/rw:

https://mail-index.netbsd.org/tech-kern/2022/03/29/msg028044.html

Furthermore, the name membar_enter has been adopted in other places
like OpenBSD where it actually does follow the documentation and
guarantee store-before-load/store, even if that order is not useful.
So the name membar_enter currently lives in a bad place where it
means either of two things -- r/rw or w/rw.

With this change, we deprecate membar_enter/exit, introduce
membar_acquire/release as better names for the useful pair (r/rw and
rw/w), and make sure the implementation of membar_enter guarantees
both what was documented _and_ what was implemented, making it an
alias for membar_sync.

While here, rework all of the membar_* definitions and aliases.  The
new logic follows a rule to make it easier to audit:

        membar_X is defined as an alias for membar_Y iff membar_X is
        guaranteed by membar_Y.

The `no stronger than' relation is (the transitive closure of):

- membar_consumer (r/r) is guaranteed by membar_acquire (r/rw)
- membar_producer (w/w) is guaranteed by membar_release (rw/w)
- membar_acquire (r/rw) is guaranteed by membar_sync (rw/rw)
- membar_release (rw/w) is guaranteed by membar_sync (rw/rw)

And, for the deprecated membars:

- membar_enter (whether r/rw, w/rw, or rw/rw) is guaranteed by
  membar_sync (rw/rw)
- membar_exit (rw/w) is guaranteed by membar_release (rw/w)

(membar_exit is identical to membar_release, but the name is
deprecated.)

Finally, while here, annotate some of the instructions with their
semantics.  For powerpc, leave an essay with citations on the
unfortunate but -- as far as I can tell -- necessary decision to use
lwsync, not isync, for membar_acquire and membar_consumer.

Also add membar(3) and atomic(3) man page links.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/common/lib/libc/arch/aarch64/atomic/membar_ops.S
cvs rdiff -u -r1.8 -r1.9 src/common/lib/libc/arch/alpha/atomic/membar_ops.S
cvs rdiff -u -r1.9 -r1.10 src/common/lib/libc/arch/arm/atomic/membar_ops.S
cvs rdiff -u -r1.2 -r1.3 src/common/lib/libc/arch/hppa/atomic/membar_ops.S
cvs rdiff -u -r1.34 -r1.35 src/common/lib/libc/arch/i386/atomic/atomic.S
cvs rdiff -u -r1.6 -r1.7 src/common/lib/libc/arch/ia64/atomic/atomic.S
cvs rdiff -u -r1.11 -r1.12 src/common/lib/libc/arch/mips/atomic/membar_ops.S
cvs rdiff -u -r1.1 -r1.2 src/common/lib/libc/arch/or1k/atomic/membar_ops.S
cvs rdiff -u -r1.5 -r1.6 src/common/lib/libc/arch/powerpc/atomic/membar_ops.S
cvs rdiff -u -r1.3 -r1.4 src/common/lib/libc/arch/riscv/atomic/membar_ops.S
cvs rdiff -u -r1.7 -r1.8 src/common/lib/libc/arch/sparc/atomic/membar_ops.S
cvs rdiff -u -r1.8 -r1.9 src/common/lib/libc/arch/sparc64/atomic/membar_ops.S
cvs rdiff -u -r1.27 -r1.28 src/common/lib/libc/arch/x86_64/atomic/atomic.S
cvs rdiff -u -r1.7 -r1.8 src/common/lib/libc/atomic/membar_ops_nop.c
cvs rdiff -u -r1.2412 -r1.2413 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.4 -r1.5 src/lib/libc/atomic/Makefile.inc
cvs rdiff -u -r1.9 -r1.10 src/lib/libc/atomic/membar_ops.3
cvs rdiff -u -r1.6 -r1.7 src/share/man/man9/atomic_loadstore.9
cvs rdiff -u -r1.22 -r1.23 src/sys/sys/atomic.h
cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libc/membar/t_dekker.c \
    src/tests/lib/libc/membar/t_spinlock.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/common/lib/libc/arch/aarch64/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/aarch64/atomic/membar_ops.S:1.3 src/common/lib/libc/arch/aarch64/atomic/membar_ops.S:1.4
--- src/common/lib/libc/arch/aarch64/atomic/membar_ops.S:1.3	Sat Apr  9 12:07:37 2022
+++ src/common/lib/libc/arch/aarch64/atomic/membar_ops.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: membar_ops.S,v 1.3 2022/04/09 12:07:37 riastradh Exp $ */
+/* $NetBSD: membar_ops.S,v 1.4 2022/04/09 23:32:51 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -32,19 +32,21 @@
 #include "atomic_op_asm.h"
 
 ENTRY_NP(_membar_producer)
-	dmb	ishst
+	dmb	ishst		/* store-before-store */
 	ret
 END(_membar_producer)
 ATOMIC_OP_ALIAS(membar_producer,_membar_producer)
 ATOMIC_OP_ALIAS(membar_write,_membar_producer)
 STRONG_ALIAS(_membar_write,_membar_producer)
 
-ENTRY_NP(_membar_consumer)
-	dmb	ishld
+ENTRY_NP(_membar_acquire)
+	dmb	ishld		/* load-before-load/store */
 	ret
-END(_membar_consumer)
-ATOMIC_OP_ALIAS(membar_consumer,_membar_consumer)
+END(_membar_acquire)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_acquire)
+ATOMIC_OP_ALIAS(membar_consumer,_membar_acquire)
 ATOMIC_OP_ALIAS(membar_read,_membar_consumer)
+STRONG_ALIAS(_membar_consumer,_membar_acquire)
 STRONG_ALIAS(_membar_read,_membar_consumer)
 
 ENTRY_NP(_membar_sync)
@@ -52,8 +54,10 @@ ENTRY_NP(_membar_sync)
 	ret
 END(_membar_sync)
 ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+ATOMIC_OP_ALIAS(membar_release,_membar_sync)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 ATOMIC_OP_ALIAS(membar_exit,_membar_sync)
 STRONG_ALIAS(__sync_synchronize,_membar_sync)
+STRONG_ALIAS(_membar_release,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_exit,_membar_sync)

Index: src/common/lib/libc/arch/alpha/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/alpha/atomic/membar_ops.S:1.8 src/common/lib/libc/arch/alpha/atomic/membar_ops.S:1.9
--- src/common/lib/libc/arch/alpha/atomic/membar_ops.S:1.8	Wed Apr  6 22:47:55 2022
+++ src/common/lib/libc/arch/alpha/atomic/membar_ops.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.8 2022/04/06 22:47:55 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.9 2022/04/09 23:32:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
@@ -42,45 +42,50 @@
 LEAF(_membar_producer, 0)
 	RET
 	nop
-	END(_membar_producer)
+END(_membar_producer)
 EXPORT(_membar_producer_end)
 
 LEAF(_membar_sync, 0)
 	RET
 	nop
-	END(_membar_sync)
+END(_membar_sync)
 EXPORT(_membar_sync_end)
 
 LEAF(_membar_producer_mp, 0)
-	wmb
+	wmb		/* store-before-store */
 	RET
-	END(_membar_producer_mp)
+END(_membar_producer_mp)
 EXPORT(_membar_producer_mp_end)
 
 LEAF(_membar_sync_mp, 0)
-	mb
+	mb		/* load/store-before-load/store */
 	RET
-	END(_membar_sync_mp)
+END(_membar_sync_mp)
 EXPORT(_membar_sync_mp_end)
 
 #else	/* _KERNEL */
 
 LEAF(_membar_producer, 0)
-	mb
+	mb		/* load/store-before-load/store */
 	RET
-	END(_membar_producer)
+END(_membar_producer)
 EXPORT(_membar_producer_end)
 
 LEAF(_membar_sync, 0)
-	mb
+	mb		/* load/store-before-load/store */
 	RET
-	END(_membar_sync)
+END(_membar_sync)
 EXPORT(_membar_sync_end)
 
 #endif	/* _KERNEL */
 
 ATOMIC_OP_ALIAS(membar_producer,_membar_producer)
 ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+
+ATOMIC_OP_ALIAS(membar_acquire,_membar_sync)
+STRONG_ALIAS(_membar_acquire,_membar_sync)
+ATOMIC_OP_ALIAS(membar_release,_membar_sync)
+STRONG_ALIAS(_membar_release,_membar_sync)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
 ATOMIC_OP_ALIAS(membar_exit,_membar_sync)

Index: src/common/lib/libc/arch/arm/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/arm/atomic/membar_ops.S:1.9 src/common/lib/libc/arch/arm/atomic/membar_ops.S:1.10
--- src/common/lib/libc/arch/arm/atomic/membar_ops.S:1.9	Wed Jul 28 07:32:20 2021
+++ src/common/lib/libc/arch/arm/atomic/membar_ops.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.9 2021/07/28 07:32:20 skrll Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.10 2022/04/09 23:32:51 riastradh Exp $	*/
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -33,7 +33,7 @@
 #if defined(_ARM_ARCH_6)
 
 ENTRY_NP(_membar_producer)
-	DMBST
+	DMBST		/* store-before-store */
 	RET
 END(_membar_producer)
 ATOMIC_OP_ALIAS(membar_producer,_membar_producer)
@@ -41,15 +41,19 @@ ATOMIC_OP_ALIAS(membar_write,_membar_pro
 STRONG_ALIAS(_membar_write,_membar_producer)
 
 ENTRY_NP(_membar_sync)
-	DMB
+	DMB		/* load/store-before-load/store */
 	RET
 END(_membar_sync)
 ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_sync)
+ATOMIC_OP_ALIAS(membar_release,_membar_sync)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 ATOMIC_OP_ALIAS(membar_exit,_membar_sync)
 ATOMIC_OP_ALIAS(membar_consumer,_membar_sync)
 ATOMIC_OP_ALIAS(membar_read,_membar_sync)
 STRONG_ALIAS(__sync_synchronize,_membar_sync)
+STRONG_ALIAS(_membar_acquire,_membar_sync)
+STRONG_ALIAS(_membar_release,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_exit,_membar_sync)
 STRONG_ALIAS(_membar_consumer,_membar_sync)

Index: src/common/lib/libc/arch/hppa/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/hppa/atomic/membar_ops.S:1.2 src/common/lib/libc/arch/hppa/atomic/membar_ops.S:1.3
--- src/common/lib/libc/arch/hppa/atomic/membar_ops.S:1.2	Wed Apr  6 22:47:56 2022
+++ src/common/lib/libc/arch/hppa/atomic/membar_ops.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.2 2022/04/06 22:47:56 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.3 2022/04/09 23:32:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -31,11 +31,11 @@
 
 #include "atomic_op_asm.h"
 
-RCSID("$NetBSD: membar_ops.S,v 1.2 2022/04/06 22:47:56 riastradh Exp $")
+RCSID("$NetBSD: membar_ops.S,v 1.3 2022/04/09 23:32:51 riastradh Exp $")
 
 	.text
 
-LEAF_ENTRY(_membar_consumer)
+LEAF_ENTRY(_membar_sync)
 	sync
 	nop
 	nop
@@ -44,24 +44,18 @@ LEAF_ENTRY(_membar_consumer)
 	nop
 	bv	%r0(%rp)
 	 nop
-EXIT(_membar_consumer)
+EXIT(_membar_sync)
+ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
 
-LEAF_ENTRY(_membar_producer)
-	sync
-	nop
-	nop
-	nop
-	nop
-	nop
-	bv	%r0(%rp)
-	 nop
-EXIT(_membar_producer)
-
-ATOMIC_OP_ALIAS(membar_producer,_membar_producer)
-ATOMIC_OP_ALIAS(membar_consumer,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_enter,_membar_consumer)
-STRONG_ALIAS(_membar_enter,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_exit,_membar_producer)
-STRONG_ALIAS(_membar_exit,_membar_producer)
-ATOMIC_OP_ALIAS(membar_sync,_membar_producer)
-STRONG_ALIAS(_membar_sync,_membar_producer)
+ATOMIC_OP_ALIAS(membar_producer,_membar_sync)
+STRONG_ALIAS(_membar_producer,_membar_sync)
+ATOMIC_OP_ALIAS(membar_consumer,_membar_sync)
+STRONG_ALIAS(_membar_consumer,_membar_sync)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_sync)
+STRONG_ALIAS(_membar_acquire,_membar_sync)
+ATOMIC_OP_ALIAS(membar_release,_membar_sync)
+STRONG_ALIAS(_membar_release,_membar_sync)
+ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
+STRONG_ALIAS(_membar_enter,_membar_sync)
+ATOMIC_OP_ALIAS(membar_exit,_membar_sync)
+STRONG_ALIAS(_membar_exit,_membar_sync)

Index: src/common/lib/libc/arch/i386/atomic/atomic.S
diff -u src/common/lib/libc/arch/i386/atomic/atomic.S:1.34 src/common/lib/libc/arch/i386/atomic/atomic.S:1.35
--- src/common/lib/libc/arch/i386/atomic/atomic.S:1.34	Sat Apr  9 22:53:36 2022
+++ src/common/lib/libc/arch/i386/atomic/atomic.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: atomic.S,v 1.34 2022/04/09 22:53:36 riastradh Exp $	*/
+/*	$NetBSD: atomic.S,v 1.35 2022/04/09 23:32:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -178,23 +178,23 @@ ENTRY(_atomic_cas_32_ni)
 	ret
 END(_atomic_cas_32_ni)
 
-ENTRY(_membar_consumer)
+ENTRY(_membar_acquire)
 	/*
 	 * Every load from normal memory is a load-acquire on x86, so
 	 * there is never any need for explicit barriers to order
 	 * load-before-anything.
 	 */
 	ret
-END(_membar_consumer)
+END(_membar_acquire)
 
-ENTRY(_membar_producer)
+ENTRY(_membar_release)
 	/*
 	 * Every store to normal memory is a store-release on x86, so
 	 * there is never any need for explicit barriers to order
 	 * anything-before-store.
 	 */
 	ret
-END(_membar_producer)
+END(_membar_release)
 
 ENTRY(_membar_sync)
 	/*
@@ -340,10 +340,14 @@ ALIAS(atomic_cas_64_ni,_atomic_cas_64)
 ALIAS(__sync_val_compare_and_swap_8,_atomic_cas_64)
 #endif /* __HAVE_ATOMIC64_OPS || _KERNEL */
 
-ALIAS(membar_consumer,_membar_consumer)
-ALIAS(membar_producer,_membar_producer)
+ALIAS(membar_acquire,_membar_acquire)
+ALIAS(membar_release,_membar_release)
+ALIAS(membar_sync,_membar_sync)
+
+ALIAS(membar_consumer,_membar_acquire)
+ALIAS(membar_producer,_membar_release)
 ALIAS(membar_enter,_membar_sync)
-ALIAS(membar_exit,_membar_producer)
+ALIAS(membar_exit,_membar_release)
 ALIAS(membar_sync,_membar_sync)
 
 STRONG_ALIAS(_atomic_add_int,_atomic_add_32)
@@ -398,8 +402,10 @@ STRONG_ALIAS(_atomic_cas_uint_ni,_atomic
 STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32_ni)
 STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32_ni)
 
+STRONG_ALIAS(_membar_consumer,_membar_acquire)
+STRONG_ALIAS(_membar_producer,_membar_release)
 STRONG_ALIAS(_membar_enter,_membar_sync)
-STRONG_ALIAS(_membar_exit,_membar_producer)
+STRONG_ALIAS(_membar_exit,_membar_release)
 
 #ifdef _HARDKERNEL
 	.section .rodata

Index: src/common/lib/libc/arch/ia64/atomic/atomic.S
diff -u src/common/lib/libc/arch/ia64/atomic/atomic.S:1.6 src/common/lib/libc/arch/ia64/atomic/atomic.S:1.7
--- src/common/lib/libc/arch/ia64/atomic/atomic.S:1.6	Wed Apr  6 22:47:56 2022
+++ src/common/lib/libc/arch/ia64/atomic/atomic.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: atomic.S,v 1.6 2022/04/06 22:47:56 riastradh Exp $	*/
+/*	$NetBSD: atomic.S,v 1.7 2022/04/09 23:32:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -117,6 +117,16 @@ ENTRY(_membar_producer,0)
 	br.ret.sptk	rp
 END(_membar_producer)
 
+ENTRY(_membar_acquire,0)
+	mf
+	br.ret.sptk	rp
+END(_membar_acquire)
+
+ENTRY(_membar_release,0)
+	mf
+	br.ret.sptk	rp
+END(_membar_release)
+
 ENTRY(_membar_enter,0)
 	mf
 	br.ret.sptk	rp
@@ -213,6 +223,8 @@ ALIAS(atomic_cas_ptr_ni,_atomic_cas_64)
 
 ALIAS(membar_consumer,_membar_consumer)
 ALIAS(membar_producer,_membar_producer)
+ALIAS(membar_acquire,_membar_acquire)
+ALIAS(membar_release,_membar_release)
 ALIAS(membar_enter,_membar_enter)
 ALIAS(membar_exit,_membar_exit)
 ALIAS(membar_sync,_membar_sync)

Index: src/common/lib/libc/arch/mips/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/mips/atomic/membar_ops.S:1.11 src/common/lib/libc/arch/mips/atomic/membar_ops.S:1.12
--- src/common/lib/libc/arch/mips/atomic/membar_ops.S:1.11	Sat Feb 12 17:10:02 2022
+++ src/common/lib/libc/arch/mips/atomic/membar_ops.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.11 2022/02/12 17:10:02 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.12 2022/04/09 23:32:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
@@ -40,22 +40,40 @@ LEAF(_membar_sync)
 END(_membar_sync)
 
 #ifdef __OCTEON__
-LEAF(_membar_producer)
+LEAF(_membar_release)
+	/*
+	 * syncw is documented as ordering store-before-store in
+	 *
+	 *	Cavium OCTEON III CN78XX Hardware Reference Manual,
+	 *	CN78XX-HM-0.99E, September 2014.
+	 *
+	 * It's unclear from the documentation the architecture
+	 * guarantees load-before-store ordering without barriers, but
+	 * this code assumes it does.  If that assumption is wrong, we
+	 * can only use syncw for membar_producer -- membar_release has
+	 * to use the full sync.
+	 */
 	j	ra
 	 syncw
-END(_membar_producer)
+END(_membar_release)
 #endif
 
 ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_sync)
+STRONG_ALIAS(_membar_acquire,_membar_sync)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
 #ifdef __OCTEON__
-ATOMIC_OP_ALIAS(membar_exit,_membar_producer)
-STRONG_ALIAS(_membar_exit,_membar_producer)
-STRONG_ALIAS(membar_producer,_membar_producer)
+ATOMIC_OP_ALIAS(membar_exit,_membar_release)
+STRONG_ALIAS(_membar_exit,_membar_release)
+ATOMIC_OP_ALIAS(membar_release,_membar_release)
+ATOMIC_OP_ALIAS(membar_producer,_membar_release)
+STRONG_ALIAS(_membar_producer,_membar_release)
 #else
 ATOMIC_OP_ALIAS(membar_exit,_membar_sync)
 STRONG_ALIAS(_membar_exit,_membar_sync)
+ATOMIC_OP_ALIAS(membar_release,_membar_sync)
+STRONG_ALIAS(_membar_release,_membar_sync)
 ATOMIC_OP_ALIAS(membar_producer,_membar_sync)
 STRONG_ALIAS(_membar_producer,_membar_sync)
 #endif

Index: src/common/lib/libc/arch/or1k/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/or1k/atomic/membar_ops.S:1.1 src/common/lib/libc/arch/or1k/atomic/membar_ops.S:1.2
--- src/common/lib/libc/arch/or1k/atomic/membar_ops.S:1.1	Wed Sep  3 19:34:25 2014
+++ src/common/lib/libc/arch/or1k/atomic/membar_ops.S	Sat Apr  9 23:32:51 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.1 2014/09/03 19:34:25 matt Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.2 2022/04/09 23:32:51 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,27 +31,26 @@
 
 #include "atomic_op_asm.h"
 
-ENTRY_NP(_membar_producer)
-	l.msync
-	l.jr	lr
-	l.nop
-END(_membar_producer)
-ATOMIC_OP_ALIAS(membar_producer,_membar_producer)
-ATOMIC_OP_ALIAS(membar_write,_membar_producer)
-STRONG_ALIAS(_membar_write,_membar_producer)
-
 ENTRY_NP(_membar_sync)
 	l.msync
 	l.jr	lr
 	l.nop
 END(_membar_sync)
 ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_sync)
+ATOMIC_OP_ALIAS(membar_release,_membar_sync)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 ATOMIC_OP_ALIAS(membar_exit,_membar_sync)
 ATOMIC_OP_ALIAS(membar_consumer,_membar_sync)
 ATOMIC_OP_ALIAS(membar_read,_membar_sync)
+ATOMIC_OP_ALIAS(membar_producer,_membar_sync)
+ATOMIC_OP_ALIAS(membar_write,_membar_sync)
 CRT_ALIAS(__sync_synchronize,_membar_sync)
+STRONG_ALIAS(_membar_acquire,_membar_sync)
+STRONG_ALIAS(_membar_release,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_exit,_membar_sync)
 STRONG_ALIAS(_membar_consumer,_membar_sync)
 STRONG_ALIAS(_membar_read,_membar_sync)
+STRONG_ALIAS(_membar_producer,_membar_sync)
+STRONG_ALIAS(_membar_write,_membar_sync)

Index: src/common/lib/libc/arch/powerpc/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/powerpc/atomic/membar_ops.S:1.5 src/common/lib/libc/arch/powerpc/atomic/membar_ops.S:1.6
--- src/common/lib/libc/arch/powerpc/atomic/membar_ops.S:1.5	Wed Apr  6 22:47:56 2022
+++ src/common/lib/libc/arch/powerpc/atomic/membar_ops.S	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.5 2022/04/06 22:47:56 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.6 2022/04/09 23:32:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -31,26 +31,111 @@
 
 #include "atomic_op_asm.h"
 
-__RCSID("$NetBSD: membar_ops.S,v 1.5 2022/04/06 22:47:56 riastradh Exp $")
+__RCSID("$NetBSD: membar_ops.S,v 1.6 2022/04/09 23:32:52 riastradh Exp $")
 
 	.text
-/* These assume Total Store Order (TSO) */
 
-ENTRY(_membar_consumer)
-	isync
+ENTRY(_membar_acquire)
+	/*
+	 * It is tempting to use isync to order load-before-load/store.
+	 * However, isync orders prior loads only if their value flows
+	 * into a control-flow dependency prior to the isync:
+	 *
+	 *	`[I]f an isync follows a conditional Branch instruction
+	 *	 that depends on the value returned by a preceding Load
+	 *	 instruction, the load on which the Branch depends is
+	 *	 performed before any loads caused by instructions
+	 *	 following the isync. This applies even if the effects
+	 *	 of the ``dependency'' are independent of the value
+	 *	 loaded (e.g., the value is compared to itself and the
+	 *	 Branch tests the EQ bit in the selected CR field), and
+	 *	 even if the branch target is the sequentially next
+	 *	 instruction.'
+	 *
+	 *	--PowerPC Virtual Environment Architecture, Book II,
+	 *	  Version 2.01, December 2003, 1.7.1 `Storage Access
+	 *	  Ordering', p. 7.
+	 *
+	 * We are required here, however, to order _all_ prior loads,
+	 * even if they do not flow into any control flow dependency.
+	 * For example:
+	 *
+	 *	x = *p;
+	 *	membar_acquire();
+	 *	if (x) goto foo;
+	 *
+	 * This can't be implemented by:
+	 *
+	 *	lwz	x, p
+	 *	isync
+	 *	cmpwi	x, 0
+	 *	bne	foo
+	 *
+	 * isync doesn't work here because there's no conditional
+	 * dependency on x between the lwz x, p and the isync.
+	 *
+	 * isync would only work if it followed the branch:
+	 *
+	 *	lwz	x, p
+	 *	isync
+	 *	cmpwi	x, 0
+	 *	bne	foo
+	 *	...
+	 * foo:	isync
+	 *	...
+	 *
+	 * lwsync orders everything except store-before-load, so it
+	 * serves here -- see below in membar_release in lwsync.
+	 * Except we can't use it on booke, so use sync for now.
+	 */
+	sync
+	blr
+END(_membar_acquire)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_acquire)
+
+ENTRY(_membar_release)
+	/*
+	 *	`The memory barrier provides an ordering function for
+	 *	 the storage accesses caused by Load, Store, and dcbz
+	 *	 instructions that are executed by the processor
+	 *	 executing the [lwsync] instruction and for which the
+	 *	 specified storage location is in storage that is
+	 *	 Memory Coherence Required and is neither Write Through
+	 *	 Required nor Caching Inhibited.  The applicable pairs
+	 *	 are all pairs a_i, b_j of such accesses except those
+	 *	 in which a_i is an access caused by a Store or dcbz
+	 *	 instruction and b_j is an access caused by a Load
+	 *	 instruction.'
+	 *
+	 *	--PowerPC Virtual Environment Architecture, Book II,
+	 *	  Version 2.01, December 2003, 3.3.3 `Memory Barrier
+	 *	  Instructions', p. 25.
+	 *
+	 * In brief, lwsync is an acquire-release barrier -- it orders
+	 * load-before-load/store and load/store-before-store, but not
+	 * store-before-load.  Except we can't use it on booke, so use
+	 * sync for now.
+	 */
+	sync
 	blr
-END(_membar_consumer)
+END(_membar_release)
+ATOMIC_OP_ALIAS(membar_release,_membar_release)
 
-ENTRY(_membar_producer)
+ENTRY(_membar_sync)
+	/*
+	 * sync, or `heavyweight sync', is a full sequential
+	 * consistency barrier.
+	 */
 	sync
 	blr
-END(_membar_producer)
+END(_membar_sync)
+ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
 
-ATOMIC_OP_ALIAS(membar_producer,_membar_producer)
-ATOMIC_OP_ALIAS(membar_consumer,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_enter,_membar_consumer)
-STRONG_ALIAS(_membar_enter,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_exit,_membar_producer)
-STRONG_ALIAS(_membar_exit,_membar_producer)
-ATOMIC_OP_ALIAS(membar_sync,_membar_producer)
-STRONG_ALIAS(_membar_sync,_membar_producer)
+ATOMIC_OP_ALIAS(membar_producer,_membar_release)
+STRONG_ALIAS(_membar_producer,_membar_release)
+ATOMIC_OP_ALIAS(membar_consumer,_membar_acquire)
+STRONG_ALIAS(_membar_consumer,_membar_acquire)
+ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
+STRONG_ALIAS(_membar_enter,_membar_sync)
+ATOMIC_OP_ALIAS(membar_exit,_membar_release)
+STRONG_ALIAS(_membar_exit,_membar_release)

Index: src/common/lib/libc/arch/riscv/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/riscv/atomic/membar_ops.S:1.3 src/common/lib/libc/arch/riscv/atomic/membar_ops.S:1.4
--- src/common/lib/libc/arch/riscv/atomic/membar_ops.S:1.3	Sat Apr  9 22:53:53 2022
+++ src/common/lib/libc/arch/riscv/atomic/membar_ops.S	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.3 2022/04/09 22:53:53 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.4 2022/04/09 23:32:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
@@ -38,6 +38,18 @@ END(_membar_sync)
 ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
 CRT_ALIAS(__sync_synchronize,_membar_sync)
 
+ENTRY_NP(_membar_acquire)
+	fence	r,rw
+	ret
+END(_membar_acquire)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_acquire)
+
+ENTRY_NP(_membar_release)
+	fence	rw,w
+	ret
+END(_membar_release)
+ATOMIC_OP_ALIAS(membar_release,_membar_release)
+
 ENTRY_NP(_membar_enter)
 	fence	rw,rw
 	ret

Index: src/common/lib/libc/arch/sparc/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/sparc/atomic/membar_ops.S:1.7 src/common/lib/libc/arch/sparc/atomic/membar_ops.S:1.8
--- src/common/lib/libc/arch/sparc/atomic/membar_ops.S:1.7	Sat Apr  9 22:53:17 2022
+++ src/common/lib/libc/arch/sparc/atomic/membar_ops.S	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.7 2022/04/09 22:53:17 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.8 2022/04/09 23:32:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -45,14 +45,21 @@
  * instruction that implies a sequential consistency barrier.
  *
  * If we ran with Partial Store Order (PSO), we would also need to
- * issue STBAR for membar_exit (load/store-before-store) and
+ * issue STBAR for membar_release (load/store-before-store) and
  * membar_producer (store-before-store).
  */
 
-ENTRY(_membar_consumer)
+ENTRY(_membar_acquire)
 	retl
 	 nop
-END(_membar_consumer)
+END(_membar_acquire)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_acquire)
+
+ENTRY(_membar_release)
+	retl
+	 nop
+END(_membar_release)
+ATOMIC_OP_ALIAS(membar_release,_membar_release)
 
 ENTRY(_membar_sync)
 	retl
@@ -62,12 +69,13 @@ ENTRY(_membar_sync)
 	 nop
 #endif
 END(_membar_sync)
+ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
 
-ATOMIC_OP_ALIAS(membar_producer,_membar_consumer)
-STRONG_ALIAS(_membar_producer,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_consumer,_membar_consumer)
+ATOMIC_OP_ALIAS(membar_producer,_membar_release)
+STRONG_ALIAS(_membar_producer,_membar_release)
+ATOMIC_OP_ALIAS(membar_consumer,_membar_acquire)
+STRONG_ALIAS(_membar_consumer,_membar_acquire)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
-ATOMIC_OP_ALIAS(membar_exit,_membar_consumer)
-STRONG_ALIAS(_membar_exit,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+ATOMIC_OP_ALIAS(membar_exit,_membar_release)
+STRONG_ALIAS(_membar_exit,_membar_release)

Index: src/common/lib/libc/arch/sparc64/atomic/membar_ops.S
diff -u src/common/lib/libc/arch/sparc64/atomic/membar_ops.S:1.8 src/common/lib/libc/arch/sparc64/atomic/membar_ops.S:1.9
--- src/common/lib/libc/arch/sparc64/atomic/membar_ops.S:1.8	Sat Apr  9 22:53:25 2022
+++ src/common/lib/libc/arch/sparc64/atomic/membar_ops.S	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops.S,v 1.8 2022/04/09 22:53:25 riastradh Exp $	*/
+/*	$NetBSD: membar_ops.S,v 1.9 2022/04/09 23:32:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -44,10 +44,17 @@
  * and membar_producer (store-before-store).
  */
 
-ENTRY(_membar_consumer)
+ENTRY(_membar_acquire)
 	retl
 	 nop
-END(_membar_consumer)
+END(_membar_acquire)
+ATOMIC_OP_ALIAS(membar_acquire,_membar_acquire)
+
+ENTRY(_membar_release)
+	retl
+	 nop
+END(_membar_release)
+ATOMIC_OP_ALIAS(membar_release,_membar_release)
 
 ENTRY(_membar_sync)
 	/*
@@ -70,12 +77,13 @@ ENTRY(_membar_sync)
 	retl
 	 nop
 END(_membar_sync)
+ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
 
-ATOMIC_OP_ALIAS(membar_producer,_membar_consumer)
-STRONG_ALIAS(_membar_producer,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_consumer,_membar_consumer)
+ATOMIC_OP_ALIAS(membar_producer,_membar_release)
+STRONG_ALIAS(_membar_producer,_membar_release)
+ATOMIC_OP_ALIAS(membar_consumer,_membar_acquire)
+STRONG_ALIAS(_membar_consumer,_membar_acquire)
 ATOMIC_OP_ALIAS(membar_enter,_membar_sync)
 STRONG_ALIAS(_membar_enter,_membar_sync)
-ATOMIC_OP_ALIAS(membar_exit,_membar_consumer)
-STRONG_ALIAS(_membar_exit,_membar_consumer)
-ATOMIC_OP_ALIAS(membar_sync,_membar_sync)
+ATOMIC_OP_ALIAS(membar_exit,_membar_release)
+STRONG_ALIAS(_membar_exit,_membar_release)

Index: src/common/lib/libc/arch/x86_64/atomic/atomic.S
diff -u src/common/lib/libc/arch/x86_64/atomic/atomic.S:1.27 src/common/lib/libc/arch/x86_64/atomic/atomic.S:1.28
--- src/common/lib/libc/arch/x86_64/atomic/atomic.S:1.27	Sat Apr  9 22:53:45 2022
+++ src/common/lib/libc/arch/x86_64/atomic/atomic.S	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: atomic.S,v 1.27 2022/04/09 22:53:45 riastradh Exp $	*/
+/*	$NetBSD: atomic.S,v 1.28 2022/04/09 23:32:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -253,23 +253,23 @@ END(_atomic_cas_64_ni)
 
 /* memory barriers */
 
-ENTRY(_membar_consumer)
+ENTRY(_membar_acquire)
 	/*
 	 * Every load from normal memory is a load-acquire on x86, so
 	 * there is never any need for explicit barriers to order
 	 * load-before-anything.
 	 */
 	ret
-END(_membar_consumer)
+END(_membar_acquire)
 
-ENTRY(_membar_producer)
+ENTRY(_membar_release)
 	/*
 	 * Every store to normal memory is a store-release on x86, so
 	 * there is never any need for explicit barriers to order
 	 * anything-before-store.
 	 */
 	ret
-END(_membar_producer)
+END(_membar_release)
 
 ENTRY(_membar_sync)
 	/*
@@ -363,10 +363,14 @@ ALIAS(atomic_cas_uint_ni,_atomic_cas_32_
 ALIAS(atomic_cas_ulong_ni,_atomic_cas_64_ni)
 ALIAS(atomic_cas_ptr_ni,_atomic_cas_64_ni)
 
-ALIAS(membar_consumer,_membar_consumer)
-ALIAS(membar_producer,_membar_producer)
+ALIAS(membar_acquire,_membar_acquire)
+ALIAS(membar_release,_membar_release)
+ALIAS(membar_sync,_membar_sync)
+
+ALIAS(membar_consumer,_membar_acquire)
+ALIAS(membar_producer,_membar_release)
 ALIAS(membar_enter,_membar_sync)
-ALIAS(membar_exit,_membar_producer)
+ALIAS(membar_exit,_membar_release)
 ALIAS(membar_sync,_membar_sync)
 
 STRONG_ALIAS(_atomic_add_int,_atomic_add_32)
@@ -421,8 +425,10 @@ STRONG_ALIAS(_atomic_cas_uint_ni,_atomic
 STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_64_ni)
 STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_64_ni)
 
+STRONG_ALIAS(_membar_consumer,_membar_acquire)
+STRONG_ALIAS(_membar_producer,_membar_release)
 STRONG_ALIAS(_membar_enter,_membar_sync)
-STRONG_ALIAS(_membar_exit,_membar_producer)
+STRONG_ALIAS(_membar_exit,_membar_release)
 
 #ifdef _HARDKERNEL
 	.section .rodata

Index: src/common/lib/libc/atomic/membar_ops_nop.c
diff -u src/common/lib/libc/atomic/membar_ops_nop.c:1.7 src/common/lib/libc/atomic/membar_ops_nop.c:1.8
--- src/common/lib/libc/atomic/membar_ops_nop.c:1.7	Sat Feb 22 17:08:30 2014
+++ src/common/lib/libc/atomic/membar_ops_nop.c	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: membar_ops_nop.c,v 1.7 2014/02/22 17:08:30 martin Exp $	*/
+/*	$NetBSD: membar_ops_nop.c,v 1.8 2022/04/09 23:32:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -40,6 +40,12 @@ membar_sync(void)
 	/* nothing */
 }
 
+#undef membar_acquire
+atomic_op_alias(membar_acquire,_membar_sync)
+__strong_alias(_membar_acquire,_membar_sync)
+#undef membar_release
+atomic_op_alias(membar_release,_membar_sync)
+__strong_alias(_membar_release,_membar_sync)
 #undef membar_enter
 atomic_op_alias(membar_enter,_membar_sync)
 __strong_alias(_membar_enter,_membar_sync)

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2412 src/distrib/sets/lists/comp/mi:1.2413
--- src/distrib/sets/lists/comp/mi:1.2412	Tue Feb 15 22:46:29 2022
+++ src/distrib/sets/lists/comp/mi	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2412 2022/02/15 22:46:29 riastradh Exp $
+#	$NetBSD: mi,v 1.2413 2022/04/09 23:32:52 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -6307,6 +6307,7 @@
 ./usr/share/man/cat3/atoi.0			comp-c-catman		.cat
 ./usr/share/man/cat3/atol.0			comp-c-catman		.cat
 ./usr/share/man/cat3/atoll.0			comp-c-catman		.cat
+./usr/share/man/cat3/atomic.0			comp-c-catman		.cat
 ./usr/share/man/cat3/atomic_add.0		comp-c-catman		.cat
 ./usr/share/man/cat3/atomic_add_32.0		comp-c-catman		.cat
 ./usr/share/man/cat3/atomic_add_32_nv.0		comp-c-catman		.cat
@@ -8913,12 +8914,15 @@
 ./usr/share/man/cat3/md5.0			comp-c-catman		.cat
 ./usr/share/man/cat3/mdc2.0			comp-obsolete		obsolete
 ./usr/share/man/cat3/mdoc.0			comp-obsolete		obsolete
+./usr/share/man/cat3/membar.0			comp-c-catman		.cat
+./usr/share/man/cat3/membar_acquire.0		comp-c-catman		.cat
 ./usr/share/man/cat3/membar_consumer.0		comp-c-catman		.cat
 ./usr/share/man/cat3/membar_datadep_consumer.0	comp-c-catman		.cat
 ./usr/share/man/cat3/membar_enter.0		comp-c-catman		.cat
 ./usr/share/man/cat3/membar_exit.0		comp-c-catman		.cat
 ./usr/share/man/cat3/membar_ops.0		comp-c-catman		.cat
 ./usr/share/man/cat3/membar_producer.0		comp-c-catman		.cat
+./usr/share/man/cat3/membar_release.0		comp-c-catman		.cat
 ./usr/share/man/cat3/membar_sync.0		comp-c-catman		.cat
 ./usr/share/man/cat3/memccpy.0			comp-c-catman		.cat
 ./usr/share/man/cat3/memchr.0			comp-c-catman		.cat
@@ -14668,6 +14672,7 @@
 ./usr/share/man/html3/atoi.html			comp-c-htmlman		html
 ./usr/share/man/html3/atol.html			comp-c-htmlman		html
 ./usr/share/man/html3/atoll.html		comp-c-htmlman		html
+./usr/share/man/html3/atomic.html		comp-c-htmlman		html
 ./usr/share/man/html3/atomic_add.html		comp-c-htmlman		html
 ./usr/share/man/html3/atomic_add_32.html	comp-c-htmlman		html
 ./usr/share/man/html3/atomic_add_32_nv.html	comp-c-htmlman		html
@@ -17195,12 +17200,15 @@
 ./usr/share/man/html3/md4.html			comp-c-htmlman		html
 ./usr/share/man/html3/md5.html			comp-c-htmlman		html
 ./usr/share/man/html3/mdoc.html			comp-obsolete		obsolete
+./usr/share/man/html3/membar.html		comp-c-htmlman		html
+./usr/share/man/html3/membar_acquire.html	comp-c-htmlman		html
 ./usr/share/man/html3/membar_consumer.html	comp-c-htmlman		html
 ./usr/share/man/html3/membar_datadep_consumer.html	comp-c-htmlman		html
 ./usr/share/man/html3/membar_enter.html		comp-c-htmlman		html
 ./usr/share/man/html3/membar_exit.html		comp-c-htmlman		html
 ./usr/share/man/html3/membar_ops.html		comp-c-htmlman		html
 ./usr/share/man/html3/membar_producer.html	comp-c-htmlman		html
+./usr/share/man/html3/membar_release.html	comp-c-htmlman		html
 ./usr/share/man/html3/membar_sync.html		comp-c-htmlman		html
 ./usr/share/man/html3/memccpy.html		comp-c-htmlman		html
 ./usr/share/man/html3/memchr.html		comp-c-htmlman		html
@@ -22866,6 +22874,7 @@
 ./usr/share/man/man3/atoi.3			comp-c-man		.man
 ./usr/share/man/man3/atol.3			comp-c-man		.man
 ./usr/share/man/man3/atoll.3			comp-c-man		.man
+./usr/share/man/man3/atomic.3			comp-c-man		.man
 ./usr/share/man/man3/atomic_add.3		comp-c-man		.man
 ./usr/share/man/man3/atomic_add_32.3		comp-c-man		.man
 ./usr/share/man/man3/atomic_add_32_nv.3		comp-c-man		.man
@@ -25484,12 +25493,15 @@
 ./usr/share/man/man3/md5.3			comp-c-man		.man
 ./usr/share/man/man3/mdc2.3			comp-obsolete		obsolete
 ./usr/share/man/man3/mdoc.3			comp-obsolete		obsolete
+./usr/share/man/man3/membar.3			comp-c-man		.man
+./usr/share/man/man3/membar_acquire.3		comp-c-man		.man
 ./usr/share/man/man3/membar_consumer.3		comp-c-man		.man
 ./usr/share/man/man3/membar_datadep_consumer.3	comp-c-man		.man
 ./usr/share/man/man3/membar_enter.3		comp-c-man		.man
 ./usr/share/man/man3/membar_exit.3		comp-c-man		.man
 ./usr/share/man/man3/membar_ops.3		comp-c-man		.man
 ./usr/share/man/man3/membar_producer.3		comp-c-man		.man
+./usr/share/man/man3/membar_release.3		comp-c-man		.man
 ./usr/share/man/man3/membar_sync.3		comp-c-man		.man
 ./usr/share/man/man3/memccpy.3			comp-c-man		.man
 ./usr/share/man/man3/memchr.3			comp-c-man		.man

Index: src/lib/libc/atomic/Makefile.inc
diff -u src/lib/libc/atomic/Makefile.inc:1.4 src/lib/libc/atomic/Makefile.inc:1.5
--- src/lib/libc/atomic/Makefile.inc:1.4	Sat Dec  7 15:13:59 2019
+++ src/lib/libc/atomic/Makefile.inc	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.4 2019/12/07 15:13:59 riastradh Exp $
+#	$NetBSD: Makefile.inc,v 1.5 2022/04/09 23:32:52 riastradh Exp $
 #	from: @(#)Makefile.inc	8.6 (Berkeley) 5/4/95
 
 # gen sources
@@ -75,6 +75,10 @@ MLINKS+=atomic_add.3 atomic_add_32.3 \
 	atomic_swap.3 atomic_swap_ulong.3 \
 	atomic_swap.3 atomic_swap_ptr.3 \
 	atomic_swap.3 atomic_swap_64.3 \
+	atomic_ops.3 atomic.3 \
+	membar_ops.3 membar.3 \
+	membar_ops.3 membar_acquire.3 \
+	membar_ops.3 membar_release.3 \
 	membar_ops.3 membar_enter.3 \
 	membar_ops.3 membar_exit.3 \
 	membar_ops.3 membar_producer.3 \

Index: src/lib/libc/atomic/membar_ops.3
diff -u src/lib/libc/atomic/membar_ops.3:1.9 src/lib/libc/atomic/membar_ops.3:1.10
--- src/lib/libc/atomic/membar_ops.3:1.9	Tue Feb 15 22:46:53 2022
+++ src/lib/libc/atomic/membar_ops.3	Sat Apr  9 23:32:52 2022
@@ -1,4 +1,4 @@
-.\"	$NetBSD: membar_ops.3,v 1.9 2022/02/15 22:46:53 riastradh Exp $
+.\"	$NetBSD: membar_ops.3,v 1.10 2022/04/09 23:32:52 riastradh Exp $
 .\"
 .\" Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,13 +27,13 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd September 2, 2020
+.Dd March 30, 2022
 .Dt MEMBAR_OPS 3
 .Os
 .Sh NAME
 .Nm membar_ops ,
-.Nm membar_enter ,
-.Nm membar_exit ,
+.Nm membar_acquire ,
+.Nm membar_release ,
 .Nm membar_producer ,
 .Nm membar_consumer ,
 .Nm membar_datadep_consumer ,
@@ -45,9 +45,9 @@
 .In sys/atomic.h
 .\"
 .Ft void
-.Fn membar_enter "void"
+.Fn membar_acquire "void"
 .Ft void
-.Fn membar_exit "void"
+.Fn membar_release "void"
 .Ft void
 .Fn membar_producer "void"
 .Ft void
@@ -65,9 +65,9 @@ relaxed load and store order.
 .Pp
 In general, memory barriers must come in pairs \(em a barrier on one
 CPU, such as
-.Fn membar_exit ,
+.Fn membar_release ,
 must pair with a barrier on another CPU, such as
-.Fn membar_enter ,
+.Fn membar_acquire ,
 in order to synchronize anything between the two CPUs.
 Code using
 .Nm
@@ -92,72 +92,57 @@ not just C11 atomic operations on
 .Vt _Atomic\^ Ns -qualified
 objects.
 .Bl -tag -width abcd
-.It Fn membar_enter
-Any store preceding
-.Fn membar_enter
+.It Fn membar_acquire
+Any load preceding
+.Fn membar_acquire
 will happen before all memory operations following it.
 .Pp
-An atomic read/modify/write operation
-.Pq Xr atomic_ops 3
-followed by a
-.Fn membar_enter
+A load followed by a
+.Fn membar_acquire
 implies a
 .Em load-acquire
 operation in the language of C11.
+.Fn membar_acquire
+should only be used after atomic read/modify/write, such as
+.Xr atomic_cas_uint 3 .
+For regular loads, instead of
+.Li "x = *p; membar_acquire()" ,
+you should use
+.Li "x = atomic_load_acquire(p)" .
 .Pp
-.Sy WARNING :
-A load followed by
-.Fn membar_enter
-.Em does not
-imply a
-.Em load-acquire
-operation, even though
-.Fn membar_exit
-followed by a store implies a
-.Em store-release
-operation; the symmetry of these names and asymmetry of the semantics
-is a historical mistake.
-In the
-.Nx
-kernel, you can use
-.Xr atomic_load_acquire 9
-for a
-.Em load-acquire
-operation without any atomic read/modify/write.
-.Pp
-.Fn membar_enter
+.Fn membar_acquire
 is typically used in code that implements locking primitives to ensure
 that a lock protects its data, and is typically paired with
-.Fn membar_exit ;
+.Fn membar_release ;
 see below for an example.
-.It Fn membar_exit
+.It Fn membar_release
 All memory operations preceding
-.Fn membar_exit
+.Fn membar_release
 will happen before any store that follows it.
 .Pp
 A
-.Fn membar_exit
+.Fn membar_release
 followed by a store implies a
 .Em store-release
 operation in the language of C11.
-.Fn membar_exit
+.Fn membar_release
 should only be used before atomic read/modify/write, such as
 .Xr atomic_inc_uint 3 .
 For regular stores, instead of
-.Li "membar_exit(); *p = x" ,
+.Li "membar_release(); *p = x" ,
 you should use
 .Li "atomic_store_release(p, x)" .
 .Pp
-.Fn membar_exit
+.Fn membar_release
 is typically paired with
-.Fn membar_enter ,
+.Fn membar_acquire ,
 and is typically used in code that implements locking or reference
 counting primitives.
 Releasing a lock or reference count should use
-.Fn membar_exit ,
+.Fn membar_release ,
 and acquiring a lock or handling an object after draining references
 should use
-.Fn membar_enter ,
+.Fn membar_acquire ,
 so that whatever happened before releasing will also have happened
 before acquiring.
 For example:
@@ -165,7 +150,7 @@ For example:
 /* thread A -- release a reference */
 obj->state.mumblefrotz = 42;
 KASSERT(valid(&obj->state));
-membar_exit();
+membar_release();
 atomic_dec_uint(&obj->refcnt);
 
 /*
@@ -174,7 +159,7 @@ atomic_dec_uint(&obj->refcnt);
  */
 while (atomic_cas_uint(&obj->refcnt, 0, -1) != 0)
 	continue;
-membar_enter();
+membar_acquire();
 KASSERT(valid(&obj->state));
 obj->state.mumblefrotz--;
 .Ed
@@ -188,9 +173,9 @@ in thread B witnesses the store in
 in thread A setting the reference count to zero,
 .Em then
 everything in thread A before the
-.Fn membar_exit
+.Fn membar_release
 is guaranteed to happen before everything in thread B after the
-.Fn membar_enter ,
+.Fn membar_acquire ,
 as if the machine had sequentially executed:
 .Bd -literal -offset abcdefgh
 obj->state.mumblefrotz = 42;	/* from thread A */
@@ -200,11 +185,11 @@ KASSERT(valid(&obj->state));	/* from thr
 obj->state.mumblefrotz--;
 .Ed
 .Pp
-.Fn membar_exit
+.Fn membar_release
 followed by a store, serving as a
 .Em store-release
 operation, may also be paired with a subsequent load followed by
-.Fn membar_sync ,
+.Fn membar_acquire ,
 serving as the corresponding
 .Em load-acquire
 operation.
@@ -214,7 +199,7 @@ and
 .Xr atomic_load_acquire 9
 instead in that situation, unless the store is an atomic
 read/modify/write which requires a separate
-.Fn membar_exit .
+.Fn membar_release .
 .It Fn membar_producer
 All stores preceding
 .Fn membar_producer
@@ -294,7 +279,7 @@ consume(v);
 .Pp
 .Fn membar_datadep_consumer
 is typically paired with
-.Fn membar_exit
+.Fn membar_release
 by code that initializes an object before publishing it.
 However, you should use
 .Xr atomic_store_release 9
@@ -337,24 +322,48 @@ in C11.
 is typically paired with
 .Fn membar_sync .
 .Pp
-A load followed by
-.Fn membar_sync ,
-serving as a
-.Em load-acquire
-operation, may also be paired with a prior
-.Fn membar_exit
-followed by a store, serving as the corresponding
-.Em store-release
-operation.
-However, you should use
-.Xr atomic_load_acquire 9
-instead of
-.No load-then- Ns Fn membar_sync
-if it is a regular load, or
-.Fn membar_enter
-instead of
 .Fn membar_sync
-if the load is in an atomic read/modify/write operation.
+is typically not needed except in exotic synchronization schemes like
+Dekker's algorithm that require store-before-load ordering.
+If you are tempted to reach for it, see if there is another way to do
+what you're trying to do first.
+.El
+.Sh DEPRECATED MEMORY BARRIERS
+The following memory barriers are deprecated.
+They were imported from Solaris, which describes them as providing
+ordering relative to
+.Sq lock acquisition ,
+but the documentation in
+.Nx
+disagreed with the implementation and use on the semantics.
+.Bl -tag -width abcd
+.It Fn membar_enter
+Originally documented as store-before-load/store, this was instead
+implemented as load-before-load/store on some platforms, which is what
+essentially all uses relied on.
+Now this is implemented as an alias for
+.Fn membar_sync
+everywhere, meaning a full load/store-before-load/store sequential
+consistency barrier, in order to guarantee what the documentation
+claimed
+.Em and
+what the implementation actually did.
+.Pp
+New code should use
+.Fn membar_acquire
+for load-before-load/store ordering, which is what most uses need, or
+.Fn membar_sync
+for store-before-load/store ordering, which typically only appears in
+exotic synchronization schemes like Dekker's algorithm.
+.It Fn membar_exit
+Alias for
+.Fn membar_release .
+This was originally meant to be paired with
+.Fn membar_enter .
+.Pp
+New code should use
+.Fn membar_release
+instead.
 .El
 .Sh SEE ALSO
 .Xr atomic_ops 3 ,
@@ -366,7 +375,19 @@ The
 .Nm membar_ops
 functions first appeared in
 .Nx 5.0 .
+.Pp
 The data-dependent load barrier,
 .Fn membar_datadep_consumer ,
 first appeared in
 .Nx 7.0 .
+.Pp
+The
+.Fn membar_acquire
+and
+.Fn membar_release
+functions first appeared, and the
+.Fn membar_enter
+and
+.Fn membar_exit
+functions were deprecated, in
+.Nx 10.0 .

Index: src/share/man/man9/atomic_loadstore.9
diff -u src/share/man/man9/atomic_loadstore.9:1.6 src/share/man/man9/atomic_loadstore.9:1.7
--- src/share/man/man9/atomic_loadstore.9:1.6	Thu Sep  3 00:23:57 2020
+++ src/share/man/man9/atomic_loadstore.9	Sat Apr  9 23:32:53 2022
@@ -1,4 +1,4 @@
-.\"	$NetBSD: atomic_loadstore.9,v 1.6 2020/09/03 00:23:57 riastradh Exp $
+.\"	$NetBSD: atomic_loadstore.9,v 1.7 2022/04/09 23:32:53 riastradh Exp $
 .\"
 .\" Copyright (c) 2019 The NetBSD Foundation
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 25, 2019
+.Dd February 11, 2022
 .Dt ATOMIC_LOADSTORE 9
 .Os
 .Sh NAME
@@ -648,7 +648,7 @@ is an atomic read/modify/write operation
 .Xr atomic_ops 3 ,
 then
 .Bd -literal
-	membar_exit();
+	membar_release();
 	atomic_r/m/w(obj, ...);
 .Ed
 .Pp
@@ -657,32 +657,34 @@ functions like a release operation on
 and
 .Bd -literal
 	atomic_r/m/w(obj, ...);
-	membar_enter();
+	membar_acquire();
 .Ed
 .Pp
 functions like a acquire operation on
 .Va obj .
 .Pp
-.Sy WARNING :
-The combination of
-.Fn atomic_load_relaxed
-and
-.Xr membar_enter 3
-.Em does not
-make an acquire operation; only read/modify/write atomics may be
-combined with
-.Xr membar_enter 3
-this way.
-.Pp
 On architectures where
 .Dv __HAVE_ATOMIC_AS_MEMBAR
 is defined, all the
 .Xr atomic_ops 3
 imply release and acquire operations, so the
-.Xr membar_enter 3
+.Xr membar_acquire 3
 and
-.Xr membar_exit 3
+.Xr membar_release 3
 are redundant.
+.Pp
+The combination of
+.Fn atomic_load_relaxed
+and
+.Xr membar_acquire 3
+in that order is equivalent to
+.Fn atomic_load_acquire ,
+and the combination of
+.Xr membar_release 3
+and
+.Fn atomic_store_relaxed
+in that order is equivalent to
+.Fn atomic_store_release .
 .Sh EXAMPLES
 Maintaining lossy counters.
 These may lose some counts, because the read/modify/write cycle as a

Index: src/sys/sys/atomic.h
diff -u src/sys/sys/atomic.h:1.22 src/sys/sys/atomic.h:1.23
--- src/sys/sys/atomic.h:1.22	Sat Dec 18 16:31:40 2021
+++ src/sys/sys/atomic.h	Sat Apr  9 23:32:53 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: atomic.h,v 1.22 2021/12/18 16:31:40 riastradh Exp $	*/
+/*	$NetBSD: atomic.h,v 1.23 2022/04/09 23:32:53 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
@@ -181,12 +181,18 @@ uint8_t 	atomic_cas_8(volatile uint8_t *
 /*
  * Memory barrier operations
  */
-void		membar_enter(void);
-void		membar_exit(void);
+void		membar_acquire(void);
+void		membar_release(void);
 void		membar_producer(void);
 void		membar_consumer(void);
 void		membar_sync(void);
 
+/*
+ * Deprecated memory barriers
+ */
+void		membar_enter(void);
+void		membar_exit(void);
+
 #ifdef	__HAVE_MEMBAR_DATADEP_CONSUMER
 void		membar_datadep_consumer(void);
 #else

Index: src/tests/lib/libc/membar/t_dekker.c
diff -u src/tests/lib/libc/membar/t_dekker.c:1.1 src/tests/lib/libc/membar/t_dekker.c:1.2
--- src/tests/lib/libc/membar/t_dekker.c:1.1	Fri Apr  8 23:35:52 2022
+++ src/tests/lib/libc/membar/t_dekker.c	Sat Apr  9 23:32:53 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_dekker.c,v 1.1 2022/04/08 23:35:52 riastradh Exp $	*/
+/*	$NetBSD: t_dekker.c,v 1.2 2022/04/09 23:32:53 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2022 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: t_dekker.c,v 1.1 2022/04/08 23:35:52 riastradh Exp $");
+__RCSID("$NetBSD: t_dekker.c,v 1.2 2022/04/09 23:32:53 riastradh Exp $");
 
 #include <sys/atomic.h>
 #include <sys/param.h>
@@ -44,10 +44,6 @@ __RCSID("$NetBSD: t_dekker.c,v 1.1 2022/
 #include <stdio.h>
 #include <unistd.h>
 
-/* XXX */
-#define	membar_acquire()	membar_enter()
-#define	membar_release()	membar_exit()
-
 #ifdef	BROKEN_SYNC
 #undef	membar_sync
 #define	membar_sync()	asm volatile("" ::: "memory")
Index: src/tests/lib/libc/membar/t_spinlock.c
diff -u src/tests/lib/libc/membar/t_spinlock.c:1.1 src/tests/lib/libc/membar/t_spinlock.c:1.2
--- src/tests/lib/libc/membar/t_spinlock.c:1.1	Fri Apr  8 23:35:52 2022
+++ src/tests/lib/libc/membar/t_spinlock.c	Sat Apr  9 23:32:53 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_spinlock.c,v 1.1 2022/04/08 23:35:52 riastradh Exp $	*/
+/*	$NetBSD: t_spinlock.c,v 1.2 2022/04/09 23:32:53 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2022 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: t_spinlock.c,v 1.1 2022/04/08 23:35:52 riastradh Exp $");
+__RCSID("$NetBSD: t_spinlock.c,v 1.2 2022/04/09 23:32:53 riastradh Exp $");
 
 #include <sys/atomic.h>
 #include <sys/param.h>
@@ -44,10 +44,6 @@ __RCSID("$NetBSD: t_spinlock.c,v 1.1 202
 #include <stdio.h>
 #include <unistd.h>
 
-/* XXX */
-#define	membar_acquire()	membar_enter()
-#define	membar_release()	membar_exit()
-
 #ifdef	BROKEN_ACQUIRE
 #undef	membar_acquire
 #define	membar_acquire()	asm volatile("" ::: "memory")

Reply via email to