Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern pcq(9): Fix consume operation in pcq_peek/get.
details: https://anonhg.NetBSD.org/src/rev/649eeac6ad6c
branches: trunk
changeset: 373656:649eeac6ad6c
user: riastradh <riastradh%NetBSD.org@localhost>
date: Thu Feb 23 03:01:22 2023 +0000
description:
pcq(9): Fix consume operation in pcq_peek/get.
These use atomic_load_consume to match the atomic_store_release in
pcq_put for pcq->pcq_items[c].
Reading the snapshot of pcq->pcq_pc need not be ordered:
- The consumer side (pcq_peek/get) is serialized by the API contract
(single-consumer, multi-producer), so no ordering is necessary.
- The producer side updates pcq->pcq_pc first; if the consumer side
sees that before the producer side has stored pcq->pcq_items[c],
there's no problem -- it's as if the consumer had happened just a
moment earlier and the producer hadn't entered pcq_put yet.
However, it should be an atomic load, not a plain load. So use
atomic_load_relaxed, if for no other reason than to pacify thread
sanitizers.
XXX pullup-9
XXX pullup-10
diffstat:
sys/kern/subr_pcq.c | 19 ++++++++-----------
1 files changed, 8 insertions(+), 11 deletions(-)
diffs (71 lines):
diff -r f2210eaa7f72 -r 649eeac6ad6c sys/kern/subr_pcq.c
--- a/sys/kern/subr_pcq.c Thu Feb 23 03:00:53 2023 +0000
+++ b/sys/kern/subr_pcq.c Thu Feb 23 03:01:22 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_pcq.c,v 1.14 2023/02/23 03:00:53 riastradh Exp $ */
+/* $NetBSD: subr_pcq.c,v 1.15 2023/02/23 03:01:22 riastradh Exp $ */
/*-
* Copyright (c) 2009, 2019 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pcq.c,v 1.14 2023/02/23 03:00:53 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pcq.c,v 1.15 2023/02/23 03:01:22 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -100,7 +100,7 @@
KASSERT(item != NULL);
do {
- v = pcq->pcq_pc;
+ v = atomic_load_relaxed(&pcq->pcq_pc);
pcq_split(v, &op, &c);
p = pcq_advance(pcq, op);
if (p == c) {
@@ -132,14 +132,13 @@
void *
pcq_peek(pcq_t *pcq)
{
- const uint32_t v = pcq->pcq_pc;
+ const uint32_t v = atomic_load_relaxed(&pcq->pcq_pc);
u_int p, c;
pcq_split(v, &p, &c);
/* See comment on race below in pcq_get(). */
- return (p == c) ? NULL :
- (membar_datadep_consumer(), pcq->pcq_items[c]);
+ return (p == c) ? NULL : atomic_load_consume(&pcq->pcq_items[c]);
}
/*
@@ -154,15 +153,13 @@
u_int p, c;
void *item;
- v = pcq->pcq_pc;
+ v = atomic_load_relaxed(&pcq->pcq_pc);
pcq_split(v, &p, &c);
if (p == c) {
/* Queue is empty: nothing to return. */
return NULL;
}
- /* Make sure we read pcq->pcq_pc before pcq->pcq_items[c]. */
- membar_datadep_consumer();
- item = pcq->pcq_items[c];
+ item = atomic_load_consume(&pcq->pcq_items[c]);
if (item == NULL) {
/*
* Raced with sender: we rely on a notification (e.g. softint
@@ -185,7 +182,7 @@
membar_producer();
#endif
while (__predict_false(atomic_cas_32(&pcq->pcq_pc, v, nv) != v)) {
- v = pcq->pcq_pc;
+ v = atomic_load_relaxed(&pcq->pcq_pc);
pcq_split(v, &p, &c);
c = pcq_advance(pcq, c);
nv = pcq_combine(p, c);
Home |
Main Index |
Thread Index |
Old Index