Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/atomic Reword advice about when not to use membar_e...
details: https://anonhg.NetBSD.org/src/rev/78f8efc33601
branches: trunk
changeset: 976938:78f8efc33601
user: riastradh <riastradh%NetBSD.org@localhost>
date: Fri Oct 09 17:36:16 2020 +0000
description:
Reword advice about when not to use membar_exit.
With help from skrll and pgoyette.
While here, change the example so it doesn't violate the advice just
given. Still not a great example -- abusing UINT_MAX for a reference
count is kinda sketchy, but it'll serve for now.
diffstat:
lib/libc/atomic/membar_ops.3 | 48 +++++++++++++++++++++++++++----------------
1 files changed, 30 insertions(+), 18 deletions(-)
diffs (79 lines):
diff -r 2de6466597eb -r 78f8efc33601 lib/libc/atomic/membar_ops.3
--- a/lib/libc/atomic/membar_ops.3 Fri Oct 09 17:01:29 2020 +0000
+++ b/lib/libc/atomic/membar_ops.3 Fri Oct 09 17:36:16 2020 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: membar_ops.3,v 1.6 2020/09/03 00:00:06 riastradh Exp $
+.\" $NetBSD: membar_ops.3,v 1.7 2020/10/09 17:36:16 riastradh Exp $
.\"
.\" Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -140,28 +140,40 @@
followed by a store implies a
.Em store-release
operation in the language of C11.
-For a regular store, rather than an atomic read/modify/write store, you
-should use
-.Xr atomic_store_release 9
-instead of
.Fn membar_exit
-followed by the store.
+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" ,
+you should use
+.Li "atomic_store_release(p, x)" .
.Pp
.Fn membar_exit
-is typically used in code that implements locking primitives to ensure
-that a lock protects its data, and is typically paired with
-.Fn membar_enter .
+is typically paired with
+.Fn membar_enter ,
+and is typically used in code that implements locking or reference
+counting primitives.
+Releasing a lock or reference count should use
+.Fn membar_exit ,
+and acquiring a lock or handling an object after draining references
+should use
+.Fn membar_enter ,
+so that whatever happened before releasing will also have happened
+before acquiring.
For example:
.Bd -literal -offset abcdefgh
-/* thread A */
+/* thread A -- release a reference */
obj->state.mumblefrotz = 42;
KASSERT(valid(&obj->state));
membar_exit();
-obj->lock = 0;
+atomic_dec_uint(&obj->refcnt);
-/* thread B */
-if (atomic_cas_uint(&obj->lock, 0, 1) != 0)
- return;
+/*
+ * thread B -- busy-wait until last reference is released,
+ * then lock it by setting refcnt to UINT_MAX
+ */
+while (atomic_cas_uint(&obj->refcnt, 0, -1) != 0)
+ continue;
membar_enter();
KASSERT(valid(&obj->state));
obj->state.mumblefrotz--;
@@ -169,11 +181,11 @@
.Pp
In this example,
.Em if
-the
+the load in
.Fn atomic_cas_uint
-operation in thread B witnesses the store
-.Li "obj->lock = 0"
-from thread A,
+in thread B witnesses the store in
+.Fn atomic_dec_uint
+in thread A setting the reference count to zero,
.Em then
everything in thread A before the
.Fn membar_exit
Home |
Main Index |
Thread Index |
Old Index