void taskSystem(void) { // Calculate system load if (totalWaitingTasksSamples > 0) { averageSystemLoadPercent = 100 * totalWaitingTasks / totalWaitingTasksSamples; totalWaitingTasksSamples = 0; totalWaitingTasks = 0; } realtimeGuardInterval = 0; #ifdef USE_REALTIME_GUARD_INTERVAL // Calculate guard interval uint32_t maxNonRealtimeTaskTime = 0; for (const cfTask_t *task = queueFirst(); task != NULL; task = queueNext()) { if (task->staticPriority != TASK_PRIORITY_REALTIME) { maxNonRealtimeTaskTime = MAX(maxNonRealtimeTaskTime, task->averageExecutionTime); } } realtimeGuardInterval = constrain(maxNonRealtimeTaskTime, REALTIME_GUARD_INTERVAL_MIN, REALTIME_GUARD_INTERVAL_MAX) + REALTIME_GUARD_INTERVAL_MARGIN; #if defined SCHEDULER_DEBUG debug[2] = realtimeGuardInterval; #endif #endif }
void PlaylistWindow::changePlaylistSelection( QUrl itemUrl, QUuid playlistUuid, QUuid itemUuid) { (void)itemUrl; if (!activateItem(playlistUuid, itemUuid)) return; auto pl = PlaylistCollection::getSingleton()->playlistOf(playlistUuid); if (!itemUuid.isNull() && pl->queueFirst() == itemUuid) pl->queueTakeFirst(); }
void scheduler(void) { // Cache currentTime currentTime = micros(); // Check for realtime tasks uint32_t timeToNextRealtimeTask = UINT32_MAX; for (const cfTask_t *task = queueFirst(); task != NULL && task->staticPriority >= TASK_PRIORITY_REALTIME; task = queueNext()) { const uint32_t nextExecuteAt = task->lastExecutedAt + task->desiredPeriod; if ((int32_t)(currentTime - nextExecuteAt) >= 0) { timeToNextRealtimeTask = 0; } else { const uint32_t newTimeInterval = nextExecuteAt - currentTime; timeToNextRealtimeTask = MIN(timeToNextRealtimeTask, newTimeInterval); } } const bool outsideRealtimeGuardInterval = (timeToNextRealtimeTask > realtimeGuardInterval); // The task to be invoked cfTask_t *selectedTask = NULL; uint16_t selectedTaskDynamicPriority = 0; // Update task dynamic priorities uint16_t waitingTasks = 0; for (cfTask_t *task = queueFirst(); task != NULL; task = queueNext()) { // Task has checkFunc - event driven if (task->checkFunc != NULL) { // Increase priority for event driven tasks if (task->dynamicPriority > 0) { task->taskAgeCycles = 1 + ((currentTime - task->lastSignaledAt) / task->desiredPeriod); task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles; waitingTasks++; } else if (task->checkFunc(currentTime - task->lastExecutedAt)) { task->lastSignaledAt = currentTime; task->taskAgeCycles = 1; task->dynamicPriority = 1 + task->staticPriority; waitingTasks++; } else { task->taskAgeCycles = 0; } } else { // Task is time-driven, dynamicPriority is last execution age (measured in desiredPeriods) // Task age is calculated from last execution task->taskAgeCycles = ((currentTime - task->lastExecutedAt) / task->desiredPeriod); if (task->taskAgeCycles > 0) { task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles; waitingTasks++; } } if (task->dynamicPriority > selectedTaskDynamicPriority) { const bool taskCanBeChosenForScheduling = (outsideRealtimeGuardInterval) || (task->taskAgeCycles > 1) || (task->staticPriority == TASK_PRIORITY_REALTIME); if (taskCanBeChosenForScheduling) { selectedTaskDynamicPriority = task->dynamicPriority; selectedTask = task; } } } totalWaitingTasksSamples++; totalWaitingTasks += waitingTasks; currentTask = selectedTask; if (selectedTask != NULL) { // Found a task that should be run selectedTask->taskLatestDeltaTime = currentTime - selectedTask->lastExecutedAt; selectedTask->lastExecutedAt = currentTime; selectedTask->dynamicPriority = 0; // Execute task const uint32_t currentTimeBeforeTaskCall = micros(); selectedTask->taskFunc(); const uint32_t taskExecutionTime = micros() - currentTimeBeforeTaskCall; selectedTask->averageExecutionTime = ((uint32_t)selectedTask->averageExecutionTime * 31 + taskExecutionTime) / 32; #ifndef SKIP_TASK_STATISTICS selectedTask->totalExecutionTime += taskExecutionTime; // time consumed by scheduler + task selectedTask->maxExecutionTime = MAX(selectedTask->maxExecutionTime, taskExecutionTime); #endif #if defined SCHEDULER_DEBUG debug[3] = (micros() - currentTime) - taskExecutionTime; } else { debug[3] = (micros() - currentTime); #endif } GET_SCHEDULER_LOCALS(); }
void scheduler(void) { // Cache currentTime const timeUs_t currentTimeUs = micros(); // Check for realtime tasks timeUs_t timeToNextRealtimeTask = TIMEUS_MAX; for (const cfTask_t *task = queueFirst(); task != NULL && task->staticPriority >= TASK_PRIORITY_REALTIME; task = queueNext()) { const timeUs_t nextExecuteAt = task->lastExecutedAt + task->desiredPeriod; if ((int32_t)(currentTimeUs - nextExecuteAt) >= 0) { timeToNextRealtimeTask = 0; } else { const timeUs_t newTimeInterval = nextExecuteAt - currentTimeUs; timeToNextRealtimeTask = MIN(timeToNextRealtimeTask, newTimeInterval); } } const bool outsideRealtimeGuardInterval = (timeToNextRealtimeTask > 0); // The task to be invoked cfTask_t *selectedTask = NULL; uint16_t selectedTaskDynamicPriority = 0; // Update task dynamic priorities uint16_t waitingTasks = 0; for (cfTask_t *task = queueFirst(); task != NULL; task = queueNext()) { // Task has checkFunc - event driven if (task->checkFunc) { const timeUs_t currentTimeBeforeCheckFuncCallUs = micros(); // Increase priority for event driven tasks if (task->dynamicPriority > 0) { task->taskAgeCycles = 1 + ((timeDelta_t)(currentTimeUs - task->lastSignaledAt)) / task->desiredPeriod; task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles; waitingTasks++; } else if (task->checkFunc(currentTimeBeforeCheckFuncCallUs, currentTimeBeforeCheckFuncCallUs - task->lastExecutedAt)) { #ifndef SKIP_TASK_STATISTICS const timeUs_t checkFuncExecutionTime = micros() - currentTimeBeforeCheckFuncCallUs; checkFuncMovingSumExecutionTime -= checkFuncMovingSumExecutionTime / TASK_MOVING_SUM_COUNT; checkFuncMovingSumExecutionTime += checkFuncExecutionTime; checkFuncTotalExecutionTime += checkFuncExecutionTime; // time consumed by scheduler + task checkFuncMaxExecutionTime = MAX(checkFuncMaxExecutionTime, checkFuncExecutionTime); #endif task->lastSignaledAt = currentTimeBeforeCheckFuncCallUs; task->taskAgeCycles = 1; task->dynamicPriority = 1 + task->staticPriority; waitingTasks++; } else { task->taskAgeCycles = 0; } } else { // Task is time-driven, dynamicPriority is last execution age (measured in desiredPeriods) // Task age is calculated from last execution task->taskAgeCycles = ((timeDelta_t)(currentTimeUs - task->lastExecutedAt)) / task->desiredPeriod; if (task->taskAgeCycles > 0) { task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles; waitingTasks++; } } if (task->dynamicPriority > selectedTaskDynamicPriority) { const bool taskCanBeChosenForScheduling = (outsideRealtimeGuardInterval) || (task->taskAgeCycles > 1) || (task->staticPriority == TASK_PRIORITY_REALTIME); if (taskCanBeChosenForScheduling) { selectedTaskDynamicPriority = task->dynamicPriority; selectedTask = task; } } } totalWaitingTasksSamples++; totalWaitingTasks += waitingTasks; currentTask = selectedTask; if (selectedTask) { // Found a task that should be run selectedTask->taskLatestDeltaTime = (timeDelta_t)(currentTimeUs - selectedTask->lastExecutedAt); selectedTask->lastExecutedAt = currentTimeUs; selectedTask->dynamicPriority = 0; // Execute task const timeUs_t currentTimeBeforeTaskCall = micros(); selectedTask->taskFunc(currentTimeBeforeTaskCall); #ifndef SKIP_TASK_STATISTICS const timeUs_t taskExecutionTime = micros() - currentTimeBeforeTaskCall; selectedTask->movingSumExecutionTime += taskExecutionTime - selectedTask->movingSumExecutionTime / TASK_MOVING_SUM_COUNT; selectedTask->totalExecutionTime += taskExecutionTime; // time consumed by scheduler + task selectedTask->maxExecutionTime = MAX(selectedTask->maxExecutionTime, taskExecutionTime); #endif #if defined(SCHEDULER_DEBUG) DEBUG_SET(DEBUG_SCHEDULER, 2, micros() - currentTimeUs - taskExecutionTime); // time spent in scheduler } else { DEBUG_SET(DEBUG_SCHEDULER, 2, micros() - currentTimeUs); #endif } }
int main(void) { queueHead* queue; int i1 = 1; int i2 = 2; int i3 = 3; int i4 = 4; /* * Test 1 */ /* Create queue */ assert(NULL != (queue = queueCreate())); /* Fill the queue */ assert(1 == (queueAdd(queue, &i1))); /* Insert 1 */ assert(1 == (queueAdd(queue, &i2))); /* Insert 2 */ assert(1 == (queueAdd(queue, &i3))); /* Insert 3 */ assert(1 == (queueAdd(queue, &i4))); /* Insert 4 */ /* Check the queue */ assert(1 == (*(int*)queueFirst(queue))); /* Check 1 */ assert(1 == (*(int*)queueRemove(queue))); /* Remove 1 */ assert(2 == (*(int*)queueFirst(queue))); /* Check 2 */ assert(2 == (*(int*)queueRemove(queue))); /* Remove 2 */ assert(3 == (*(int*)queueFirst(queue))); /* Check 3 */ assert(3 == (*(int*)queueRemove(queue))); /* Remove 3 */ assert(4 == (*(int*)queueFirst(queue))); /* Check 4 */ assert(4 == (*(int*)queueRemove(queue))); /* Remove 4 */ assert(NULL == (queueFirst(queue))); /* Check empty */ assert(NULL == (queueRemove(queue))); /* Queue is empty */ /* Clear the queue */ queueFree(queue); printf("Queue: Test1 success!\n"); /* * Test 2 */ /* Create queue */ assert(NULL != (queue = queueCreate())); /* Fill the queue */ assert(1 == (queueAdd(queue, &i1))); /* Insert 1 */ assert(1 == (*(int*)queueRemove(queue))); /* Remove 1 */ assert(1 == (queueAdd(queue, &i1))); /* Insert 1 */ assert(1 == (queueAdd(queue, &i2))); /* Insert 2 */ assert(1 == (*(int*)queueRemove(queue))); /* Remove 1 */ assert(2 == (*(int*)queueRemove(queue))); /* Remove 2 */ assert(1 == (queueAdd(queue, &i1))); /* Insert 1 */ assert(1 == (*(int*)queueFirst(queue))); /* Check 1 */ assert(1 == (queueAdd(queue, &i2))); /* Insert 2 */ assert(1 == (*(int*)queueRemove(queue))); /* Remove 1 */ assert(1 == (queueAdd(queue, &i3))); /* Insert 3 */ assert(2 == (*(int*)queueRemove(queue))); /* Remove 2 */ assert(1 == (queueAdd(queue, &i4))); /* Insert 4 */ assert(3 == (*(int*)queueRemove(queue))); /* Remove 3 */ assert(4 == (*(int*)queueRemove(queue))); /* Remove 4 */ /* Fill the queue */ assert(1 == (queueAdd(queue, &i1))); /* Insert 1 */ assert(1 == (queueAdd(queue, &i2))); /* Insert 2 */ assert(1 == (queueAdd(queue, &i3))); /* Insert 3 */ assert(1 == (queueAdd(queue, &i4))); /* Insert 4 */ /* Check the queue */ assert(1 == (*(int*)queueRemove(queue))); /* Remove 1 */ assert(2 == (*(int*)queueFirst(queue))); /* Check 2 */ assert(2 == (*(int*)queueRemove(queue))); /* Remove 2 */ assert(3 == (*(int*)queueRemove(queue))); /* Remove 3 */ assert(4 == (*(int*)queueRemove(queue))); /* Remove 4 */ assert(NULL == (queueFirst(queue))); /* Check empty */ assert(NULL == (queueRemove(queue))); /* Queue is empty */ /* Clear the queue */ queueFree(queue); printf("Queue: Test2 success!\n"); return 0; }