From 9aab33c2e99e8dc134fdb7029c257c0c31649f84 Mon Sep 17 00:00:00 2001
From: Terraneo Federico <fede.tft@miosix.org>
Date: Thu, 27 Apr 2023 01:04:51 +0200
Subject: [PATCH] Prevent spurious wakeup in Semaphore

---
 miosix/kernel/sync.cpp | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/miosix/kernel/sync.cpp b/miosix/kernel/sync.cpp
index 5d66ed60..b7cc79b9 100644
--- a/miosix/kernel/sync.cpp
+++ b/miosix/kernel/sync.cpp
@@ -454,6 +454,7 @@ Thread *Semaphore::IRQsignalNoPreempt()
     }
     WaitToken *cd=fifo.front();
     Thread *t=cd->thread;
+    cd->thread=nullptr; //Thread pointer doubles as flag against spurious wakeup
     fifo.pop_front();
     t->IRQwakeup();
     return t;
@@ -500,8 +501,8 @@ void Semaphore::wait()
     //Otherwise put ourselves in queue and wait
     WaitToken listItem(Thread::IRQgetCurrentThread());
     fifo.push_back(&listItem); //Add entry to tail of list
-    Thread::IRQenableIrqAndWait(dLock);
-    fifo.removeFast(&listItem); //In case of spurious wakeup
+    while(listItem.thread) Thread::IRQenableIrqAndWait(dLock);
+    //Spurious wakeup handled by while loop, listItem already removed from fifo
 }
 
 TimedWaitResult Semaphore::timedWait(long long absTime)
@@ -517,9 +518,15 @@ TimedWaitResult Semaphore::timedWait(long long absTime)
     //Otherwise put ourselves in queue and wait
     WaitToken listItem(Thread::IRQgetCurrentThread());
     fifo.push_back(&listItem); //Add entry to tail of list
-    auto result=Thread::IRQenableIrqAndTimedWait(dLock,absTime);
-    fifo.removeFast(&listItem); //In case of timeout or spurious wakeup
-    return result;
+    while(listItem.thread)
+    {
+        if(Thread::IRQenableIrqAndTimedWait(dLock,absTime)==TimedWaitResult::Timeout)
+        {
+            fifo.removeFast(&listItem); //Remove fifo entry in case of timeout
+            return TimedWaitResult::Timeout;
+        }
+    }
+    return TimedWaitResult::NoTimeout;
 }
 
 } //namespace miosix
-- 
GitLab