diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-07-04 13:31:54 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-07-04 13:32:14 -0400 |
commit | 58a36277cfaf95cba8609c1ddc823df2bc9fb60e (patch) | |
tree | b337759c0dd032d0853abf18fc44f771d583f384 | |
parent | 4a6e24764b4248a1a97a338138fa71c2c8c4d1d0 (diff) | |
download | bfs-58a36277cfaf95cba8609c1ddc823df2bc9fb60e.tar.xz |
ioq: Don't write to an empty slot in ioqq_trypop()
-rw-r--r-- | src/ioq.c | 16 |
1 files changed, 10 insertions, 6 deletions
@@ -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; } |