From 58a36277cfaf95cba8609c1ddc823df2bc9fb60e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 4 Jul 2023 13:31:54 -0400 Subject: ioq: Don't write to an empty slot in ioqq_trypop() --- src/ioq.c | 16 ++++++++++------ 1 file 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; } -- cgit v1.2.3