From 80ce73a2c1535d70752f06cbcd9f6ebd33904a05 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 19 Oct 2020 22:08:37 +0200 Subject: [PATCH] Fix executor hanging in some cases where tasks wake themselves. --- embassy/src/executor/executor.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/embassy/src/executor/executor.rs b/embassy/src/executor/executor.rs index 62b781ba..43127d61 100644 --- a/embassy/src/executor/executor.rs +++ b/embassy/src/executor/executor.rs @@ -110,18 +110,16 @@ impl Queue { } unsafe fn dequeue_all(&self, on_task: impl Fn(*mut Header)) { - loop { - let mut task = self.head.swap(ptr::null_mut(), Ordering::AcqRel); + let mut task = self.head.swap(ptr::null_mut(), Ordering::AcqRel); - if task.is_null() { - // Queue is empty, we're done - return; - } + while !task.is_null() { + // If the task re-enqueues itself, the `next` pointer will get overwritten. + // Therefore, first read the next pointer, and only then process the task. + let next = (*task).next.load(Ordering::Relaxed); - while !task.is_null() { - on_task(task); - task = (*task).next.load(Ordering::Relaxed); - } + on_task(task); + + task = next } } }