Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Feb 2025 15:56:45 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d2870b8666f2 - main - queue: Add atomic variants for *_EMPTY
Message-ID:  <202502141556.51EFujI8046152@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=d2870b8666f2438af400269c0f6a1a48031bb71e

commit d2870b8666f2438af400269c0f6a1a48031bb71e
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-02-14 15:45:11 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-02-14 15:45:11 +0000

    queue: Add atomic variants for *_EMPTY
    
    In some places, these macros are used without a lock, under the
    assumption that they are naturally atomic.  After commit
    34740937f7a4 ("queue: New debug macros for STAILQ"), this assumption is
    false.
    
    Provide *_EMPTY_ATOMIC for such cases.  This lets us include extra debug
    checks for the non-atomic case, and gives us a way to explicitly
    annotate unlocked checks, which generally deserve extra scrutiny and
    might otherwise raise reports from KCSAN.
    
    Reviewed by:    kib, olce (previous version)
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D48899
---
 share/man/man3/queue.3 | 26 +++++++++++++++++++++++++-
 sys/sys/queue.h        | 12 ++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/share/man/man3/queue.3 b/share/man/man3/queue.3
index be890fd2cc88..e55c7cfb7513 100644
--- a/share/man/man3/queue.3
+++ b/share/man/man3/queue.3
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 8, 2024
+.Dd February 10, 2025
 .Dt QUEUE 3
 .Os
 .Sh NAME
@@ -33,6 +33,7 @@
 .Nm SLIST_CLASS_HEAD ,
 .Nm SLIST_CONCAT ,
 .Nm SLIST_EMPTY ,
+.Nm SLIST_EMPTY_ATOMIC ,
 .Nm SLIST_ENTRY ,
 .Nm SLIST_FIRST ,
 .Nm SLIST_FOREACH ,
@@ -53,6 +54,7 @@
 .Nm STAILQ_CLASS_HEAD ,
 .Nm STAILQ_CONCAT ,
 .Nm STAILQ_EMPTY ,
+.Nm STAILQ_EMPTY_ATOMIC ,
 .Nm STAILQ_ENTRY ,
 .Nm STAILQ_FIRST ,
 .Nm STAILQ_FOREACH ,
@@ -75,6 +77,7 @@
 .Nm LIST_CLASS_HEAD ,
 .Nm LIST_CONCAT ,
 .Nm LIST_EMPTY ,
+.Nm LIST_EMPTY_ATOMIC ,
 .Nm LIST_ENTRY ,
 .Nm LIST_FIRST ,
 .Nm LIST_FOREACH ,
@@ -96,6 +99,7 @@
 .Nm TAILQ_CLASS_HEAD ,
 .Nm TAILQ_CONCAT ,
 .Nm TAILQ_EMPTY ,
+.Nm TAILQ_EMPTY_ATOMIC ,
 .Nm TAILQ_ENTRY ,
 .Nm TAILQ_FIRST ,
 .Nm TAILQ_FOREACH ,
@@ -128,6 +132,7 @@ lists and tail queues
 .Fn SLIST_CLASS_HEAD "HEADNAME" "CLASSTYPE"
 .Fn SLIST_CONCAT "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE" "SLIST_ENTRY NAME"
 .Fn SLIST_EMPTY "SLIST_HEAD *head"
+.Fn SLIST_EMPTY_ATOMIC "SLIST_HEAD *head"
 .Fn SLIST_ENTRY "TYPE"
 .Fn SLIST_FIRST "SLIST_HEAD *head"
 .Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
@@ -149,6 +154,7 @@ lists and tail queues
 .Fn STAILQ_CLASS_HEAD "HEADNAME" "CLASSTYPE"
 .Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
 .Fn STAILQ_EMPTY "STAILQ_HEAD *head"
+.Fn STAILQ_EMPTY_ATOMIC "STAILQ_HEAD *head"
 .Fn STAILQ_ENTRY "TYPE"
 .Fn STAILQ_FIRST "STAILQ_HEAD *head"
 .Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
@@ -172,6 +178,7 @@ lists and tail queues
 .Fn LIST_CLASS_HEAD "HEADNAME" "CLASSTYPE"
 .Fn LIST_CONCAT "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
 .Fn LIST_EMPTY "LIST_HEAD *head"
