2021-07-13 21:02:53 +02:00
|
|
|
#include "fsfw/osal/linux/PeriodicPosixTask.h"
|
2021-06-05 19:52:38 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
#include <errno.h>
|
|
|
|
|
2021-07-13 21:02:53 +02:00
|
|
|
#include "fsfw/objectmanager/ObjectManager.h"
|
|
|
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
2021-06-05 19:52:38 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
|
|
|
uint32_t period_, void(deadlineMissedFunc_)())
|
|
|
|
: PosixThread(name_, priority_, stackSize_),
|
|
|
|
objectList(),
|
|
|
|
started(false),
|
|
|
|
periodMs(period_),
|
|
|
|
deadlineMissedFunc(deadlineMissedFunc_) {}
|
2018-07-13 18:28:26 +02:00
|
|
|
|
|
|
|
PeriodicPosixTask::~PeriodicPosixTask() {
|
2022-02-02 10:29:30 +01:00
|
|
|
// Not Implemented
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
2022-02-02 10:29:30 +01:00
|
|
|
// The argument is re-interpreted as PollingTask.
|
|
|
|
PeriodicPosixTask* originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
|
|
|
// The task's functionality is called.
|
|
|
|
originalTask->taskFunctionality();
|
|
|
|
return NULL;
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
2022-05-14 09:38:59 +02:00
|
|
|
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, uint8_t opCode) {
|
2022-02-02 10:29:30 +01:00
|
|
|
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
2022-05-14 09:38:59 +02:00
|
|
|
return addComponent(newObject, opCode);
|
2022-03-28 13:50:42 +02:00
|
|
|
}
|
|
|
|
|
2022-05-14 09:38:59 +02:00
|
|
|
ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object, uint8_t opCode) {
|
2022-03-28 13:50:42 +02:00
|
|
|
if (object == nullptr) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
|
|
|
<< " it implements ExecutableObjectIF!" << std::endl;
|
2021-06-03 12:29:06 +02:00
|
|
|
#else
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::printError(
|
|
|
|
"PeriodicTask::addComponent: Invalid object. Make sure it "
|
|
|
|
"implements ExecutableObjectIF!\n");
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
2022-05-14 09:38:59 +02:00
|
|
|
objectList.emplace(object, opCode);
|
2022-03-28 13:50:42 +02:00
|
|
|
object->setTaskIF(this);
|
2020-06-23 01:14:28 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return PosixThread::sleep((uint64_t)ms * 1000000);
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
2020-09-04 14:49:59 +02:00
|
|
|
ReturnValue_t PeriodicPosixTask::startTask(void) {
|
2022-05-14 09:38:59 +02:00
|
|
|
if (isEmpty()) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
started = true;
|
|
|
|
PosixThread::createTask(&taskEntryPoint, this);
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
2020-09-04 14:49:59 +02:00
|
|
|
void PeriodicPosixTask::taskFunctionality(void) {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (not started) {
|
|
|
|
suspend();
|
|
|
|
}
|
2020-09-04 14:43:53 +02:00
|
|
|
|
2022-05-14 09:38:59 +02:00
|
|
|
initObjsAfterTaskCreation();
|
2020-09-04 14:43:53 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
|
|
|
// The task's "infinite" inner loop is entered.
|
|
|
|
while (1) {
|
2022-05-14 09:38:59 +02:00
|
|
|
for (auto const& objOpCodePair : objectList) {
|
|
|
|
objOpCodePair.first->performOperation(objOpCodePair.second);
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2020-09-04 14:43:53 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) {
|
|
|
|
if (this->deadlineMissedFunc != nullptr) {
|
|
|
|
this->deadlineMissedFunc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
uint32_t PeriodicPosixTask::getPeriodMs() const { return periodMs; }
|
2022-05-14 09:38:59 +02:00
|
|
|
|
|
|
|
bool PeriodicPosixTask::isEmpty() const { return objectList.empty(); }
|
|
|
|
|
|
|
|
ReturnValue_t PeriodicPosixTask::initObjsAfterTaskCreation() {
|
|
|
|
std::multiset<ExecutableObjectIF*> uniqueObjects;
|
|
|
|
ReturnValue_t status = HasReturnvaluesIF::RETURN_OK;
|
|
|
|
uint32_t count = 0;
|
|
|
|
for (const auto& obj : objectList) {
|
|
|
|
// Ensure that each unique object is initialized once.
|
|
|
|
if (uniqueObjects.find(obj.first) == uniqueObjects.end()) {
|
|
|
|
ReturnValue_t result = obj.first->initializeAfterTaskCreation();
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
count++;
|
|
|
|
status = result;
|
|
|
|
}
|
|
|
|
uniqueObjects.emplace(obj.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (count > 0) {
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|