32using namespace std::chrono;
38TaskScheduler::EventQueue TaskScheduler::makeAgenda()
40 std::vector<Event> agendaStorage{};
42 return EventQueue{std::greater<Event>{}, std::move(agendaStorage)};
46 :
ActiveObject(STACK_MIN_FOR_SKYWARD, priority), tasks(),
58 Policy policy, time_point<steady_clock> startTime)
60 std::unique_lock<miosix::FastMutex> lock{mutex};
66 LOG_ERR(logger,
"Full task scheduler");
74 tasks.emplace_back(function,
period.count(), policy,
75 startTime.time_since_epoch().count());
76 size_t id = tasks.size() - 1;
81 agenda.emplace(
id, startTime.time_since_epoch().count());
89 std::unique_lock<miosix::FastMutex> lock{mutex};
91 if (
id > tasks.size() - 1)
94 LOG_ERR(logger,
"Tried to enable an out-of-range task, id = {}",
id);
98 Task& task = tasks[id];
106 LOG_WARN(logger,
"Tried to enable an empty task, id = {}",
id);
111 agenda.emplace(
id, miosix::getTime() + task.period);
116 std::unique_lock<miosix::FastMutex> lock{mutex};
118 if (
id > tasks.size() - 1)
121 LOG_ERR(logger,
"Tried to disable an out-of-range task, id = {}",
id);
125 Task& task = tasks[id];
126 task.enabled =
false;
133 Lock<FastMutex> lock(mutex);
156 Lock<FastMutex> lock(mutex);
158 vector<TaskStatsResult> result;
160 for (
size_t id = 1;
id < tasks.size();
id++)
162 const Task& task = tasks[id];
164 result.push_back(fromTaskIdPairToStatsResult(task,
id));
170void TaskScheduler::populateAgenda()
172 int64_t currentTime = miosix::getTime();
174 for (
size_t id = 1;
id < tasks.size();
id++)
176 Task& task = tasks[id];
177 int64_t startTime = task.startTime;
181 if (startTime < currentTime)
183 int64_t timeSinceStart = currentTime - startTime;
184 int64_t periodsMissed = timeSinceStart / task.period;
185 int64_t periodsToSkip = periodsMissed + 1;
186 startTime += periodsToSkip * task.period;
189 agenda.emplace(
id, startTime);
193void TaskScheduler::run()
195 Lock<FastMutex> lock(mutex);
206 int64_t startTime = miosix::getTime();
207 Event nextEvent = agenda.top();
209 if (nextEvent.nextTime <= startTime)
211 Task& nextTask = tasks[nextEvent.taskId];
215 if (nextTask.enabled)
218 Unlock<FastMutex> unlock(lock);
227 nextTask.failedEvents++;
232 updateStats(nextEvent, startTime, miosix::getTime());
233 enqueue(nextEvent, startTime);
238 Unlock<FastMutex> unlock(lock);
240 Thread::nanoSleepUntil(nextEvent.nextTime);
245void TaskScheduler::updateStats(
const Event& event, int64_t startTime,
248 Task& task = tasks[
event.taskId];
250 float activationTime = startTime -
event.nextTime;
253 int64_t lastCall = task.lastCall;
256 float periodTime = startTime - lastCall;
261 task.lastCall = startTime;
263 float workloadTime = endTime - startTime;
267void TaskScheduler::enqueue(
Event event, int64_t startTime)
269 Task& task = tasks[
event.taskId];
275 task.enabled =
false;
280 int64_t timeSinceLastExec = startTime -
event.nextTime;
281 int64_t periodsMissed = timeSinceLastExec / task.period;
287 int64_t periodsToSkip = periodsMissed + 1;
290 event.nextTime += periodsToSkip * task.period;
293 task.missedEvents +=
static_cast<uint32_t
>(periodsMissed);
297 event.nextTime += task.period;
306TaskScheduler::Task::Task()
307 : function(nullptr),
period(0), startTime(0), enabled(false),
308 policy(Policy::SKIP), lastCall(-1), activationStats(), periodStats(),
309 workloadStats(), missedEvents(0), failedEvents(0)
313TaskScheduler::Task::Task(function_t function, int64_t period, Policy policy,
315 : function(function),
period(
period), startTime(startTime), enabled(true),
316 policy(policy), lastCall(-1), activationStats(), periodStats(),
317 workloadStats(), missedEvents(0), failedEvents(0)
#define LOG_WARN(logger,...)
#define LOG_ERR(logger,...)
std::atomic< bool > stopFlag
std::atomic< bool > running
bool shouldStop()
Tells whether or not the ActiveObject should stop its execution.
virtual void stop()
Signals the runner thread to terminate and joins the thread.
virtual bool start()
Start the thread associated with this active object.
std::vector< TaskStatsResult > getTaskStats()
void enableTask(size_t id)
Enables the task with the given id.
bool start() override
Start the thread associated with this active object.
void disableTask(size_t id)
Disables the task with the given id, preventing it from executing.
@ ONE_SHOT
Run the task one single timer.
@ RECOVER
Prioritize the number of executions over the period.
void stop() override
Signals the runner thread to terminate and joins the thread.
size_t addTask(function_t function, uint32_t periodMs, Policy policy=Policy::RECOVER, int64_t startTick=Kernel::getOldTick())
Add a millisecond-period task function to the scheduler with an auto generated ID.
TaskScheduler(miosix::Priority priority=miosix::PRIORITY_MAX - 1)
static constexpr size_t MAX_TASKS
The maximum number of tasks the scheduler can handle.
constexpr long long NS_IN_MS
This file includes all the types the logdecoder script will decode.