+.Fn LIST_EMPTY_ATOMIC "LIST_HEAD *head"
 .Fn LIST_ENTRY "TYPE"
 .Fn LIST_FIRST "LIST_HEAD *head"
 .Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
@@ -194,6 +201,7 @@ lists and tail queues
 .Fn TAILQ_CLASS_HEAD "HEADNAME" "CLASSTYPE"
 .Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME"
 .Fn TAILQ_EMPTY "TAILQ_HEAD *head"
+.Fn TAILQ_EMPTY_ATOMIC "TAILQ_HEAD *head"
 .Fn TAILQ_ENTRY "TYPE"
 .Fn TAILQ_FIRST "TAILQ_HEAD *head"
 .Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
@@ -425,6 +433,10 @@ high-usage code paths or to operate on long lists.
 The macro
 .Nm SLIST_EMPTY
 evaluates to true if there are no elements in the list.
+The
+.Nm SLIST_EMPTY_ATOMIC
+variant has the same behavior, but can be safely used in contexts where it is
+possible that a different thread is concurrently updating the list.
 .Pp
 The macro
 .Nm SLIST_ENTRY
@@ -633,6 +645,10 @@ removing all entries from the former.
 The macro
 .Nm STAILQ_EMPTY
 evaluates to true if there are no items on the tail queue.
+The
+.Nm STAILQ_EMPTY_ATOMIC
+variant has the same behavior, but can be safely used in contexts where it is
+possible that a different thread is concurrently updating the queue.
 .Pp
 The macro
 .Nm STAILQ_ENTRY
@@ -866,6 +882,10 @@ high-usage code paths or to operate on long lists.
 The macro
 .Nm LIST_EMPTY
 evaluates to true if there are no elements in the list.
+The
+.Nm LIST_EMPTY_ATOMIC
+variant has the same behavior, but can be safely used in contexts where it is
+possible that a different thread is concurrently updating the list.
 .Pp
 The macro
 .Nm LIST_ENTRY
@@ -1084,6 +1104,10 @@ removing all entries from the former.
 The macro
 .Nm TAILQ_EMPTY
 evaluates to true if there are no items on the tail queue.
+The
+.Nm TAILQ_EMPTY_ATOMIC
+variant has the same behavior, but can be safely used in contexts where it is
+possible that a different thread is concurrently updating the queue.
 .Pp
 The macro
 .Nm TAILQ_ENTRY
diff --git a/sys/sys/queue.h b/sys/sys/queue.h
index c1fa8cd812cf..6e4da0fa0bec 100644
--- a/sys/sys/queue.h
+++ b/sys/sys/queue.h
@@ -226,6 +226,9 @@ struct {								\
 
 #define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
 
+#define	SLIST_EMPTY_ATOMIC(head)					\
+	(atomic_load_ptr(&(head)->slh_first) == NULL)
+
 #define	SLIST_FIRST(head)	((head)->slh_first)
 
 #define	SLIST_FOREACH(var, head, field)					\
@@ -387,6 +390,9 @@ struct {								\
 	STAILQ_FIRST(head) == NULL;					\
 })
 
+#define	STAILQ_EMPTY_ATOMIC(head)					\
+	(atomic_load_ptr(&(head)->stqh_first) == NULL)
+
 #define	STAILQ_FIRST(head)	((head)->stqh_first)
 
 #define	STAILQ_FOREACH(var, head, field)				\
@@ -575,6 +581,9 @@ struct {								\
 
 #define	LIST_EMPTY(head)	((head)->lh_first == NULL)
 
+#define	LIST_EMPTY_ATOMIC(head)						\
+	(atomic_load_ptr(&(head)->lh_first) == NULL)
+
 #define	LIST_FIRST(head)	((head)->lh_first)
 
 #define	LIST_FOREACH(var, head, field)					\
@@ -779,6 +788,9 @@ struct {								\
 
 #define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
 
+#define	TAILQ_EMPTY_ATOMIC(head)					\
+	(atomic_load_ptr(&(head)->tqh_first) == NULL)
+
 #define	TAILQ_FIRST(head)	((head)->tqh_first)
 
 #define	TAILQ_FOREACH(var, head, field)					\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502141556.51EFujI8046152>