I am using FreeRTOS to dispatch task set of 4 periodical tasks.
All tasks have the same period of 10 time units, but they differ in their release times. Release times are 10,3,5,0 time units for tasks T1,T2,T3,T4 respectively. All 4 tasks are stored inside the linked list gll_t* pTaskList
. Tasks should run e.g.,
t=0 T4 is released, t=3 T2 is released, t=5 T3 is released, t=10 T1 is relased and T4 is executed again since it was released at t = 0, and so on...
However I have two problems with my dispatcher code:
1. Problem At t=0, only T4 is ready, but note that T1 has release time at 10, According to my if statement for T1 I have 0 % (10 + 10) == 0
, and T1 gets released even though it's not ready. I could introduce a boolean that tells whether a task has been released, but is there a smarter way to do it without introducing extra variables?
2. Problem At t=26, no tasks are ready, however, task T2 gets released. According to my if statement for T2 I have 26 % (3 + 10) == 0
.
void prvTaskSchedulerProcess(void *pvParameters) {
...
uint32_t uCurrentTickCount = 0;
gll_t* pTaskList = (gll_t*) pvParameters;
WorkerTask_t* pWorkerTask = NULL;
while (true) {
for (uint8_t uIndex = 0; uIndex < pTaskList->size; uIndex++) {
pWorkerTask = gll_get(pTaskList, uIndex);
// Check if the task is ready to be executed
if ( (uCurrentTickCount % (pWorkerTask->uReleaseTime + pWorkerTask->uPeriod) ) == 0) ){
// Dispatch the ready task
vTaskResume(pWorkerTask->xHandle);
}
}
uCurrentTickCount++;
// Sleep the scheduler task, so the other tasks can run
vTaskDelay(TASK_SCHEDULER_TICK_TIME * SCHEDULER_OUTPUT_FREQUENCY_MS);
}
}
Using extra flags seems like a simple solution. However I was told that introducing flags variables is not best solution, because it makes code less readable and maintainable. Thus, I want to avoid using them. How would the correct task dispatching be achieved without using the extra flags (possibly correcting my if statement condition)?
To fix problem 2, use the following condition instead of what you have.
if ((uCurrentTickCount % pWorkerTask->uPeriod) == pWorkerTask->uReleaseTime)
To fix problem 1 (and problem 2), use the following condition.
if ((uCurrentTickCount >= pWorkerTask->uReleaseTime) &&
((uCurrentTickCount % pWorkerTask->uPeriod) == (pWorkerTask->uReleaseTime % pWorker->uPeriod)))