diff --git a/src/shared/scheduler/TaskScheduler.cpp b/src/shared/scheduler/TaskScheduler.cpp
index 3e52a534226882072b4933a6d4ca8cc9cfce748b..6e14dfefbd336014d386b89a585950aad993731c 100644
--- a/src/shared/scheduler/TaskScheduler.cpp
+++ b/src/shared/scheduler/TaskScheduler.cpp
@@ -62,14 +62,17 @@ TaskScheduler::TaskScheduler(miosix::Priority priority)
 size_t TaskScheduler::addTask(function_t function, uint32_t period,
                               Policy policy, int64_t startTick)
 {
-    // Lock the mutex manually to avoid relocking in the case of early returns
+    // In the case of early returns, using RAII mutex wrappers to unlock the
+    // mutex would cause it to be locked and unlocked one more time before
+    // returning, because of the destructor being called on the Unlock object
+    // first and then on the Lock object. To avoid this, we don't use RAII
+    // wrappers and manually lock and unlock the mutex instead.
     mutex.lock();
 
     if (tasks.size() >= MAX_TASKS)
     {
         // Unlock the mutex to release the scheduler resources before logging
         mutex.unlock();
-
         LOG_ERR(logger, "Full task scheduler");
         return 0;
     }
@@ -97,14 +100,15 @@ size_t TaskScheduler::addTask(function_t function, uint32_t period,
 
 void TaskScheduler::enableTask(size_t id)
 {
+    mutex.lock();
+
     if (id > tasks.size() - 1)
     {
+        mutex.unlock();
         LOG_ERR(logger, "Tried to enable an out-of-range task, id = {}", id);
         return;
     }
 
-    // Lock the mutex manually to avoid relocking in the case of early returns
-    mutex.lock();
     Task& task = tasks[id];
 
     // Check that the task function is not empty
@@ -112,7 +116,6 @@ void TaskScheduler::enableTask(size_t id)
     // exception
     if (task.empty())
     {
-        // Unlock the mutex to release the scheduler resources before logging
         mutex.unlock();
         LOG_WARN(logger, "Tried to enable an empty task, id = {}", id);
         return;
@@ -125,18 +128,23 @@ void TaskScheduler::enableTask(size_t id)
 
 void TaskScheduler::disableTask(size_t id)
 {
+    mutex.lock();
+
     if (id > tasks.size() - 1)
     {
+        mutex.unlock();
         LOG_ERR(logger, "Tried to disable an out-of-range task, id = {}", id);
         return;
     }
 
-    Lock<FastMutex> lock(mutex);
     tasks[id].enabled = false;
+    mutex.unlock();
 }
 
 bool TaskScheduler::start()
 {
+    Lock<FastMutex> lock(mutex);
+
     // This check is necessary to prevent task normalization if the scheduler is
     // already stopped
     if (running)
@@ -203,7 +211,9 @@ void TaskScheduler::run()
     while (true)
     {
         while (agenda.empty() && !shouldStop())
+        {
             condvar.wait(mutex);
+        }
 
         // Exit if the ActiveObject has been stopped
         if (shouldStop())