Skip to content
Snippets Groups Projects
Commit 60213865 authored by Matteo Pignataro's avatar Matteo Pignataro Committed by Niccolò Betto
Browse files

[TaskScheduler][TO BE TESTED] Added makeTask method and removed pointer array...

[TaskScheduler][TO BE TESTED] Added makeTask method and removed pointer array and dynamic allocation.
parent efee8832
No related branches found
No related tags found
1 merge request!91[TaskScheduler] Improved task scheduler efficiency and minor bugs fix
...@@ -35,40 +35,36 @@ namespace Boardcore ...@@ -35,40 +35,36 @@ namespace Boardcore
TaskScheduler::TaskScheduler() TaskScheduler::TaskScheduler()
: ActiveObject(STACK_MIN_FOR_SKYWARD, miosix::PRIORITY_MAX - 1) : ActiveObject(STACK_MIN_FOR_SKYWARD, miosix::PRIORITY_MAX - 1)
{ {
stopFlag = false; stopFlag = false;
running = false; running = false;
possibleFreeID = 1;
} }
uint8_t TaskScheduler::addTask(function_t function, uint32_t period, size_t TaskScheduler::addTask(function_t function, uint32_t period,
Policy policy, int64_t startTick) Policy policy, int64_t startTick)
{ {
Lock<FastMutex> lock(mutex); Lock<FastMutex> lock(mutex);
uint8_t id = possibleFreeID; size_t id = 1;
// Find a suitable id for the new task // Find a suitable id for the new task
for (; id < 255 && tasks[id] != nullptr; ++id) for (; id < TASKS_SIZE && tasks[id].valid == false; id++)
; ;
possibleFreeID = id + 1;
// Check if in the corresponding id there's already a task // Check if in the corresponding id there's already a task
if (tasks[id] != nullptr) if (tasks[id].valid)
{ {
LOG_ERR(logger, "Full task scheduler, id = 255"); LOG_ERR(logger, "Full task scheduler, id = {:zu}", id);
return 0; return 0;
} }
// Register the task into the map // Register the task into the map
Task* task = tasks[id] = makeTask(function, period, id, true, policy);
new Task{function, period, id, true, policy, -1, {}, {}, {}, 0, 0};
tasks[id] = task;
if (policy == Policy::ONE_SHOT) if (policy == Policy::ONE_SHOT)
startTick += period; startTick += period;
// Add the task first event in the agenda // Add the task first event in the agenda
Event event = {task, startTick}; Event event = {&(tasks[id]), startTick};
agenda.push(event); agenda.push(event);
condvar.broadcast(); // Signals the run thread condvar.broadcast(); // Signals the run thread
...@@ -80,21 +76,14 @@ bool TaskScheduler::removeTask(uint8_t id) ...@@ -80,21 +76,14 @@ bool TaskScheduler::removeTask(uint8_t id)
Lock<FastMutex> lock(mutex); Lock<FastMutex> lock(mutex);
// Check if the task is actually present // Check if the task is actually present
if (tasks[id] == nullptr) if (tasks[id].valid == false)
{ {
LOG_ERR(logger, "Attempting to remove a task not registered"); LOG_ERR(logger, "Attempting to remove a task not registered");
return false; return false;
} }
// Set the validity of the task to false // Set the validity of the task to false
tasks[id]->valid = false; tasks[id].valid = false;
// Remove the task from the tasks array
// We do not deallocate the task here because of future deallocation when
// popped from queue
tasks[id] = nullptr;
if (id < possibleFreeID)
possibleFreeID = id;
return true; return true;
} }
...@@ -128,7 +117,7 @@ vector<TaskStatsResult> TaskScheduler::getTaskStats() ...@@ -128,7 +117,7 @@ vector<TaskStatsResult> TaskScheduler::getTaskStats()
for (auto& task : tasks) for (auto& task : tasks)
{ {
if (task != nullptr) if (task.valid)
result.push_back(fromTaskIdPairToStatsResult(task)); result.push_back(fromTaskIdPairToStatsResult(task));
} }
...@@ -206,7 +195,6 @@ void TaskScheduler::run() ...@@ -206,7 +195,6 @@ void TaskScheduler::run()
{ {
if (!nextEvent.task->valid) if (!nextEvent.task->valid)
{ {
delete nextEvent.task;
agenda.pop(); agenda.pop();
} }
...@@ -248,9 +236,7 @@ void TaskScheduler::enqueue(Event& event, int64_t startTick) ...@@ -248,9 +236,7 @@ void TaskScheduler::enqueue(Event& event, int64_t startTick)
case Policy::ONE_SHOT: case Policy::ONE_SHOT:
// If the task is one shot we won't push it to the agenda and we'll // If the task is one shot we won't push it to the agenda and we'll
// remove it from the tasks map. // remove it from the tasks map.
tasks[event.task->id] = nullptr; tasks[event.task->id].valid = false;
if (event.task->id < possibleFreeID)
possibleFreeID = event.task->id;
delete event.task; delete event.task;
return; return;
...@@ -280,4 +266,11 @@ void TaskScheduler::enqueue(Event& event, int64_t startTick) ...@@ -280,4 +266,11 @@ void TaskScheduler::enqueue(Event& event, int64_t startTick)
condvar.broadcast(); condvar.broadcast();
} }
TaskScheduler::Task TaskScheduler::makeTask(function_t function,
uint32_t period, size_t id,
bool validity, Policy policy)
{
return Task{function, period, id, validity, policy, -1, {}, {}, {}, 0, 0};
}
} // namespace Boardcore } // namespace Boardcore
...@@ -61,6 +61,11 @@ class TaskScheduler : public ActiveObject ...@@ -61,6 +61,11 @@ class TaskScheduler : public ActiveObject
public: public:
typedef std::function<void()> function_t; typedef std::function<void()> function_t;
/**
* @brief It defines the tasks array maximum size
*/
static constexpr size_t TASKS_SIZE = 256;
/** /**
* @brief Task behavior policy. * @brief Task behavior policy.
* *
...@@ -107,9 +112,9 @@ public: ...@@ -107,9 +112,9 @@ public:
* @param startTick First activation time, useful for synchronizing tasks. * @param startTick First activation time, useful for synchronizing tasks.
* @return true if the task was added successfully. * @return true if the task was added successfully.
*/ */
uint8_t addTask(function_t function, uint32_t period, size_t addTask(function_t function, uint32_t period,
Policy policy = Policy::SKIP, Policy policy = Policy::SKIP,
int64_t startTick = miosix::getTick()); int64_t startTick = miosix::getTick());
/** /**
* @brief Removes the task identified by the given id if it exists. * @brief Removes the task identified by the given id if it exists.
...@@ -136,7 +141,7 @@ private: ...@@ -136,7 +141,7 @@ private:
{ {
function_t function; function_t function;
uint32_t period; uint32_t period;
uint8_t id; size_t id;
bool valid; bool valid;
Policy policy; Policy policy;
int64_t lastCall; ///< Last activation tick for statistics computation. int64_t lastCall; ///< Last activation tick for statistics computation.
...@@ -186,23 +191,35 @@ private: ...@@ -186,23 +191,35 @@ private:
*/ */
void enqueue(Event& event, int64_t startTick); void enqueue(Event& event, int64_t startTick);
static TaskStatsResult fromTaskIdPairToStatsResult(Task* task) /**
* @brief Creates a task with the passed values
*
* @param function The std::function to be called
* @param period The Period in [ms]
* @param id The task intrinsic id
* @param validity The validity of the task (false if not initialized or if
* removed)
* @param policy The task policy in case of a miss
*/
Task makeTask(function_t function, uint32_t period, size_t id,
bool validity, Policy policy);
static TaskStatsResult fromTaskIdPairToStatsResult(Task task)
{ {
return TaskStatsResult{task->id, return TaskStatsResult{task.id,
task->period, task.period,
task->activationStats.getStats(), task.activationStats.getStats(),
task->periodStats.getStats(), task.periodStats.getStats(),
task->workloadStats.getStats(), task.workloadStats.getStats(),
task->missedEvents, task.missedEvents,
task->failedEvents}; task.failedEvents};
} }
miosix::FastMutex mutex; ///< Mutex to protect tasks and agenda. miosix::FastMutex mutex; ///< Mutex to protect tasks and agenda.
std::array<Task*, 256> tasks{}; ///< Holds all tasks to be scheduled. std::array<Task, TASKS_SIZE> tasks{}; ///< Holds all tasks to be scheduled.
miosix::ConditionVariable condvar; ///< Used when agenda is empty. miosix::ConditionVariable condvar; ///< Used when agenda is empty.
std::priority_queue<Event> agenda; ///< Ordered list of functions. std::priority_queue<Event> agenda; ///< Ordered list of functions.
uint8_t possibleFreeID;
PrintLogger logger = Logging::getLogger("taskscheduler"); PrintLogger logger = Logging::getLogger("taskscheduler");
}; };
......
...@@ -43,7 +43,7 @@ namespace Boardcore ...@@ -43,7 +43,7 @@ namespace Boardcore
*/ */
struct TaskStatsResult struct TaskStatsResult
{ {
uint8_t id; size_t id;
uint32_t period; uint32_t period;
StatsResult activationStats; StatsResult activationStats;
StatsResult periodStats; StatsResult periodStats;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment