Skip to content

Commit b4a9baa

Browse files
author
dave
committed
#27 Yield for micros could get stuck when a running task got in front of other tasks in the run Q
1 parent a5c3c01 commit b4a9baa

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

src/TaskManagerIO.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,9 @@ void TaskManager::runLoop() {
207207
// go through the timer (scheduled) tasks in priority order. they are stored
208208
// in a linked list ordered by first to be scheduled. So we only go through
209209
// these until the first one that isn't ready.
210-
TimerTask* tm;
211-
while((tm = tm_internal::atomicReadPtr(&first)) != nullptr) {
212-
#if defined(ESP8266) || defined(ESP32)
213-
// here we are making extra sure we are good citizens on ESP boards
214-
yield();
215-
#endif
210+
TimerTask* tm = tm_internal::atomicReadPtr(&first);
216211

217-
if (!tm->isReady()) break;
212+
while (tm && tm->isReady()) {
218213

219214
// by here we know that the task is in use. If it's in use nothing will touch it until it's marked as
220215
// available. We can do this part without a lock, knowing that we are the only thing that will touch
@@ -223,14 +218,22 @@ void TaskManager::runLoop() {
223218
tm->execute();
224219
tm_internal::atomicWritePtr(&runningTask, nullptr);
225220
removeFromQueue(tm);
226-
if(tm->isRepeating()) {
221+
if (tm->isRepeating()) {
227222
putItemIntoQueue(tm);
228-
}
229-
else {
223+
} else {
230224
tm->clear();
231225
tm_internal::tmNotification(tm_internal::TM_INFO_TASK_FREE, TASKMGR_INVALIDID);
232226
}
233-
}
227+
if(microsToNextTask() > 0) break;
228+
tm = tm->getNext();
229+
230+
#if defined(ESP8266) || defined(ESP32)
231+
if(tm) {
232+
// here we are making extra sure we are good citizens on ESP boards
233+
yield();
234+
}
235+
#endif
236+
}
234237
}
235238

236239
void TaskManager::putItemIntoQueue(TimerTask* tm) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
#include <AUnit.h>
3+
#include <ReentrantYieldingLock.h>
4+
#include "TaskManagerIO.h"
5+
#include "test_utils.h"
6+
7+
using namespace aunit;
8+
9+
ReentrantYieldingLock testLock;
10+
taskid_t runTaskId1;
11+
taskid_t runTaskId2;
12+
13+
bool task1RunningPtrCheck = false;
14+
bool task2RunningPtrCheck = false;
15+
16+
test(testGettingRunningTaskAlwaysCorrect) {
17+
taskManager.reset();
18+
assertEqual(nullptr, taskManager.getRunningTask());
19+
20+
serdebugF("Starting running task check");
21+
22+
runTaskId1 = taskManager.scheduleFixedRate(1, [] {
23+
task1RunningPtrCheck = taskManager.getRunningTask() == taskManager.getTask(runTaskId1);
24+
if(task1RunningPtrCheck) {
25+
taskManager.yieldForMicros(millisToMicros(1));
26+
27+
task1RunningPtrCheck = taskManager.getRunningTask() == taskManager.getTask(runTaskId1);
28+
}
29+
});
30+
31+
runTaskId2 = taskManager.scheduleFixedRate(50, [] {
32+
task2RunningPtrCheck = taskManager.getRunningTask() == taskManager.getTask(runTaskId2);
33+
}, TIME_MICROS);
34+
35+
serdebugF("Scheduled running task check");
36+
37+
taskManager.yieldForMicros(millisToMicros(100));
38+
39+
serdebugF("Finished running task check, asserting.");
40+
41+
assertTrue(task1RunningPtrCheck);
42+
assertTrue(task2RunningPtrCheck);
43+
}
44+
45+
test(testReentrantLock) {
46+
47+
}

0 commit comments

Comments
 (0)