diff --git a/datapool/PoolDataSetBase.cpp b/datapool/PoolDataSetBase.cpp index 5fb1c3c7..05797012 100644 --- a/datapool/PoolDataSetBase.cpp +++ b/datapool/PoolDataSetBase.cpp @@ -38,11 +38,12 @@ ReturnValue_t PoolDataSetBase::registerVariable( return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t PoolDataSetBase::read(uint32_t lockTimeout) { +ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, + uint32_t lockTimeout) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t error = result; if (state == States::STATE_SET_UNINITIALISED) { - lockDataPool(lockTimeout); + lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { result = readVariable(count); if(result != RETURN_OK) { @@ -86,7 +87,8 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { != PoolVariableIF::NO_PARAMETER) { if(protectEveryReadCommitCall) { - result = registeredVariables[count]->read(mutexTimeout); + result = registeredVariables[count]->read( + MutexIF::TimeoutType::WAITING, mutexTimeout); } else { result = registeredVariables[count]->readWithoutLock(); @@ -99,25 +101,28 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { return result; } -ReturnValue_t PoolDataSetBase::commit(uint32_t lockTimeout) { +ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType, + uint32_t lockTimeout) { if (state == States::STATE_SET_WAS_READ) { - handleAlreadyReadDatasetCommit(lockTimeout); + handleAlreadyReadDatasetCommit(timeoutType, lockTimeout); return HasReturnvaluesIF::RETURN_OK; } else { - return handleUnreadDatasetCommit(lockTimeout); + return handleUnreadDatasetCommit(timeoutType, lockTimeout); } } -void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { - lockDataPool(lockTimeout); +void PoolDataSetBase::handleAlreadyReadDatasetCommit( + MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { + lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ && registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { if(protectEveryReadCommitCall) { - registeredVariables[count]->commit(mutexTimeout); + registeredVariables[count]->commit( + MutexIF::TimeoutType::WAITING, mutexTimeout); } else { registeredVariables[count]->commitWithoutLock(); @@ -128,16 +133,18 @@ void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { unlockDataPool(); } -ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { +ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit( + MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - lockDataPool(lockTimeout); + lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if (registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE && registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { if(protectEveryReadCommitCall) { - result = registeredVariables[count]->commit(mutexTimeout); + result = registeredVariables[count]->commit( + MutexIF::TimeoutType::WAITING, mutexTimeout); } else { result = registeredVariables[count]->commitWithoutLock(); @@ -160,7 +167,8 @@ ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { } -ReturnValue_t PoolDataSetBase::lockDataPool(uint32_t timeoutMs) { +ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType, + uint32_t lockTimeout) { return HasReturnvaluesIF::RETURN_OK; } diff --git a/datapool/PoolDataSetBase.h b/datapool/PoolDataSetBase.h index 7c1d84a4..0528f40f 100644 --- a/datapool/PoolDataSetBase.h +++ b/datapool/PoolDataSetBase.h @@ -62,8 +62,9 @@ public: * - @c SET_WAS_ALREADY_READ if read() is called twice without calling * commit() in between */ - virtual ReturnValue_t read(uint32_t lockTimeout = - MutexIF::BLOCKING) override; + virtual ReturnValue_t read( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t lockTimeout = 20) override; /** * @brief The commit call initializes writing back the registered variables. * @details @@ -82,8 +83,9 @@ public: * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - virtual ReturnValue_t commit(uint32_t lockTimeout = - MutexIF::BLOCKING) override; + virtual ReturnValue_t commit( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t lockTimeout = 20) override; /** * Register the passed pool variable instance into the data set. @@ -97,8 +99,9 @@ public: * thread-safety. Default implementation is empty * @return Always returns -@c RETURN_OK */ - virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = - MutexIF::BLOCKING) override; + virtual ReturnValue_t lockDataPool( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; /** * Provides the means to unlock the underlying data structure to ensure * thread-safety. Default implementation is empty @@ -160,8 +163,12 @@ private: uint32_t mutexTimeout = 20; ReturnValue_t readVariable(uint16_t count); - void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); - ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); + void handleAlreadyReadDatasetCommit( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); + ReturnValue_t handleUnreadDatasetCommit( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); }; #endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */ diff --git a/datapool/PoolDataSetIF.h b/datapool/PoolDataSetIF.h index 99c06cfd..1f52871d 100644 --- a/datapool/PoolDataSetIF.h +++ b/datapool/PoolDataSetIF.h @@ -18,7 +18,10 @@ public: * thread-safety * @return Lock operation result */ - virtual ReturnValue_t lockDataPool(dur_millis_t timeoutMs) = 0; + virtual ReturnValue_t lockDataPool( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) = 0; + /** * @brief Unlock call corresponding to the lock call. * @return Unlock operation result diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index 58375162..5f5f56f2 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -88,8 +88,10 @@ Type PoolEntry::getType() { template class PoolEntry; template class PoolEntry; template class PoolEntry; +template class PoolEntry; template class PoolEntry; template class PoolEntry; template class PoolEntry; +template class PoolEntry; template class PoolEntry; template class PoolEntry; diff --git a/datapool/ReadCommitIF.h b/datapool/ReadCommitIF.h index 0cdce371..efe51594 100644 --- a/datapool/ReadCommitIF.h +++ b/datapool/ReadCommitIF.h @@ -2,6 +2,7 @@ #define FSFW_DATAPOOL_READCOMMITIF_H_ #include +#include /** * @brief Common interface for all software objects which employ read-commit @@ -10,8 +11,10 @@ class ReadCommitIF { public: virtual ~ReadCommitIF() {} - virtual ReturnValue_t read(uint32_t mutexTimeout) = 0; - virtual ReturnValue_t commit(uint32_t mutexTimeout) = 0; + virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) = 0; + virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) = 0; protected: @@ -19,11 +22,11 @@ protected: //! members with commit and read semantics where the lock is only necessary //! once. virtual ReturnValue_t readWithoutLock() { - return read(20); + return read(MutexIF::TimeoutType::WAITING, 20); } virtual ReturnValue_t commitWithoutLock() { - return commit(20); + return commit(MutexIF::TimeoutType::WAITING, 20); } }; diff --git a/datapoollocal/LocalPoolDataSetBase.cpp b/datapoollocal/LocalPoolDataSetBase.cpp index dbe34dfd..af492146 100644 --- a/datapoollocal/LocalPoolDataSetBase.cpp +++ b/datapoollocal/LocalPoolDataSetBase.cpp @@ -1,4 +1,6 @@ #include "LocalPoolDataSetBase.h" + +#include "../serviceinterface/ServiceInterface.h" #include "../datapoollocal/LocalDataPoolManager.h" #include "../housekeeping/PeriodicHousekeepingHelper.h" #include "../serialize/SerializeAdapter.h" @@ -15,7 +17,10 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " << "invalid!" << std::endl; -#endif +#else + fsfw::printError("LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " + "invalid!\n\r"); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return; } hkManager = hkOwner->getHkManagerHandle(); @@ -44,13 +49,26 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, mutex = MutexFactory::instance()->createMutex(); } +LocalPoolDataSetBase::LocalPoolDataSetBase( + PoolVariableIF **registeredVariablesArray, + const size_t maxNumberOfVariables, bool protectFunctions): + PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { + if(protectFunctions) { + mutex = MutexFactory::instance()->createMutex(); + } + +} + + LocalPoolDataSetBase::~LocalPoolDataSetBase() { } -ReturnValue_t LocalPoolDataSetBase::lockDataPool(uint32_t timeoutMs) { +ReturnValue_t LocalPoolDataSetBase::lockDataPool( + MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { if(hkManager != nullptr) { - MutexIF* mutex = hkManager->getMutexHandle(); - return mutex->lockMutex(MutexIF::TimeoutType::WAITING, timeoutMs); + MutexIF* poolMutex = hkManager->getMutexHandle(); + return poolMutex->lockMutex(timeoutType, timeoutMs); } return HasReturnvaluesIF::RETURN_OK; } @@ -150,9 +168,12 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer, size, maxSize, streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization" - " error!" << std::endl; -#endif + sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: " + << "Serialization error!" << std::endl; +#else + fsfw::printWarning("LocalPoolDataSetBase::serializeLocalPoolIds: " + "Serialization error!\n\r"); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return result; } } @@ -211,8 +232,11 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const { if(position > 7) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "Pool Raw Access: Bit setting invalid position" + sif::warning << "LocalPoolDataSetBase::bitSetter: Invalid position!" << std::endl; +#else + fsfw::printWarning("LocalPoolDataSetBase::bitSetter: " + "Invalid position!\n\r"); #endif return; } @@ -244,14 +268,19 @@ void LocalPoolDataSetBase::initializePeriodicHelper( } void LocalPoolDataSetBase::setChanged(bool changed) { - // TODO: Make this configurable? - MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); + if(mutex == nullptr) { + this->changed = changed; + return; + } + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeout); this->changed = changed; } bool LocalPoolDataSetBase::hasChanged() const { - // TODO: Make this configurable? - MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); + if(mutex == nullptr) { + return changed; + } + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeout); return changed; } @@ -273,18 +302,22 @@ bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, } bool LocalPoolDataSetBase::isValid() const { + if(mutex == nullptr) { + return this->valid; + } MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); return this->valid; } void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) { - MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); + mutex->lockMutex(timeoutType, mutexTimeout); if(setEntriesRecursively) { for(size_t idx = 0; idx < this->getFillCount(); idx++) { registeredVariables[idx] -> setValid(valid); } } this->valid = valid; + mutex->unlockMutex(); } void LocalPoolDataSetBase::setReadCommitProtectionBehaviour( @@ -292,3 +325,9 @@ void LocalPoolDataSetBase::setReadCommitProtectionBehaviour( PoolDataSetBase::setReadCommitProtectionBehaviour(protectEveryReadCommit, mutexTimeout); } + +void LocalPoolDataSetBase::setDataSetMutexTimeout( + MutexIF::TimeoutType timeoutType, uint32_t mutexTimeout) { + this->timeoutType = timeoutType; + this->mutexTimeout = mutexTimeout; +} diff --git a/datapoollocal/LocalPoolDataSetBase.h b/datapoollocal/LocalPoolDataSetBase.h index d9b6a221..b44f607f 100644 --- a/datapoollocal/LocalPoolDataSetBase.h +++ b/datapoollocal/LocalPoolDataSetBase.h @@ -67,6 +67,15 @@ public: LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray, const size_t maxNumberOfVariables); + /** + * Simple constructor, if the dataset is not owner permanently by + * a class with a HK manager. + * @param registeredVariablesArray + * @param maxNumberOfVariables + */ + LocalPoolDataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables, bool protectFunctions = true); + /** * @brief The destructor automatically manages writing the valid * information of variables. @@ -87,6 +96,9 @@ public: void setReadCommitProtectionBehaviour(bool protectEveryReadCommit, uint32_t mutexTimeout = 20); + void setDataSetMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t mutexTimeout); + void setValidityBufferGeneration(bool withValidityBuffer); sid_t getSid() const; @@ -138,7 +150,12 @@ public: protected: sid_t sid; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t mutexTimeout = 20; + /** + * This mutex is required because the dataset can potentially be accessed + * by multiple threads for information like change status or validity. + */ MutexIF* mutex = nullptr; bool diagnostic = false; @@ -183,7 +200,9 @@ protected: * @details * It makes use of the lockDataPool method offered by the DataPool class. */ - ReturnValue_t lockDataPool(uint32_t timeoutMs) override; + ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) override; + /** * @brief This is a small helper function to facilitate * unlocking the global data pool diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h index 21ee2764..c81967a1 100644 --- a/datapoollocal/LocalPoolVariable.h +++ b/datapoollocal/LocalPoolVariable.h @@ -106,7 +106,9 @@ public: * at once to avoid the overhead of unnecessary lock und unlock operations. * */ - ReturnValue_t read(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t read(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; /** * @brief The commit call copies the array values back to the data pool. * @details @@ -116,8 +118,21 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; + /** + * @brief This commit function can be used to set the pool variable valid + * as well. + * @param setValid + * @param timeoutType + * @param timeoutMs + * @return + */ + ReturnValue_t commit(bool setValid, MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); LocalPoolVariable &operator=(const T& newValue); LocalPoolVariable &operator=(const LocalPoolVariable& newPoolVariable); diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index f70e4e91..9387acc5 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -24,9 +24,9 @@ inline LocalPoolVariable::LocalPoolVariable(gp_id_t globalPoolId, template -inline ReturnValue_t LocalPoolVariable::read(dur_millis_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); +inline ReturnValue_t LocalPoolVariable::read( + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return readWithoutLock(); } @@ -64,9 +64,16 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { } template -inline ReturnValue_t LocalPoolVariable::commit(dur_millis_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); +inline ReturnValue_t LocalPoolVariable::commit(bool setValid, + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + this->setValid(setValid); + return commit(timeoutType, timeoutMs); +} + +template +inline ReturnValue_t LocalPoolVariable::commit( + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return commitWithoutLock(); } diff --git a/datapoollocal/LocalPoolVector.h b/datapoollocal/LocalPoolVector.h index 58face3c..773a52cc 100644 --- a/datapoollocal/LocalPoolVector.h +++ b/datapoollocal/LocalPoolVector.h @@ -7,7 +7,7 @@ #include "../datapool/PoolVariableIF.h" #include "../datapoollocal/LocalDataPoolManager.h" #include "../serialize/SerializeAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterface.h" /** @@ -123,7 +123,9 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t read(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; /** * @brief The commit call copies the array values back to the data pool. * @details @@ -133,7 +135,9 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; protected: /** @@ -157,12 +161,12 @@ protected: private: - +#if FSFW_CPP_OSTREAM_ENABLED == 1 // std::ostream is the type for object std::cout template friend std::ostream& operator<< (std::ostream &out, const LocalPoolVector &var); - +#endif }; diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index a010a8bb..6af80de6 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -24,9 +24,9 @@ inline LocalPoolVector::LocalPoolVector(gp_id_t globalPoolId, dataSet, setReadWriteMode) {} template -inline ReturnValue_t LocalPoolVector::read(uint32_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); +inline ReturnValue_t LocalPoolVector::read( + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return readWithoutLock(); } template @@ -59,9 +59,8 @@ inline ReturnValue_t LocalPoolVector::readWithoutLock() { template inline ReturnValue_t LocalPoolVector::commit( - uint32_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return commitWithoutLock(); } @@ -153,6 +152,7 @@ inline ReturnValue_t LocalPoolVector::deSerialize( return result; } +#if FSFW_CPP_OSTREAM_ENABLED == 1 template inline std::ostream& operator<< (std::ostream &out, const LocalPoolVector &var) { @@ -166,5 +166,6 @@ inline std::ostream& operator<< (std::ostream &out, out << "]"; return out; } +#endif #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ */ diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 1af6932a..580f8c0d 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -229,7 +229,8 @@ ReturnValue_t DeviceHandlerBase::initialize() { if(result == HasReturnvaluesIF::RETURN_OK) { thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; - thermalSet->commit(PoolVariableIF::VALID); + thermalSet->heaterRequest.setValid(true); + thermalSet->commit(); } } diff --git a/events/EventManager.cpp b/events/EventManager.cpp index 65e19d10..e25e574f 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -162,9 +162,15 @@ void EventManager::printEvent(EventMessage* message) { #endif void EventManager::lockMutex() { - mutex->lockMutex(MutexIF::BLOCKING); + mutex->lockMutex(timeoutType, timeoutMs); } void EventManager::unlockMutex() { mutex->unlockMutex(); } + +void EventManager::setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->timeoutType = timeoutType; + this->timeoutMs = timeoutMs; +} diff --git a/events/EventManager.h b/events/EventManager.h index c6bd07be..abce9b8b 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -29,6 +29,8 @@ public: EventManager(object_id_t setObjectId); virtual ~EventManager(); + void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); + MessageQueueId_t getEventReportQueue(); ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false); @@ -51,6 +53,8 @@ protected: std::map listenerList; MutexIF* mutex = nullptr; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 20; static const uint8_t N_POOLS = 3; LocalPool factoryBackend; diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 48b6f851..6842da8e 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -23,7 +23,7 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) { } ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { - internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT); + internalErrorDataset.read(timeoutType, timeoutMs); uint32_t newQueueHits = getAndResetQueueHits(); uint32_t newTmHits = getAndResetTmHits(); @@ -46,8 +46,8 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { internalErrorDataset.queueHits.value += newQueueHits; internalErrorDataset.storeHits.value += newStoreHits; internalErrorDataset.tmHits.value += newTmHits; - - internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT); + internalErrorDataset.setValidity(true, true); + internalErrorDataset.commit(timeoutType, timeoutMs); poolManager.performHkOperation(); @@ -69,7 +69,7 @@ void InternalErrorReporter::lostTm() { uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = queueHits; queueHits = 0; mutex->unlockMutex(); @@ -78,21 +78,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t InternalErrorReporter::getQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = queueHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementQueueHits() { - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); queueHits++; mutex->unlockMutex(); } uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = tmHits; tmHits = 0; mutex->unlockMutex(); @@ -101,14 +101,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t InternalErrorReporter::getTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = tmHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementTmHits() { - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); tmHits++; mutex->unlockMutex(); } @@ -119,7 +119,7 @@ void InternalErrorReporter::storeFull() { uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = storeHits; storeHits = 0; mutex->unlockMutex(); @@ -128,14 +128,14 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t InternalErrorReporter::getStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = storeHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementStoreHits() { - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); storeHits++; mutex->unlockMutex(); } @@ -190,3 +190,8 @@ ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() { return poolManager.initializeAfterTaskCreation(); } +void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->timeoutType = timeoutType; + this->timeoutMs = timeoutMs; +} diff --git a/internalError/InternalErrorReporter.h b/internalError/InternalErrorReporter.h index 8d33c06e..c85057d6 100644 --- a/internalError/InternalErrorReporter.h +++ b/internalError/InternalErrorReporter.h @@ -22,7 +22,6 @@ class InternalErrorReporter: public SystemObject, public InternalErrorReporterIF, public HasLocalDataPoolIF { public: - static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20; InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5); @@ -34,6 +33,9 @@ public: */ void setDiagnosticPrintout(bool enable); + void setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs); + virtual ~InternalErrorReporter(); virtual object_id_t getObjectId() const override; @@ -61,7 +63,11 @@ protected: LocalDataPoolManager poolManager; PeriodicTaskIF* executingTask = nullptr; + MutexIF* mutex = nullptr; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 20; + sid_t internalErrorSid; InternalErrorDataset internalErrorDataset; diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index 5673e4d7..084b702b 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -14,7 +14,7 @@ public: /** * Different types of timeout for the mutex lock. */ - enum TimeoutType { + enum class TimeoutType { POLLING, //!< If mutex is not available, return immediately WAITING, //!< Wait a specified time for the mutex to become available BLOCKING //!< Block indefinitely until the mutex becomes available. diff --git a/osal/host/Clock.cpp b/osal/host/Clock.cpp index 2bc78785..88bf51d2 100644 --- a/osal/host/Clock.cpp +++ b/osal/host/Clock.cpp @@ -202,7 +202,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -217,7 +217,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if(timeMutex == nullptr){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/osal/host/Mutex.cpp b/osal/host/Mutex.cpp index ad8873df..892028b2 100644 --- a/osal/host/Mutex.cpp +++ b/osal/host/Mutex.cpp @@ -4,16 +4,16 @@ Mutex::Mutex() {} ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { - if(timeoutType == MutexIF::BLOCKING) { + if(timeoutType == TimeoutType::BLOCKING) { mutex.lock(); return HasReturnvaluesIF::RETURN_OK; } - else if(timeoutType == MutexIF::POLLING) { + else if(timeoutType == TimeoutType::POLLING) { if(mutex.try_lock()) { return HasReturnvaluesIF::RETURN_OK; } } - else if(timeoutMs > MutexIF::POLLING){ + else if(timeoutType == TimeoutType::WAITING){ auto chronoMs = std::chrono::milliseconds(timeoutMs); if(mutex.try_lock_for(chronoMs)) { return HasReturnvaluesIF::RETURN_OK; diff --git a/power/Fuse.cpp b/power/Fuse.cpp index 1c30d83f..b6e0a7f1 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -65,8 +65,8 @@ ReturnValue_t Fuse::check() { set.read(); if (!healthHelper.healthTable->isHealthy(getObjectId())) { setAllMonitorsToUnchecked(); - set.commit(PoolVariableIF::INVALID); - return RETURN_OK; + set.setValidity(false, true); + return set.commit(); } ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; checkFuseState(); @@ -206,7 +206,8 @@ float Fuse::getPower() { void Fuse::setDataPoolEntriesInvalid() { set.read(); - set.commit(PoolVariableIF::INVALID); + set.setValidity(false, true); + set.commit(); } ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId, diff --git a/power/PowerSensor.cpp b/power/PowerSensor.cpp index 1ef041e3..fb181d9f 100644 --- a/power/PowerSensor.cpp +++ b/power/PowerSensor.cpp @@ -97,7 +97,8 @@ void PowerSensor::checkCommandQueue() { void PowerSensor::setDataPoolEntriesInvalid() { powerSensorSet.read(); - powerSensorSet.commit(PoolVariableIF::INVALID); + powerSensorSet.setValidity(false, true); + powerSensorSet.commit(); } float PowerSensor::getPower() { diff --git a/unittest/internal/osal/IntTestMutex.cpp b/unittest/internal/osal/IntTestMutex.cpp index 3316de74..2a1584b8 100644 --- a/unittest/internal/osal/IntTestMutex.cpp +++ b/unittest/internal/osal/IntTestMutex.cpp @@ -13,7 +13,7 @@ void testmutex::testMutex() { std::string id = "[testMutex]"; MutexIF* mutex = MutexFactory::instance()->createMutex(); - auto result = mutex->lockMutex(MutexIF::POLLING); + auto result = mutex->lockMutex(MutexIF::TimeoutType::POLLING); if(result != HasReturnvaluesIF::RETURN_OK) { unitt::put_error(id); } diff --git a/unittest/tests/datapoollocal/DataSetTest.cpp b/unittest/tests/datapoollocal/DataSetTest.cpp new file mode 100644 index 00000000..ccb7603d --- /dev/null +++ b/unittest/tests/datapoollocal/DataSetTest.cpp @@ -0,0 +1,21 @@ +#include "LocalPoolOwnerBase.h" + +#include +#include +#include + +TEST_CASE("LocalDataSet" , "[LocDataSetTest]") { + LocalPoolOwnerBase* poolOwner = objectManager-> + get(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner != nullptr); + REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() + == retval::CATCH_OK); + + SECTION("BasicTest") { + //StaticLocalDataSet<3> localSet = StaticLocalDataSet<3>() + } +} + + + diff --git a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h index 40f657be..c665cb7f 100644 --- a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h +++ b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,9 +12,12 @@ namespace lpool { static constexpr lp_id_t uint8VarId = 0; static constexpr lp_id_t floatVarId = 1; static constexpr lp_id_t uint32VarId = 2; +static constexpr lp_id_t uint16Vec3Id = 3; +static constexpr lp_id_t int64Vec2Id = 4; } + class LocalPoolOwnerBase: public SystemObject, public HasLocalDataPoolIF { public: LocalPoolOwnerBase( @@ -31,12 +35,19 @@ public: } ReturnValue_t initializeHkManager() { - return hkManager.initialize(messageQueue); - + if(not initialized) { + initialized = true; + return hkManager.initialize(messageQueue); + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t initializeHkManagerAfterTaskCreation() { - return hkManager.initializeAfterTaskCreation(); + if(not initializedAfterTaskCreation) { + initializedAfterTaskCreation = true; + return hkManager.initializeAfterTaskCreation(); + } + return HasReturnvaluesIF::RETURN_OK; } /** Command queue for housekeeping messages. */ @@ -44,12 +55,22 @@ public: return messageQueue->getId(); } + // This is called by initializeAfterTaskCreation of the HK manager. virtual ReturnValue_t initializeLocalDataPool( LocalDataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { // Default initialization empty for now. - localDataPoolMap.emplace(lpool::uint8VarId, new PoolEntry({0})); - localDataPoolMap.emplace(lpool::floatVarId, new PoolEntry({0})); + localDataPoolMap.emplace(lpool::uint8VarId, + new PoolEntry({0})); + localDataPoolMap.emplace(lpool::floatVarId, + new PoolEntry({0})); + localDataPoolMap.emplace(lpool::uint32VarId, + new PoolEntry({0})); + + localDataPoolMap.emplace(lpool::uint16Vec3Id, + new PoolEntry({0, 0, 0})); + localDataPoolMap.emplace(lpool::int64Vec2Id, + new PoolEntry({0, 0})); return HasReturnvaluesIF::RETURN_OK; } @@ -77,9 +98,17 @@ private: lp_var_t testFloat = lp_var_t(this, lpool::floatVarId); lp_var_t testUint32 = lp_var_t(this, lpool::uint32VarId); + lp_vec_t testUint16Vec = lp_vec_t(this, + lpool::uint16Vec3Id); + lp_vec_t testInt64Vec = lp_vec_t(this, + lpool::int64Vec2Id); + MessageQueueIF* messageQueue = nullptr; LocalDataPoolManager hkManager; + bool initialized = false; + bool initializedAfterTaskCreation = false; + }; #endif /* FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ */ diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index cf4f4b6b..eb5abf35 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -6,9 +6,11 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { - LocalPoolOwnerBase poolOwner(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner.initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() + LocalPoolOwnerBase* poolOwner = objectManager-> + get(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner != nullptr); + REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); SECTION("Basic Tests") { @@ -26,6 +28,18 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { testVariable.setValid(true); CHECK(testVariable.isValid()); + testVariable.setReadWriteMode(pool_rwm_t::VAR_READ); + CHECK(testVariable.getReadWriteMode() == pool_rwm_t::VAR_READ); + testVariable.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE); + + testVariable.setDataPoolId(22); + CHECK(testVariable.getDataPoolId() == 22); + testVariable.setDataPoolId(lpool::uint8VarId); + + testVariable.setChanged(true); + CHECK(testVariable.hasChanged()); + testVariable.setChanged(false); + gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); lp_var_t testVariable2 = lp_var_t(globPoolId); @@ -93,6 +107,15 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "LocalPoolVariable printout: " < OK + lp_var_t invalidObjectVar = lp_var_t( + 0xffffffff, lpool::uint8VarId); + gp_id_t globPoolId(0xffffffff, + lpool::uint8VarId); + lp_var_t invalidObjectVar2 = lp_var_t(globPoolId); + lp_var_t invalidObjectVar3 = lp_var_t(nullptr, + lpool::uint8VarId); } } diff --git a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp new file mode 100644 index 00000000..c86a2681 --- /dev/null +++ b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp @@ -0,0 +1,16 @@ +#include "LocalPoolOwnerBase.h" + +#include +#include +#include + +TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { + LocalPoolOwnerBase* poolOwner = objectManager-> + get(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner != nullptr); + REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() + == retval::CATCH_OK); +} + +