summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-07-04 13:31:54 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-07-04 13:32:14 -0400
commit58a36277cfaf95cba8609c1ddc823df2bc9fb60e (patch)
treeb337759c0dd032d0853abf18fc44f771d583f384
parent4a6e24764b4248a1a97a338138fa71c2c8c4d1d0 (diff)
downloadbfs-58a36277cfaf95cba8609c1ddc823df2bc9fb60e.tar.xz
ioq: Don't write to an empty slot in ioqq_trypop()
-rw-r--r--src/ioq.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/src/ioq.c b/src/ioq.c
index 1160b34..10451ac 100644
--- a/src/ioq.c
+++ b/src/ioq.c
@@ -240,18 +240,22 @@ static union ioq_cmd *ioqq_trypop(struct ioqq *ioqq) {
size_t i = load(&ioqq->tail, relaxed);
atomic uintptr_t *slot = &ioqq->slots[i & ioqq->slot_mask];
- uintptr_t prev = exchange(slot, 0, acquire);
+ uintptr_t prev = load(slot, relaxed);
+ if (!(prev & ~IOQ_BLOCKED)) {
+ return NULL;
+ }
+ if (!compare_exchange_weak(slot, &prev, 0, acquire, relaxed)) {
+ return NULL;
+ }
if (prev & IOQ_BLOCKED) {
ioqq_wake(ioqq, i);
}
prev &= ~IOQ_BLOCKED;
- if (prev) {
- size_t j = exchange(&ioqq->tail, i + IOQ_STRIDE, relaxed);
- bfs_assert(j == i, "ioqq_trypop() only supports a single consumer");
- (void)j;
- }
+ size_t j = exchange(&ioqq->tail, i + IOQ_STRIDE, relaxed);
+ bfs_assert(j == i, "ioqq_trypop() only supports a single consumer");
+ (void)j;
return (union ioq_cmd *)prev;
}