diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/common/TimeSortingBuffer.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/common/TimeSortingBuffer.hpp index 24f6f36868..077218388e 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/common/TimeSortingBuffer.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/common/TimeSortingBuffer.hpp @@ -13,6 +13,7 @@ #ifndef TIMESORTINGBUFFER_HPP_INCLUDED #define TIMESORTINGBUFFER_HPP_INCLUDED +#include #include #include @@ -67,9 +68,7 @@ class TimeSortingBuffer /// @return Success of push (true) sufficient space in buffer was available /* RULECHECKER_comment(0, 3, check_cheap_to_copy_in_parameter, "For template argument f_element_r, it is not \ possible to classify cheap_to_copy or expensive_to_copy without referring original object.", true_no_defect) */ - bool push( - const TimeSortedElementType& f_element_r, - const score::mw::lifecycle::internal::saf::timers::NanoSecondType f_timestamp) + bool push(const TimeSortedElementType& f_element_r, const std::chrono::nanoseconds f_timestamp) { bool isSuccess{false}; SortChainElement newElement{nullptr, nullptr, f_element_r, f_timestamp}; @@ -134,8 +133,7 @@ class TimeSortingBuffer nullptr}; // Pointer to previous element, null pointer means first element (oldest) SortChainElement* next_p{nullptr}; // Pointer to next element, null pointer means last element (latest) TimeSortedElementType element{}; // Element to be sorted - score::mw::lifecycle::internal::saf::timers::NanoSecondType timestamp{ - 0U}; // Timestamp used for sorting the elements + std::chrono::nanoseconds timestamp{0U}; // Timestamp used for sorting the elements }; /// Sort elements diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp index 28139c54c8..5c8a572ec0 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp @@ -36,12 +36,12 @@ PhmDaemon::PhmDaemon(OsClock& f_osClock, std::size_t supervised_components) void PhmDaemon::performCyclicTriggers(void) { - NanoSecondType syncTimestamp{timers::OsClock::getMonotonicSystemClock()}; - if (syncTimestamp == 0U) + std::chrono::nanoseconds syncTimestamp{timers::OsClock::getMonotonicSystemClock()}; + if (syncTimestamp.count() == 0U) { // No valid time value, use max value for synchronization // All received data will be considered. - syncTimestamp = UINT64_MAX; + syncTimestamp = std::chrono::nanoseconds::max(); } if (supervisionStateReader_.distributeChanges(syncTimestamp)) diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp index b3b86e2a7e..7fa38512a5 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp @@ -42,7 +42,6 @@ class PhmDaemon final : public ISupervisionFactory using RecoveryClient = score::mw::lifecycle::IRecoveryClient; using CycleTimer = score::mw::lifecycle::internal::saf::timers::CycleTimer; using CycleTimeValidator = score::mw::lifecycle::internal::saf::timers::CycleTimeValidator; - using NanoSecondType = score::mw::lifecycle::internal::saf::timers::NanoSecondType; using ObservableEventReader = score::mw::lifecycle::internal::saf::ifexm::ObservableEventReader; using Config = score::mw::lifecycle::internal::configuration::Config; @@ -77,18 +76,17 @@ class PhmDaemon final : public ISupervisionFactory { recoveryClient = recovery_client; - int64_t cycleTimeModified{ - static_cast(timers::TimeConversion::convertMilliSecToNanoSec(config.evaluation_cycle_ms))}; + std::chrono::nanoseconds cycleTimeModified{ + timers::TimeConversion::convertMilliSecToNanoSec(std::chrono::milliseconds{config.evaluation_cycle_ms})}; cycleTimeModified = CycleTimeValidator::adjustCycleTimeOnClockAccuracy(cycleTimeModified, osClock); - const int64_t timerInit{cycleTimer.init(cycleTimeModified)}; - if (timerInit > 0) + const std::chrono::nanoseconds timerInit{cycleTimer.init(cycleTimeModified)}; + if (timerInit.count() > 0) { - LM_LOG_INFO() << "Phm Daemon: The (configured) periodicity in [ns] is set to:" - << static_cast(cycleTimeModified); + LM_LOG_INFO() << "Phm Daemon: The (configured) periodicity in [ns] is set to:" << cycleTimeModified; LM_LOG_DEBUG() << "Phm Daemon: The accuracy of the monotonic system clock in [ns] is:" - << static_cast(CycleTimeValidator::getMonotonicClockAccuracy(osClock)); + << CycleTimeValidator::getMonotonicClockAccuracy(osClock); } else { @@ -122,8 +120,8 @@ class PhmDaemon final : public ISupervisionFactory template bool startCyclicExec(const TerminationSignalPredType& f_terminateCond) noexcept { - NanoSecondType startTimestamp{cycleTimer.start()}; - if (startTimestamp == 0U) + std::chrono::nanoseconds startTimestamp{cycleTimer.start()}; + if (startTimestamp.count() == 0U) { LM_LOG_ERROR() << "Phm Daemon: Failed to get initial timestamp"; return false; @@ -143,7 +141,7 @@ class PhmDaemon final : public ISupervisionFactory (void)cycleTimer.calcNextShot(); // Sleep for the remaining cycle time or break out of cyclic loop if termination is requested - std::uint64_t nsOverDeadline{0U}; + std::chrono::nanoseconds nsOverDeadline{0U}; const int sleepResult{cycleTimer.sleep(f_terminateCond, nsOverDeadline)}; if (sleepResult == EINTR) { @@ -153,8 +151,8 @@ class PhmDaemon final : public ISupervisionFactory else if (sleepResult == CycleTimer::kDeadlineAlreadyOver) { LM_LOG_DEBUG() << "Phm Daemon: Phm cycle took" - << (static_cast(nsOverDeadline) / 1000000.0 /*ns per ms*/) - << "ms longer than the configured cycle time"; + << std::chrono::ceil(nsOverDeadline) + << "longer than the configured cycle time"; } else if (sleepResult != 0) { diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.cpp index 2c186cab5a..d72a0a9055 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.cpp @@ -79,7 +79,7 @@ bool SupervisionManager::constructWorker( return true; } -void SupervisionManager::checkInterfaceForNewData(const timers::NanoSecondType f_syncTimestamp) +void SupervisionManager::checkInterfaceForNewData(const std::chrono::nanoseconds f_syncTimestamp) { for (auto& aliveInterface : aliveInterfaces) { @@ -87,7 +87,7 @@ void SupervisionManager::checkInterfaceForNewData(const timers::NanoSecondType f } } -void SupervisionManager::evaluateSupervisions(const timers::NanoSecondType f_syncTimestamp) +void SupervisionManager::evaluateSupervisions(const std::chrono::nanoseconds f_syncTimestamp) { for (auto& alive : aliveSupervisions) { @@ -107,7 +107,7 @@ bool SupervisionManager::hasAnyRecoveryEnqueueFailed() const noexcept return false; } -void SupervisionManager::performCyclicTriggers(const timers::NanoSecondType f_syncTimestamp) +void SupervisionManager::performCyclicTriggers(const std::chrono::nanoseconds f_syncTimestamp) { checkInterfaceForNewData(f_syncTimestamp); evaluateSupervisions(f_syncTimestamp); diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.hpp index cf8f990639..88dc09ee1c 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SupervisionManager.hpp @@ -107,7 +107,7 @@ class SupervisionManager /// @brief Perform cyclic execution /// @details Perform cyclic execution required for alive supervision /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization - void performCyclicTriggers(const timers::NanoSecondType f_syncTimestamp); + void performCyclicTriggers(const std::chrono::nanoseconds f_syncTimestamp); /// @brief Check whether any alive supervision failed to enqueue a recovery request /// @return True if any alive supervision recovery request has failed @@ -117,12 +117,12 @@ class SupervisionManager /// @brief Check interfaces for new data /// @details All interfaces created during construction will be checked for new data. /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization - void checkInterfaceForNewData(const timers::NanoSecondType f_syncTimestamp); + void checkInterfaceForNewData(const std::chrono::nanoseconds f_syncTimestamp); /// @brief Evaluate supervisions /// @details Evaluate all supervisions created during construction. /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization - void evaluateSupervisions(const timers::NanoSecondType f_syncTimestamp); + void evaluateSupervisions(const std::chrono::nanoseconds f_syncTimestamp); /// Vector of Process states std::vector processStates; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp index b3e809c9f7..8c3df3a36f 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp @@ -35,7 +35,6 @@ namespace score::mw::lifecycle::internal::saf::factory { using RecoveryClient = score::mw::lifecycle::IRecoveryClient; -using NanoSecondType = saf::timers::NanoSecondType; using IdentifierHash = score::mw::lifecycle::IdentifierHash; FlatCfgFactory::FlatCfgFactory() : IPhmFactory() diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.cpp index 594b904eb5..852dcde497 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.cpp @@ -22,17 +22,17 @@ Checkpoint::Checkpoint(const ifexm::ObservableEvent* f_processState_p) noexcept( static_cast(0U); } -timers::NanoSecondType Checkpoint::getTimestamp(void) const noexcept(true) +std::chrono::nanoseconds Checkpoint::getTimestamp(void) const noexcept(true) { return timestamp; } -void Checkpoint::pushData(const timers::NanoSecondType f_timestamp) noexcept(true) +void Checkpoint::pushData(const std::chrono::nanoseconds f_timestamp) noexcept(true) { timestamp = f_timestamp; // If monotonic system clock fails, set data loss event. - if (timestamp == 0U) + if (timestamp.count() == 0U) { setDataLossEvent(true); } diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.hpp index 32c813b71c..f81884b648 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/Checkpoint.hpp @@ -62,13 +62,13 @@ class Checkpoint : public saf::common::Observable ~Checkpoint() override = default; /// @brief Get timestamp - /// @return NanoSecondType Timestamp value of the reported checkpoint in [nano seconds] - score::mw::lifecycle::internal::saf::timers::NanoSecondType getTimestamp(void) const noexcept(true); + /// @return std::chrono::nanoseconds Timestamp value of the reported checkpoint in [nano seconds] + std::chrono::nanoseconds getTimestamp(void) const noexcept(true); /// @brief Push data to checkpoint observer /// @details Push the checkpoint timestamp to the checkpoint observer to notify it was reported /// @param [in] f_timestamp Timestamp value captured when the checkpoint was reported in [nano seconds] - void pushData(const score::mw::lifecycle::internal::saf::timers::NanoSecondType f_timestamp) noexcept(true); + void pushData(const std::chrono::nanoseconds f_timestamp) noexcept(true); /// @brief Set data loss event /// @details Set data loss event in the checkpoint observer @@ -91,7 +91,7 @@ class Checkpoint : public saf::common::Observable bool isDataLossEvent; /// @brief Timestamp value in [nano seconds] - score::mw::lifecycle::internal::saf::timers::NanoSecondType timestamp; + std::chrono::nanoseconds timestamp; }; } // namespace score::mw::lifecycle::internal::saf::ifappl diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/DataStructures.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/DataStructures.hpp index d4e660bbfe..375e9a921c 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/DataStructures.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/DataStructures.hpp @@ -37,14 +37,14 @@ required for Vector and IPC APIs", true_no_defect) */ struct CheckpointBufferElement final { /// @brief Timestamp of the checkpoint - internal::saf::timers::NanoSecondType timestamp{0U}; + std::chrono::nanoseconds timestamp{0U}; /// @brief Default constructor needed for storage in vector CheckpointBufferElement() = default; /// @brief Constructor for usage with emplace /// @param [in] f_timestamp The checkpoint timestamp - CheckpointBufferElement(internal::saf::timers::NanoSecondType f_timestamp) noexcept(true) : timestamp(f_timestamp) + CheckpointBufferElement(std::chrono::nanoseconds f_timestamp) noexcept(true) : timestamp(f_timestamp) { } }; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp index 59e4e55e59..953100fb2d 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp @@ -54,7 +54,7 @@ void MonitorIfDaemon::updateData(const ifexm::ObservableEvent& f_observable_r) n } } -void MonitorIfDaemon::checkForNewData(const timers::NanoSecondType f_syncTimestamp) noexcept(true) +void MonitorIfDaemon::checkForNewData(const std::chrono::nanoseconds f_syncTimestamp) noexcept(true) { if ((isActivateRequest == true) && (status == EInternalState::kInactive)) { @@ -126,7 +126,7 @@ void MonitorIfDaemon::pushCheckpointToObservers(const CheckpointBufferElement& f } } -bool MonitorIfDaemon::pushNewDataToCheckpointObservers(const timers::NanoSecondType f_syncTimestamp) +bool MonitorIfDaemon::pushNewDataToCheckpointObservers(const std::chrono::nanoseconds f_syncTimestamp) { using IpcResult = CheckpointIpcServer::EIpcPeekResult; std::uint32_t amountOfReceivedCheckpoints{0U}; @@ -188,7 +188,7 @@ void MonitorIfDaemon::pushOverflowInfoToCheckpointObservers(void) const for (auto& observer : checkpointObservers) { observer->setDataLossEvent(true); - observer->pushData(static_cast(0)); + observer->pushData(static_cast(0)); } } diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.hpp index b09c72978d..7b536c3649 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.hpp @@ -91,8 +91,7 @@ class MonitorIfDaemon : public common::Observer /// @brief Check for new data /// @details Check Alive interface for new data from application side /// @param [in] f_syncTimestamp Timestamp till data shall be read, newer data will not be considered - void checkForNewData(const score::mw::lifecycle::internal::saf::timers::NanoSecondType f_syncTimestamp) noexcept( - true); + void checkForNewData(const std::chrono::nanoseconds f_syncTimestamp) noexcept(true); private: /// @brief Check if checkpoint ring buffer overflow has occurred @@ -115,8 +114,7 @@ class MonitorIfDaemon : public common::Observer /// @details The checkpoint ring buffer data is pushed to checkpoint specific objects. /// @param [in] f_syncTimestamp Timestamp till data shall be read, newer data will not be considered /// @returns True if reading data from IPC channel and pushing data to observers was successful, else false - bool pushNewDataToCheckpointObservers( - const score::mw::lifecycle::internal::saf::timers::NanoSecondType f_syncTimestamp); + bool pushNewDataToCheckpointObservers(const std::chrono::nanoseconds f_syncTimestamp); /// @brief Push a single checkpoint to observers /// @param[in] f_elem_r The checkpoint to push to observers diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp index 2ad2204684..6833302e4c 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp @@ -72,23 +72,23 @@ struct MonitorIfDaemonFixture } /// Send an activation event and notify observers. - void activateProcess(long ts) + void activateProcess(std::chrono::nanoseconds ts) { - processState.event.systemClockTimestamp.tv_nsec = ts; + processState.event.systemClockTimestamp.tv_nsec = ts.count(); processState.event.eventType = score::mw::lifecycle::SupervisionEventType::kActivation; processState.pushData(); } /// Send a deactivation event and notify observers. - void deactivateProcess(long ts) + void deactivateProcess(std::chrono::nanoseconds ts) { - processState.event.systemClockTimestamp.tv_nsec = ts; + processState.event.systemClockTimestamp.tv_nsec = ts.count(); processState.event.eventType = score::mw::lifecycle::SupervisionEventType::kDeactivation; processState.pushData(); } /// Write a single checkpoint element into the IPC ring buffer. - void sendCheckpoint(timers::NanoSecondType ts) + void sendCheckpoint(std::chrono::nanoseconds ts) { ipcServer.sendEmplace(ts); } @@ -99,7 +99,7 @@ struct MonitorIfDaemonFixture // Sending one element beyond capacity sets the ring-buffer overflow flag. for (uint32_t i = 0U; i <= ifappl::k_maxCheckpointBufferElements; ++i) { - ipcServer.sendEmplace(static_cast(i)); + ipcServer.sendEmplace(static_cast(i)); } } }; @@ -109,43 +109,43 @@ struct MonitorIfDaemonFixture class MonitorIfDaemonTest : public ::testing::Test { private: - timespec time_{}; - static constexpr long kTimeStep = 100U; + std::chrono::nanoseconds time_{}; + static constexpr std::chrono::nanoseconds kTimeStep{100U}; protected: void SetUp() override { RecordProperty("TestType", "interface-test"); RecordProperty("DerivationTechnique", "explorative-testing"); - time_.tv_nsec = 0; + time_ = std::chrono::nanoseconds{0}; } public: /// @brief Clock that increases at fixed intervals with each call [[nodiscard]] - timers::NanoSecondType mockClock() + std::chrono::nanoseconds mockClock() { - return time_.tv_nsec += kTimeStep; + return time_ += kTimeStep; } /// @brief Increase the time by @c count mockClock() calls - timers::NanoSecondType mockClockSkip(int count) + std::chrono::nanoseconds mockClockSkip(int count) { - return time_.tv_nsec += (kTimeStep * count); + return time_ += (kTimeStep * count); } /// @brief Get the current time plus an offset smaller than the tick size [[nodiscard]] - timers::NanoSecondType mockClockOffset() const + std::chrono::nanoseconds mockClockOffset() const { - return time_.tv_nsec + 50U; + return time_ + std::chrono::nanoseconds{50U}; } /// @brief Get the time @c count mockClock() calls from now [[nodiscard]] - timers::NanoSecondType mockClockFuture(int count) const + std::chrono::nanoseconds mockClockFuture(int count) const { - return time_.tv_nsec + (kTimeStep * count); + return time_ + (kTimeStep * count); } }; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.cpp index 52734a7d2f..8d02e89d6b 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.cpp @@ -52,7 +52,7 @@ void ObservableEventReader::deregisterObservableEvent(const IdentifierHash f_pro } } -bool ObservableEventReader::distributeChanges(const timers::NanoSecondType f_syncTimestamp) noexcept +bool ObservableEventReader::distributeChanges(const std::chrono::nanoseconds f_syncTimestamp) noexcept { // If push update is pending from previous cycle, push data for last change observable event. if (isPushPending) @@ -123,7 +123,7 @@ score::Result> ObservableEventReader::getNextSup bool ObservableEventReader::pushUpdateTill( const SupervisionEvent& f_event, - const timers::NanoSecondType f_syncTimestamp) noexcept + const std::chrono::nanoseconds f_syncTimestamp) noexcept { bool isSyncTimestampReached{false}; @@ -133,7 +133,7 @@ bool ObservableEventReader::pushUpdateTill( processMapIterator->second->event.eventType = f_event.eventType; processMapIterator->second->event.systemClockTimestamp = f_event.systemClockTimestamp; - timers::NanoSecondType changedProcessTimestamp{ + std::chrono::nanoseconds changedProcessTimestamp{ timers::TimeConversion::convertToNanoSec(f_event.systemClockTimestamp)}; // If event occurred before synchronization timestamp, push data for current cycle. diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.hpp index 50958598bf..e06bf56adf 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ObservableEventReader.hpp @@ -61,14 +61,14 @@ class ObservableEventReader /// @details Distribute supervision events to the registered Observable Event classes /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization /// @return true (successful distribution), false (failed distribution) - bool distributeChanges(const timers::NanoSecondType f_syncTimestamp) noexcept; + bool distributeChanges(const std::chrono::nanoseconds f_syncTimestamp) noexcept; private: /// @brief Push update for changed registered process /// @param [in] f_event Supervision event for which push update is needed /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization /// @return true (sync timestamp is reached), false (sync timestamp is not yet reached) - bool pushUpdateTill(const SupervisionEvent& f_event, const timers::NanoSecondType f_syncTimestamp) noexcept; + bool pushUpdateTill(const SupervisionEvent& f_event, const std::chrono::nanoseconds f_syncTimestamp) noexcept; /// @brief Returns a queued SupervisionEvent that has not yet been parsed. /// @returns Result containing SupervisionEvent in case of success, or ExecError in case of failure. diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp index 8852d562d5..b84d74e541 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp @@ -31,7 +31,8 @@ Alive::Alive( saf::ifappl::Checkpoint& checkpoint_r, const uint16_t bufferSize) : ISupervision(id), - k_aliveReferenceCycle(timers::TimeConversion::convertMilliSecToNanoSec(f_aliveCfg_r.reporting_cycle_ms)), + k_aliveReferenceCycle( + timers::TimeConversion::convertMilliSecToNanoSec(std::chrono::milliseconds{f_aliveCfg_r.reporting_cycle_ms})), k_minAliveIndications(f_aliveCfg_r.min_indications.value_or(0)), k_maxAliveIndications(f_aliveCfg_r.max_indications.value_or(0)), k_isMinCheckDisabled(k_minAliveIndications == 0), @@ -43,7 +44,7 @@ Alive::Alive( { checkpoint_r.attachObserver(*this); SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE( - (k_aliveReferenceCycle != 0U), "k_aliveReferenceCycle=0 causes infinite loop during evaluation."); + (k_aliveReferenceCycle.count() != 0U), "k_aliveReferenceCycle=0 causes infinite loop during evaluation."); SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE( (aliveStatus == EStatus::kDeactivated), "Alive Supervision must start in deactivated state, see SWS_PHM_00204"); @@ -55,13 +56,13 @@ Alive::Alive( // coverity[exn_spec_violation:FALSE] std::length_error is not thrown from push() which uses fixed-size-vector void Alive::updateData(const score::mw::lifecycle::internal::saf::ifappl::Checkpoint& f_observable_r) noexcept(true) { - timers::NanoSecondType timestamp{f_observable_r.getTimestamp()}; + std::chrono::nanoseconds timestamp{f_observable_r.getTimestamp()}; if (f_observable_r.getDataLossEvent()) { dataLossReason = EDataLossReason::kSharedMemory; // If clock error is detected, last syncTimestamp is used as event timestamp. - eventTimestamp = ((timestamp == 0U) ? lastSyncTimestamp : timestamp); + eventTimestamp = ((timestamp.count() == 0U) ? lastSyncTimestamp : timestamp); } else { @@ -77,7 +78,7 @@ void Alive::updateData(const score::mw::lifecycle::internal::saf::ifappl::Checkp // coverity[exn_spec_violation:FALSE] std::length_error is not thrown from push() which uses fixed-size-vector void Alive::updateData(const ifexm::ObservableEvent& f_observable_r) noexcept(true) { - const timers::NanoSecondType timestamp{ + const std::chrono::nanoseconds timestamp{ timers::TimeConversion::convertToNanoSec(f_observable_r.event.systemClockTimestamp)}; SupervisionEventSnapshot snapshot{timestamp, f_observable_r.event.eventType}; if (!timeSortingUpdateEventBuffer.push(snapshot, timestamp)) @@ -92,12 +93,12 @@ Alive::EStatus Alive::getStatus(void) const noexcept(true) return aliveStatus; } -timers::NanoSecondType Alive::getTimestamp(void) const noexcept(true) +std::chrono::nanoseconds Alive::getTimestamp(void) const noexcept(true) { return eventTimestamp; } -void Alive::evaluate(const timers::NanoSecondType f_syncTimestamp) +void Alive::evaluate(const std::chrono::nanoseconds f_syncTimestamp) { storeSyncEvent(f_syncTimestamp); @@ -113,7 +114,7 @@ void Alive::evaluate(const timers::NanoSecondType f_syncTimestamp) while (sortedUpdateEvent_p != nullptr) { - timers::NanoSecondType timestampOfUpdateEvent{getTimestampOfUpdateEvent(*sortedUpdateEvent_p)}; + std::chrono::nanoseconds timestampOfUpdateEvent{getTimestampOfUpdateEvent(*sortedUpdateEvent_p)}; SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( (timestampOfUpdateEvent <= f_syncTimestamp), "Alive supervision: Checkpoint events are reported beyond syncTimestamp."); @@ -177,7 +178,7 @@ void Alive::evaluate(const timers::NanoSecondType f_syncTimestamp) lastSyncTimestamp = f_syncTimestamp; } -void Alive::storeSyncEvent(const timers::NanoSecondType f_syncTimestamp) +void Alive::storeSyncEvent(const std::chrono::nanoseconds f_syncTimestamp) { // If there is a reported alive checkpoint exactly at syncTimestamp, push will update sync event after the // reported alive checkpoint during sorting. Reason: Sync event is pushed after last alive checkpoint. @@ -201,7 +202,7 @@ void Alive::handleDataLossReaction(void) noexcept(true) } bool Alive::detectEvaluationEvent( - const timers::NanoSecondType f_timestampOfUpdateEvent, + const std::chrono::nanoseconds f_timestampOfUpdateEvent, const TimeSortedUpdateEvent f_updateEvent) const noexcept(true) { bool isEvaluationEvent; @@ -290,7 +291,7 @@ Alive::EUpdateEventType Alive::getAliveEventType( void Alive::checkTransitionsOutOfDeactivated( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true) + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true) { if (f_updateEventType == EUpdateEventType::kActivation) { @@ -304,7 +305,7 @@ void Alive::checkTransitionsOutOfDeactivated( void Alive::checkTransitionsToDeactivated( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true) + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true) { if ((f_updateEventType == EUpdateEventType::kDeactivation) && (aliveStatus != EStatus::kDeactivated)) { @@ -315,7 +316,7 @@ void Alive::checkTransitionsToDeactivated( void Alive::checkTransitionsOutOfOk( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true) + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true) { // Accept only alive checkpoint or evaluation event. // Deactivation event is handled at the end of evaluate function. @@ -333,13 +334,13 @@ void Alive::checkTransitionsOutOfOk( } } -bool Alive::setReferenceCycleTimestamps(timers::NanoSecondType f_baseValue) noexcept(true) +bool Alive::setReferenceCycleTimestamps(std::chrono::nanoseconds f_baseValue) noexcept(true) { - if (f_baseValue > UINT64_MAX - k_aliveReferenceCycle) + if (f_baseValue > std::chrono::nanoseconds::max() - k_aliveReferenceCycle) { LM_LOG_ERROR() << "Alive Supervision (" << getConfigName() << ") overflow appeared during increase of reference cycle timestamps"; - eventTimestamp = std::max(referenceCycleEnd + 1U, UINT64_MAX); + eventTimestamp = std::max(referenceCycleEnd + std::chrono::nanoseconds{1U}, std::chrono::nanoseconds::max()); switchToExpired(EReason::kOverflow); return true; } @@ -348,7 +349,7 @@ bool Alive::setReferenceCycleTimestamps(timers::NanoSecondType f_baseValue) noex return false; } -void Alive::incIndicationCount(const timers::NanoSecondType f_updateEventTimestamp) noexcept(true) +void Alive::incIndicationCount(const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true) { if (indicationCount == UINT32_MAX) { @@ -382,7 +383,7 @@ void Alive::evaluateRefCycleOutOfOk(void) noexcept(true) void Alive::checkTransitionsOutOfFailed( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true) + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true) { // Accept only alive checkpoint or evaluation event. // Deactivation event is handled at the end of evaluate function. @@ -441,8 +442,8 @@ void Alive::switchToDeactivated(void) noexcept(true) aliveStatus = EStatus::kDeactivated; failedSupervisionCycles = 0U; indicationCount = 0U; - referenceCycleStart = 0U; - referenceCycleEnd = UINT64_MAX; + referenceCycleStart = std::chrono::nanoseconds{0U}; + referenceCycleEnd = std::chrono::nanoseconds::max(); LM_LOG_DEBUG() << "Alive Supervision (" << getConfigName() << ") switched to DEACTIVATED."; @@ -510,8 +511,8 @@ void Alive::switchToExpired(Alive::EReason reason) noexcept(true) failedSupervisionCycles = k_failedSupervisionCyclesTolerance; indicationCount = 0U; - referenceCycleStart = 0U; - referenceCycleEnd = UINT64_MAX; + referenceCycleStart = std::chrono::nanoseconds{0U}; + referenceCycleEnd = std::chrono::nanoseconds::max(); dataLossReason = EDataLossReason::kNoDataLoss; const bool enqueued = recoveryClient_p->sendRecoveryRequest(processIdentifier_); @@ -577,9 +578,9 @@ void Alive::logExpiredFailedStateDetails() const noexcept(true) << k_failedSupervisionCyclesTolerance; } -timers::NanoSecondType Alive::getTimestampOfUpdateEvent(const TimeSortedUpdateEvent f_updateEvent) noexcept(true) +std::chrono::nanoseconds Alive::getTimestampOfUpdateEvent(const TimeSortedUpdateEvent f_updateEvent) noexcept(true) { - timers::NanoSecondType timestamp{0U}; + std::chrono::nanoseconds timestamp{0U}; if (std::holds_alternative(f_updateEvent)) { timestamp = std::get(f_updateEvent).timestamp; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp index c6f0df911d..e8b029cbae 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp @@ -117,7 +117,7 @@ class Alive : public ISupervision, void updateData(const ifexm::ObservableEvent& f_observable_r) noexcept(true) override; /// @copydoc ISupervision::evaluate() - void evaluate(const timers::NanoSecondType f_syncTimestamp) override; + void evaluate(const std::chrono::nanoseconds f_syncTimestamp) override; /// @brief Get Supervision status /// @return Status of Supervision @@ -125,7 +125,7 @@ class Alive : public ISupervision, /// @brief Get timestamp of supervision event /// @return Timestamp of checkpoint supervision event - timers::NanoSecondType getTimestamp(void) const noexcept(true); + std::chrono::nanoseconds getTimestamp(void) const noexcept(true); /// @brief Check whether a recovery request failed to enqueue (ring buffer full) /// @return True if sendRecoveryRequest failed @@ -143,21 +143,21 @@ class Alive : public ISupervision, // cppcheck-suppress unusedStructMember CheckpointIdentifier identifier_p{nullptr}; /// @brief timestamp of checkpoint - timers::NanoSecondType timestamp{UINT64_MAX}; + std::chrono::nanoseconds timestamp{std::chrono::nanoseconds::max()}; }; /// @brief Time sorted supervision event snapshot (activation / deactivation event) struct SupervisionEventSnapshot final { /// @brief Timestamp of the supervision event - timers::NanoSecondType timestamp{UINT64_MAX}; + std::chrono::nanoseconds timestamp{std::chrono::nanoseconds::max()}; /// @brief Supervision event type that triggered this snapshot // cppcheck-suppress unusedStructMember score::mw::lifecycle::SupervisionEventType eventType{score::mw::lifecycle::SupervisionEventType::kDeactivation}; }; /// @brief Sync snapshot stores sync timestamp in the time sorting buffer - using SyncSnapshot = timers::NanoSecondType; + using SyncSnapshot = std::chrono::nanoseconds; /// @brief Defines one element of time sorted update event using TimeSortedUpdateEvent = std::variant; @@ -176,35 +176,35 @@ class Alive : public ISupervision, /// @brief Get timestamp of current update event /// @param [in] f_updateEvent Sorted update event (e.g, Activation, Deactivation, Checkpoint, ...) from Buffer /// @return Timestamp of update event - static timers::NanoSecondType getTimestampOfUpdateEvent(const TimeSortedUpdateEvent f_updateEvent) noexcept(true); + static std::chrono::nanoseconds getTimestampOfUpdateEvent(const TimeSortedUpdateEvent f_updateEvent) noexcept(true); /// @brief Check and trigger transition out of state Deactivated /// @param [in] f_updateEventType Type of update event (e.g, Activation, Deactivation, Checkpoint, ...) /// @param [in] f_updateEventTimestamp Timestamp of update event void checkTransitionsOutOfDeactivated( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true); + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true); /// @brief Check and trigger common transitions to state Deactivated /// @param [in] f_updateEventType Type of update event (e.g, Activation, Deactivation, Checkpoint, ...) /// @param [in] f_updateEventTimestamp Timestamp of update event void checkTransitionsToDeactivated( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true); + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true); /// @brief Check and trigger transition out of state Ok /// @param [in] f_updateEventType Type of update event (e.g, Activation, Deactivation, Checkpoint, ...) /// @param [in] f_updateEventTimestamp Timestamp of update event void checkTransitionsOutOfOk( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true); + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true); /// @brief Check and trigger transition out of state Failed /// @param [in] f_updateEventType Type of update event (e.g, Activation, Deactivation, Checkpoint, ...) /// @param [in] f_updateEventTimestamp Timestamp of update event void checkTransitionsOutOfFailed( const EUpdateEventType f_updateEventType, - const timers::NanoSecondType f_updateEventTimestamp) noexcept(true); + const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true); /// @brief Get the type of current update events for alive supervision (including evaluation event) /// @param [in] f_isEvaluationEvent Flag for indicating evaluation event @@ -221,7 +221,7 @@ class Alive : public ISupervision, /// @param [in] f_updateEvent Sorted update event (e.g, Activation, Deactivation, Checkpoint, ...) from Buffer /// @return True: evaluation event is set, False: no evaluation event bool detectEvaluationEvent( - const timers::NanoSecondType f_timestampOfUpdateEvent, + const std::chrono::nanoseconds f_timestampOfUpdateEvent, const TimeSortedUpdateEvent f_updateEvent) const noexcept(true); /// @brief Evaluate alive supervision after reference cycle in Ok state @@ -232,7 +232,7 @@ class Alive : public ISupervision, /// @brief Store sync event in time sorting buffer /// @param [in] f_syncTimestamp synchronization timestamp - void storeSyncEvent(const timers::NanoSecondType f_syncTimestamp); + void storeSyncEvent(const std::chrono::nanoseconds f_syncTimestamp); /// @brief Handle data loss reaction void handleDataLossReaction(void) noexcept(true); @@ -284,17 +284,17 @@ class Alive : public ISupervision, /// @brief Increment indication count and check for overflow /// @details If overflow appears, status is set to EXPIRED /// @param [in] f_updateEventTimestamp Timestamp of last update event which lead to increment of indication count - void incIndicationCount(const timers::NanoSecondType f_updateEventTimestamp) noexcept(true); + void incIndicationCount(const std::chrono::nanoseconds f_updateEventTimestamp) noexcept(true); /// @brief Set reference cycle timestamps if no overflow appears /// @details Set referenceCycleStart to the provided param and referenceCycleEnd to f_baseValue + /// k_aliveReferenceCycle. If overflow would appear status is set to EXPIRED. /// @param [in] f_baseValue Value to set reference referenceCycleStart /// @return true on overflow and vice versa - bool setReferenceCycleTimestamps(timers::NanoSecondType f_baseValue) noexcept(true); + bool setReferenceCycleTimestamps(std::chrono::nanoseconds f_baseValue) noexcept(true); /// @brief Alive reference cycle in [nano seconds] - const score::mw::lifecycle::internal::saf::timers::NanoSecondType k_aliveReferenceCycle; + const std::chrono::nanoseconds k_aliveReferenceCycle; /// @brief Minimum allowed alive indications const uint32_t k_minAliveIndications; @@ -327,10 +327,10 @@ class Alive : public ISupervision, EStatus aliveStatus{EStatus::kDeactivated}; /// @brief alive reference cycle start time in [nano seconds] - timers::NanoSecondType referenceCycleStart{0U}; + std::chrono::nanoseconds referenceCycleStart{0U}; /// @brief alive reference cycle end time in [nano seconds] - timers::NanoSecondType referenceCycleEnd{UINT64_MAX}; + std::chrono::nanoseconds referenceCycleEnd{std::chrono::nanoseconds::max()}; /// @brief Number of indications that belong to the current alive reference cycle uint32_t indicationCount{0U}; @@ -340,11 +340,11 @@ class Alive : public ISupervision, /// @brief Timestamp in which state change is detected in [nano seconds] /// @details This timestamp is updated whenever assessment is done or data loss has occurred. - saf::timers::NanoSecondType eventTimestamp{0U}; + std::chrono::nanoseconds eventTimestamp{0U}; /// @brief Sync timestamp from current evaluation [nano seconds] /// @details This is required for eventTimestamp in case of data loss - saf::timers::NanoSecondType lastSyncTimestamp{0U}; + std::chrono::nanoseconds lastSyncTimestamp{0U}; /// @brief Time sorting buffer for update events in alive supervision /// @details This buffer sorts all process events and checkpoint events in the same buffer. diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp index 384676523f..4ed542f0f5 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp @@ -29,6 +29,8 @@ using namespace testing; using EStatus = score::mw::lifecycle::internal::saf::supervision::Alive::EStatus; using score::mw::lifecycle::internal::configuration::ComponentAliveSupervision; +using namespace std::chrono_literals; + namespace { @@ -114,23 +116,23 @@ struct AliveFixture } /// Send an activation event and notify observers. - void activateProcess(long ts) + void activateProcess(std::chrono::nanoseconds ts) { - processState.event.systemClockTimestamp.tv_nsec = ts; + processState.event.systemClockTimestamp.tv_nsec = ts.count(); processState.event.eventType = score::mw::lifecycle::SupervisionEventType::kActivation; processState.pushData(); } /// Send a deactivation event and notify observers. - void deactivateProcess(long ts) + void deactivateProcess(std::chrono::nanoseconds ts) { - processState.event.systemClockTimestamp.tv_nsec = ts; + processState.event.systemClockTimestamp.tv_nsec = ts.count(); processState.event.eventType = score::mw::lifecycle::SupervisionEventType::kDeactivation; processState.pushData(); } /// Report one alive heartbeat checkpoint at the given timestamp. - void reportHeartbeat(score::mw::lifecycle::internal::saf::timers::NanoSecondType timestamp) + void reportHeartbeat(std::chrono::nanoseconds timestamp) { checkpoint.pushData(timestamp); } @@ -161,12 +163,12 @@ TEST_F(AliveSupervisionTest, AliveTransitionsOkToExpiredOnMissingHeartbeat) EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); // No heartbeats; reference cycle ends at 10 + 100000 = 1000010 - fix.alive->evaluate(1000011U); + fix.alive->evaluate(1000011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kExpired); } @@ -178,18 +180,18 @@ TEST_F(AliveSupervisionTest, AliveStaysOkWithCorrectHeartbeats) EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); // Cycle 1: one heartbeat at t=500 (within [10, 1010]), evaluate at t=1011 - fix.reportHeartbeat(500U); - fix.alive->evaluate(1011U); + fix.reportHeartbeat(500ns); + fix.alive->evaluate(1011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); // Cycle 2: one heartbeat at t=1500 (within [1010, 2010]), evaluate at t=2011 - fix.reportHeartbeat(1500U); - fix.alive->evaluate(2011U); + fix.reportHeartbeat(1500ns); + fix.alive->evaluate(2011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); } @@ -203,12 +205,12 @@ TEST_F(AliveSupervisionTest, AliveReportsEnqueueFailureWhenRingBufferFull) EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(fix.kProcessIdentifier)).Times(1).WillOnce(Return(false)); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_FALSE(fix.alive->hasRecoveryEnqueueFailed()); - fix.alive->evaluate(1000011U); + fix.alive->evaluate(1000011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kExpired); EXPECT_TRUE(fix.alive->hasRecoveryEnqueueFailed()); } @@ -225,16 +227,16 @@ TEST_F(AliveSupervisionTest, AliveDebouncesThroughFailedBeforeExpired) .Times(1) .WillOnce(::testing::Return(true)); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); // First missed cycle: ok -> failed (tolerance not yet exceeded) - fix.alive->evaluate(1000011U); + fix.alive->evaluate(1000011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kFailed); // Second missed cycle: tolerance exceeded -> expired - fix.alive->evaluate(2000011U); + fix.alive->evaluate(2000011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kExpired); } @@ -245,12 +247,12 @@ TEST_F(AliveSupervisionTest, DeactivatesOnSupervisionDeactivation) EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); - fix.deactivateProcess(20U); - fix.alive->evaluate(21U); + fix.deactivateProcess(20ns); + fix.alive->evaluate(21ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); } @@ -264,16 +266,16 @@ TEST_F(AliveSupervisionTest, ReactivatesAfterDeactivation) EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); - fix.deactivateProcess(20U); - fix.alive->evaluate(21U); + fix.deactivateProcess(20ns); + fix.alive->evaluate(21ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); - fix.activateProcess(30U); - fix.alive->evaluate(31U); + fix.activateProcess(30ns); + fix.alive->evaluate(31ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); } @@ -285,13 +287,13 @@ TEST_F(AliveSupervisionTest, MaxIndicationViolationExpires) EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(fix.kProcessIdentifier)).Times(1).WillOnce(Return(true)); - fix.activateProcess(10U); - fix.alive->evaluate(11U); + fix.activateProcess(10ns); + fix.alive->evaluate(11ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); // Two heartbeats in one cycle violates max=1 - fix.reportHeartbeat(100U); - fix.reportHeartbeat(200U); - fix.alive->evaluate(1000011U); + fix.reportHeartbeat(100ns); + fix.reportHeartbeat(200ns); + fix.alive->evaluate(1000011ns); EXPECT_EQ(fix.alive->getStatus(), EStatus::kExpired); } diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/ISupervision.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/ISupervision.hpp index 7555e7bd4f..90be7632e8 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/ISupervision.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/ISupervision.hpp @@ -48,7 +48,7 @@ class ISupervision /// This method tells the supervision that all supervision interfaces were queried for new data /// and the collected data (checkpoints) is now ready for evaluation. /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization - virtual void evaluate(const timers::NanoSecondType f_syncTimestamp) = 0; + virtual void evaluate(const std::chrono::nanoseconds f_syncTimestamp) = 0; /// @brief Get the name of the configuration element for the corresponding supervision container /// @return The hashed name of the corresponding supervision configuration container diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.cpp index c19ee28f20..c5329b9d30 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.cpp @@ -15,31 +15,31 @@ namespace score::mw::lifecycle::internal::saf::timers { -int64_t CycleTimeValidator::getMonotonicClockAccuracy( +std::chrono::nanoseconds CycleTimeValidator::getMonotonicClockAccuracy( const score::mw::lifecycle::internal::saf::timers::OsClockInterface& f_clock_sys) noexcept(true) { struct timespec clockResolution{}; - int64_t accuracyNs{-1}; + std::chrono::nanoseconds accuracyNs{-1}; const int getResResult{f_clock_sys.clockGetRes(&clockResolution)}; if (0 == getResResult) { - accuracyNs = clockResolution.tv_nsec; + accuracyNs = std::chrono::nanoseconds{clockResolution.tv_nsec}; } return accuracyNs; } -int64_t CycleTimeValidator::adjustCycleTimeOnClockAccuracy( - const int64_t f_requested_interval_ns, +std::chrono::nanoseconds CycleTimeValidator::adjustCycleTimeOnClockAccuracy( + const std::chrono::nanoseconds f_requested_interval_ns, const score::mw::lifecycle::internal::saf::timers::OsClockInterface& f_clock_sys) noexcept(true) { - int64_t intervalNs{-1}; // start with an invalid value + std::chrono::nanoseconds intervalNs{-1}; // start with an invalid value - const int64_t accuracyNs{ + const std::chrono::nanoseconds accuracyNs{ score::mw::lifecycle::internal::saf::timers::CycleTimeValidator::getMonotonicClockAccuracy(f_clock_sys)}; - if (0 < accuracyNs) + if (accuracyNs.count() > 0) { if (f_requested_interval_ns >= accuracyNs) { diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.hpp index 054bc431ca..0ea549aec6 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimeValidator.hpp @@ -28,7 +28,7 @@ class CycleTimeValidator /// @brief Get the monotonic clock accuracy in nanoseconds /// @param[in] f_clock_sys Interface to access the system clock functionality /// @return nanoseconds or -1 if receiving the clock resolution fails - static int64_t getMonotonicClockAccuracy( + static std::chrono::nanoseconds getMonotonicClockAccuracy( const score::mw::lifecycle::internal::saf::timers::OsClockInterface& f_clock_sys) noexcept(true); /// @brief Adjust a given time interval based on the clock accuracy of @@ -39,8 +39,8 @@ class CycleTimeValidator /// - the requested interval if it's actually greater than the system's clock accuracyl /// - clock accuracy if the requested time interval is < clock accuracy /// - -1 if retrieving the system's clock resolution failed - static int64_t adjustCycleTimeOnClockAccuracy( - const int64_t f_requested_interval_ns, + static std::chrono::nanoseconds adjustCycleTimeOnClockAccuracy( + const std::chrono::nanoseconds f_requested_interval_ns, const score::mw::lifecycle::internal::saf::timers::OsClockInterface& f_clock_sys) noexcept(true); }; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.cpp index a6647f575d..5eb3ccde5b 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.cpp @@ -26,18 +26,18 @@ CycleTimer::CycleTimer(const score::mw::lifecycle::internal::saf::timers::OsCloc static_cast(0U); } -int64_t CycleTimer::init(int64_t f_sleepIntervalNs) noexcept +std::chrono::nanoseconds CycleTimer::init(std::chrono::nanoseconds f_sleepIntervalNs) noexcept { if (nullptr == osInterface) { - sleepIntervalNs = -2; + sleepIntervalNs = std::chrono::nanoseconds{-2}; return sleepIntervalNs; } // check for invalid cycle time - if (f_sleepIntervalNs <= 0) + if (f_sleepIntervalNs.count() <= 0) { - sleepIntervalNs = -3; + sleepIntervalNs = std::chrono::nanoseconds{-3}; return sleepIntervalNs; } @@ -45,7 +45,7 @@ int64_t CycleTimer::init(int64_t f_sleepIntervalNs) noexcept struct timespec tmp = {}; if (-1 == osInterface->clockGetTime(&tmp)) { - sleepIntervalNs = -1; + sleepIntervalNs = std::chrono::nanoseconds{-1}; } else { @@ -55,7 +55,7 @@ int64_t CycleTimer::init(int64_t f_sleepIntervalNs) noexcept return sleepIntervalNs; } -NanoSecondType CycleTimer::start() noexcept +std::chrono::nanoseconds CycleTimer::start() noexcept { const int result{osInterface->clockGetTime(&deadline)}; if (0 == result) @@ -64,7 +64,7 @@ NanoSecondType CycleTimer::start() noexcept } else { - return 0U; + return std::chrono::nanoseconds{0U}; } } @@ -73,11 +73,11 @@ struct timespec& CycleTimer::calcNextShot() noexcept(true) static_assert(sizeof(long) == 8U, "long is not 64 bit"); // tv_nsec max retval from clockGetTime() 0,000,000,001,000,000,000 ns (1s) // tv_nsec absolute max (long)(64bit) 9,223,372,036,854,775,807 ns - // sleepIntervalNs max (int64_t) 60,000,000,000 ns (60s CONSTR_PHM_DAEMON_CYCLE_TIME_RANGE) + // sleepIntervalNs max (std::chrono::nanoseconds) 60,000,000,000 ns (60s CONSTR_PHM_DAEMON_CYCLE_TIME_RANGE) // Overflow can occur after 9223372036854775807 / 60000000000 ~ 153722867 cycles // which corresponds to 153722867 * 60s = 9223372020s = 153722867min ~ 2562047h ~ 106751d ~ 292y // coverity[autosar_cpp14_a4_7_1_violation] overflow would only occur after ~292 years active device runtime - deadline.tv_nsec += sleepIntervalNs; + deadline.tv_nsec += sleepIntervalNs.count(); handleNanoSecOverflow(); @@ -86,6 +86,7 @@ struct timespec& CycleTimer::calcNextShot() noexcept(true) void CycleTimer::handleNanoSecOverflow() noexcept(true) { + constexpr long k_nanoSecondsPerSecond = std::chrono::nanoseconds{std::chrono::seconds{1}}.count(); while (deadline.tv_nsec >= k_nanoSecondsPerSecond) { deadline.tv_nsec -= k_nanoSecondsPerSecond; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.hpp index 6b03fdc2f8..8936952ac1 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/CycleTimer.hpp @@ -24,9 +24,6 @@ namespace score::mw::lifecycle::internal::saf::timers { -// coverity[autosar_cpp14_m3_4_1_violation] value is referenced in multiple files, but depending on build package. -constexpr int64_t k_nanoSecondsPerSecond{1000000000}; - /// @brief Features to realize robust cyclic / periodic loops on a POSIX-compliant system (e.g. QNX, Linux) /// /// @details All direct system calls are wrapped behind an interface for the sake of simpler unit testing w/ possibility @@ -57,11 +54,11 @@ class CycleTimer /// execution. The method returns immediately right on the first error occurrence. The implementation will set /// sleepIntervalNs attribute on success. /// @todo Use conversion operators to switch between ms and ns - int64_t init(int64_t f_sleepIntervalNs) noexcept; + std::chrono::nanoseconds init(std::chrono::nanoseconds f_sleepIntervalNs) noexcept; /// @brief Start the cyclic timer /// @return start timestamp in nano seconds (0ns in case of failure) - NanoSecondType start() noexcept; + std::chrono::nanoseconds start() noexcept; /// @pre init() has been invoked with success /// @post calcNextShot() will be invoked @@ -78,10 +75,11 @@ class CycleTimer /* RULECHECKER_comment(0, 4, check_cheap_to_copy_in_parameter, "f_exitRequested_r is passed as reference\ to refer to original object", true_no_defect) */ template - int sleep(const TerminationSignalPredType& f_exitRequested_r, std::uint64_t& f_nsOverDeadline_r) const noexcept + int sleep(const TerminationSignalPredType& f_exitRequested_r, std::chrono::nanoseconds& f_nsOverDeadline_r) + const noexcept { struct timespec now = {}; - f_nsOverDeadline_r = 0U; + f_nsOverDeadline_r = std::chrono::nanoseconds{0U}; // If clockGetTime fails, we do not calculate the time (possibly) passed the deadline // and will not use the returned timestamp. // In case of such clock error, the clockNanosleep below will fail as well and the error is handled there. @@ -89,11 +87,11 @@ class CycleTimer { if ((now.tv_sec > deadline.tv_sec) || ((now.tv_sec == deadline.tv_sec) && (now.tv_nsec > deadline.tv_nsec))) { - const long secDiff{now.tv_sec - deadline.tv_sec}; - const long nsDiff{now.tv_nsec - deadline.tv_nsec}; + const std::chrono::seconds secDiff{now.tv_sec - deadline.tv_sec}; + const std::chrono::nanoseconds nsDiff{now.tv_nsec - deadline.tv_nsec}; // Arithmetic overflow unlikely (deadline would have to be missed by hundreds of years) - const long nsOverDeadlineSigned{nsDiff + k_nanoSecondsPerSecond * secDiff}; - f_nsOverDeadline_r = static_cast(nsOverDeadlineSigned); + const std::chrono::nanoseconds nsOverDeadlineSigned{nsDiff + secDiff}; + f_nsOverDeadline_r = nsOverDeadlineSigned; return kDeadlineAlreadyOver; } } @@ -127,9 +125,7 @@ class CycleTimer const score::mw::lifecycle::internal::saf::timers::OsClockInterface* osInterface; /// @brief Cycle time interval value in nanoseconds - /// - /// @todo NanoSeconds as concrete type - int64_t sleepIntervalNs; + std::chrono::nanoseconds sleepIntervalNs; /// @brief Contains the absolute time until when to sleep /// diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.cpp index 4419894565..0518c926b0 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.cpp @@ -18,52 +18,49 @@ namespace score::mw::lifecycle::internal::saf::timers { -NanoSecondType TimeConversion::convertToNanoSec(const timespec f_timespec) noexcept(true) +using namespace std::chrono; + +nanoseconds TimeConversion::convertToNanoSec(const timespec f_timespec) noexcept(true) { // Result (0: invalid, >=0: valid) - NanoSecondType result{0U}; - // Calculate maximum number of seconds which can be stored in 64 bit unsigned integer - static constexpr NanoSecondType timeMaxSecond{std::numeric_limits::max() / k_nanoSecInSec}; - if ((f_timespec.tv_sec >= 0) && (f_timespec.tv_nsec >= 0) && - (static_cast(f_timespec.tv_sec) <= timeMaxSecond)) + + constexpr seconds max_seconds = duration_cast(nanoseconds::max()); + constexpr nanoseconds max_nanoseconds = nanoseconds::max(); + + if (f_timespec.tv_sec > max_seconds.count() || f_timespec.tv_sec < 0) { - NanoSecondType timeNanoSecPart1{static_cast(f_timespec.tv_sec) * k_nanoSecInSec}; - if ((std::numeric_limits::max() - timeNanoSecPart1) >= - static_cast(f_timespec.tv_nsec)) - { - result = timeNanoSecPart1 + static_cast(f_timespec.tv_nsec); - } + return nanoseconds{0}; } - return result; -} -NanoSecondType TimeConversion::convertMilliSecToNanoSec(const double f_timeValueMilliSec) noexcept(true) -{ - NanoSecondType nanoSeconds{0U}; - double timeValue{f_timeValueMilliSec}; - - timeValue = timeValue * k_nanoSecInMilliSec; + if (f_timespec.tv_nsec > max_nanoseconds.count() || f_timespec.tv_nsec < 0) + { + return nanoseconds{0}; + } - if (timeValue >= static_cast(std::numeric_limits::max())) + if (max_nanoseconds - seconds{f_timespec.tv_sec} < nanoseconds{f_timespec.tv_nsec}) { - nanoSeconds = std::numeric_limits::max(); + return nanoseconds{0}; } - else if (timeValue < 0.0) + + return seconds{f_timespec.tv_sec} + nanoseconds{f_timespec.tv_nsec}; +} + +nanoseconds TimeConversion::convertMilliSecToNanoSec(const milliseconds f_timeValueMilliSec) noexcept(true) +{ + if (f_timeValueMilliSec.count() < 0) { - nanoSeconds = 0U; + return nanoseconds{0U}; } - else + if (f_timeValueMilliSec > duration_cast(nanoseconds::max())) { - nanoSeconds = static_cast(timeValue); + return nanoseconds::max(); } - return nanoSeconds; + return nanoseconds{f_timeValueMilliSec}; } -double TimeConversion::convertNanoSecToMilliSec(const NanoSecondType f_timeValueNanoSec) noexcept(true) +milliseconds TimeConversion::convertNanoSecToMilliSec(const nanoseconds f_timeValueNanoSec) noexcept(true) { - double milliSeconds{static_cast(f_timeValueNanoSec) / k_nanoSecInMilliSec}; - - return milliSeconds; + return duration_cast(f_timeValueNanoSec); } } // namespace score::mw::lifecycle::internal::saf::timers diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.hpp index 48e4ebc17f..0f62295b1c 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion.hpp @@ -16,11 +16,10 @@ /* RULECHECKER_comment(0, 4, {check_include_time}, "Monotonic clock is needed from this header.\ other clocks and time format is not used.", true_no_defect) */ +#include #include #include -#include "score/mw/launch_manager/alive_monitor/details/timers/Timers_OsClock.hpp" - namespace score::mw::lifecycle::internal::saf::timers { @@ -42,25 +41,22 @@ class TimeConversion /// Convert time value in timespec (second and nanosecond) to nanoseconds /// @param [in] f_timespec Time value in timespec (second and nanosecond) - /// @return NanoSecondType Time value converted to nanoseconds + /// @return std::chrono::nanoseconds Time value converted to nanoseconds /// (returns 0 in case of an invalid timespec) - static NanoSecondType convertToNanoSec(const timespec f_timespec) noexcept(true); + static std::chrono::nanoseconds convertToNanoSec(const timespec f_timespec) noexcept(true); /// Convert time value in milliseconds to nanoseconds /// @param [in] f_timeValueMilliSec Time value in milliseconds unit - /// @return NanoSecondType Time value converted to nanoseconds + /// @return std::chrono::nanoseconds Time value converted to nanoseconds /// (returns 0 in case of an error) - static NanoSecondType convertMilliSecToNanoSec(const double f_timeValueMilliSec) noexcept(true); + static std::chrono::nanoseconds convertMilliSecToNanoSec( + const std::chrono::milliseconds f_timeValueMilliSec) noexcept(true); /// Convert time value in nanoseconds to milliseconds /// @param [in] f_timeValueNanoSec Time value in nanoseconds unit /// @return double Time value converted to milliseconds - static double convertNanoSecToMilliSec(const NanoSecondType f_timeValueNanoSec) noexcept(true); - - /// Factor for conversion from seconds to nanoseconds - static constexpr uint32_t k_nanoSecInSec{static_cast(1000U) * 1000U * 1000U}; - /// Factor for conversion from milliseconds to nanoseconds - static constexpr double k_nanoSecInMilliSec{1000.0 * 1000.0}; + static std::chrono::milliseconds convertNanoSecToMilliSec( + const std::chrono::nanoseconds f_timeValueNanoSec) noexcept(true); }; } // namespace score::mw::lifecycle::internal::saf::timers diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion_UT.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion_UT.cpp index 7724ecde80..c1e1c40370 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion_UT.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/TimeConversion_UT.cpp @@ -20,17 +20,16 @@ using namespace testing; -using score::mw::lifecycle::internal::saf::timers::NanoSecondType; using score::mw::lifecycle::internal::saf::timers::TimeConversion; +using namespace std::chrono; +using namespace std::chrono_literals; namespace { -// Largest tv_sec that can still be represented in nanoseconds without overflowing NanoSecondType. -constexpr NanoSecondType k_maxSeconds{std::numeric_limits::max() / TimeConversion::k_nanoSecInSec}; -// Remaining nanoseconds that fit on top of k_maxSeconds seconds before overflowing NanoSecondType. -constexpr NanoSecondType k_maxRemainderNanoSec{ - std::numeric_limits::max() - (k_maxSeconds * TimeConversion::k_nanoSecInSec)}; +constexpr std::chrono::seconds k_maxSeconds = std::chrono::seconds::max(); + +const std::chrono::nanoseconds k_maxRemainderNanoSec = std::chrono::nanoseconds::max() - k_maxSeconds; class TimeConversionTest : public ::testing::Test { @@ -50,7 +49,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_ZeroTimespec_ReturnsZero) { RecordProperty("Description", "This test verifies that a zero-valued timespec is converted to zero nanoseconds."); const timespec ts{0, 0}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0U); + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0ns); } TEST_F(TimeConversionTest, ConvertToNanoSec_SecondsOnly_ReturnsSecondsInNanoSec) @@ -60,7 +59,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_SecondsOnly_ReturnsSecondsInNanoSec) "This test verifies that a timespec containing only whole seconds is converted to the equivalent " "number of nanoseconds."); const timespec ts{2, 0}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 2U * static_cast(TimeConversion::k_nanoSecInSec)); + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 2s); } TEST_F(TimeConversionTest, ConvertToNanoSec_NanoSecondsOnly_ReturnsNanoSeconds) @@ -68,7 +67,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_NanoSecondsOnly_ReturnsNanoSeconds) RecordProperty( "Description", "This test verifies that a timespec containing only a nanosecond part is returned unchanged."); const timespec ts{0, 123456789}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 123456789U); + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 123456789ns); } TEST_F(TimeConversionTest, ConvertToNanoSec_SecondsAndNanoSeconds_ReturnsSum) @@ -78,7 +77,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_SecondsAndNanoSeconds_ReturnsSum) "This test verifies that the second and nanosecond parts of a timespec are correctly combined into " "a single nanosecond value."); const timespec ts{1, 500}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), static_cast(TimeConversion::k_nanoSecInSec) + 500U); + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 1s + 500ns); } TEST_F(TimeConversionTest, ConvertToNanoSec_NegativeSeconds_ReturnsZero) @@ -88,7 +87,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_NegativeSeconds_ReturnsZero) "This test verifies that a timespec with a negative second part is treated as invalid and yields " "zero."); const timespec ts{-1, 0}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0U); + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0ns); } TEST_F(TimeConversionTest, ConvertToNanoSec_NegativeNanoSeconds_ReturnsZero) @@ -98,7 +97,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_NegativeNanoSeconds_ReturnsZero) "This test verifies that a timespec with a negative nanosecond part is treated as invalid and " "yields zero."); const timespec ts{1, -1}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0U); + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0ns); } TEST_F(TimeConversionTest, ConvertToNanoSec_SecondsAboveMax_ReturnsZero) @@ -108,9 +107,9 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_SecondsAboveMax_ReturnsZero) "This test verifies that a timespec whose second part exceeds the representable range is treated as " "invalid and yields zero."); // k_maxSeconds is the last representable value, so one above it must be rejected. - ASSERT_LT(k_maxSeconds, static_cast(std::numeric_limits::max())); - const timespec ts{static_cast(k_maxSeconds + 1U), 0}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0U); + ASSERT_LT(k_maxSeconds, static_cast(std::numeric_limits::max())); + const timespec ts{(k_maxSeconds + 1s).count(), 0}; + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0ns); } TEST_F(TimeConversionTest, ConvertToNanoSec_MaxRepresentableValue_ReturnsMax) @@ -118,19 +117,19 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_MaxRepresentableValue_ReturnsMax) RecordProperty( "Description", "This test verifies that the largest representable timespec is converted to the maximum " - "NanoSecondType value without overflow."); - const timespec ts{static_cast(k_maxSeconds), static_cast(k_maxRemainderNanoSec)}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), std::numeric_limits::max()); + "nanoseconds value without overflow."); + const timespec ts{k_maxSeconds.count(), k_maxRemainderNanoSec.count()}; + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), std::numeric_limits::max()); } TEST_F(TimeConversionTest, ConvertToNanoSec_NanoSecondOverflow_ReturnsZero) { RecordProperty( "Description", - "This test verifies that a timespec whose nanosecond part would overflow NanoSecondType when added " + "This test verifies that a timespec whose nanosecond part would overflow nanoseconds when added " "to the seconds is treated as invalid and yields zero."); - const timespec ts{static_cast(k_maxSeconds), static_cast(k_maxRemainderNanoSec) + 1}; - ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0U); + const timespec ts{k_maxSeconds.count(), k_maxRemainderNanoSec.count() + 1}; + ASSERT_EQ(TimeConversion::convertToNanoSec(ts), 0ns); } // -------------------------------------------------------------------------- @@ -140,7 +139,7 @@ TEST_F(TimeConversionTest, ConvertToNanoSec_NanoSecondOverflow_ReturnsZero) TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_Zero_ReturnsZero) { RecordProperty("Description", "This test verifies that zero milliseconds is converted to zero nanoseconds."); - ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(0.0), 0U); + ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(0ms), 0ns); } TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_WholeMillis_ReturnsNanoSeconds) @@ -149,45 +148,23 @@ TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_WholeMillis_ReturnsNanoSecon "Description", "This test verifies that a whole number of milliseconds is converted to the equivalent number of " "nanoseconds."); - ASSERT_EQ( - TimeConversion::convertMilliSecToNanoSec(1.0), - static_cast(TimeConversion::k_nanoSecInMilliSec)); -} - -TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_FractionalMillis_ReturnsNanoSeconds) -{ - RecordProperty( - "Description", - "This test verifies that a fractional millisecond value is converted to the corresponding " - "nanosecond value."); - ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(1.5), 1500000U); -} - -TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_SubNanoSecond_TruncatesToZero) -{ - RecordProperty( - "Description", - "This test verifies that a positive millisecond value smaller than one nanosecond is truncated to " - "zero."); - // 0.0000001 ms * 1e6 = 0.1 ns, which truncates to 0. - ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(0.0000001), 0U); + ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(1ms), std::chrono::duration_cast(1ms)); } TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_Negative_ReturnsZero) { RecordProperty("Description", "This test verifies that a negative millisecond value is clamped to zero."); - ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(-1.0), 0U); + ASSERT_EQ(TimeConversion::convertMilliSecToNanoSec(-1ms), 0ms); } TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_Overflow_ReturnsMax) { RecordProperty( "Description", - "This test verifies that a millisecond value large enough to overflow NanoSecondType is clamped to " + "This test verifies that a millisecond value large enough to overflow nanoseconds is clamped to " "the maximum representable value."); ASSERT_EQ( - TimeConversion::convertMilliSecToNanoSec(std::numeric_limits::max()), - std::numeric_limits::max()); + TimeConversion::convertMilliSecToNanoSec(std::chrono::milliseconds::max()), std::chrono::nanoseconds::max()); } // -------------------------------------------------------------------------- @@ -197,7 +174,7 @@ TEST_F(TimeConversionTest, ConvertMilliSecToNanoSec_Overflow_ReturnsMax) TEST_F(TimeConversionTest, ConvertNanoSecToMilliSec_Zero_ReturnsZero) { RecordProperty("Description", "This test verifies that zero nanoseconds is converted to zero milliseconds."); - ASSERT_DOUBLE_EQ(TimeConversion::convertNanoSecToMilliSec(0U), 0.0); + ASSERT_EQ(TimeConversion::convertNanoSecToMilliSec(0ns), 0ms); } TEST_F(TimeConversionTest, ConvertNanoSecToMilliSec_WholeMilli_ReturnsMilliSeconds) @@ -206,18 +183,14 @@ TEST_F(TimeConversionTest, ConvertNanoSecToMilliSec_WholeMilli_ReturnsMilliSecon "Description", "This test verifies that a nanosecond value equal to one millisecond is converted to 1.0 " "milliseconds."); - ASSERT_DOUBLE_EQ( - TimeConversion::convertNanoSecToMilliSec(static_cast(TimeConversion::k_nanoSecInMilliSec)), - 1.0); + ASSERT_EQ(TimeConversion::convertNanoSecToMilliSec(1ms), 1ms); } TEST_F(TimeConversionTest, ConvertNanoSecToMilliSec_FractionalMilli_ReturnsMilliSeconds) { RecordProperty( - "Description", - "This test verifies that a nanosecond value between millisecond boundaries is converted to a " - "fractional millisecond value."); - ASSERT_DOUBLE_EQ(TimeConversion::convertNanoSecToMilliSec(1500000U), 1.5); + "Description", "This test verifies that a nanosecond value between millisecond boundaries is truncated"); + ASSERT_EQ(TimeConversion::convertNanoSecToMilliSec(1ms + 500000ns), 1ms); } TEST_F(TimeConversionTest, ConvertNanoSecToMilliSec_RoundTrip_PreservesValue) @@ -226,9 +199,9 @@ TEST_F(TimeConversionTest, ConvertNanoSecToMilliSec_RoundTrip_PreservesValue) "Description", "This test verifies that converting milliseconds to nanoseconds and back yields the original " "millisecond value."); - const double milliSec{42.0}; - const NanoSecondType nanoSec{TimeConversion::convertMilliSecToNanoSec(milliSec)}; - ASSERT_DOUBLE_EQ(TimeConversion::convertNanoSecToMilliSec(nanoSec), milliSec); + const milliseconds milliSec{42}; + const nanoseconds nanoSec{TimeConversion::convertMilliSecToNanoSec(milliSec)}; + ASSERT_EQ(TimeConversion::convertNanoSecToMilliSec(nanoSec), milliSec); } } // namespace diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.cpp index c7188bf9e0..24952d04b3 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.cpp @@ -12,39 +12,25 @@ ********************************************************************************/ #include "score/mw/launch_manager/alive_monitor/details/timers/Timers_OsClock.hpp" +#include "score/mw/launch_manager/alive_monitor/details/timers/TimeConversion.hpp" /* RULECHECKER_comment(0, 4, {check_include_time}, "Monotonic clock is needed from this header.\ other clocks and time format is not used.", true_no_defect) */ #include #include -#include - -#include "score/mw/launch_manager/alive_monitor/details/timers/TimeConversion.hpp" namespace score::mw::lifecycle::internal::saf::timers { -NanoSecondType OsClock::getMonotonicSystemClock(void) noexcept(true) +std::chrono::nanoseconds OsClock::getMonotonicSystemClock(void) noexcept(true) { timespec systemClock = {}; // Result (0=error, >0=the system clock in ns) - NanoSecondType result{0U}; + std::chrono::nanoseconds result{0U}; if (clock_gettime(CLOCK_MONOTONIC, &systemClock) == 0) { - // Calculate max number of seconds which can be stored in 64 bit unsigned integer - static constexpr NanoSecondType timeMaxSecond{ - std::numeric_limits::max() / TimeConversion::k_nanoSecInSec}; - if (static_cast(systemClock.tv_sec) <= timeMaxSecond) - { - NanoSecondType timeNanoSecPart1{ - static_cast(systemClock.tv_sec) * TimeConversion::k_nanoSecInSec}; - if ((std::numeric_limits::max() - timeNanoSecPart1) >= - static_cast(systemClock.tv_nsec)) - { - result = timeNanoSecPart1 + static_cast(systemClock.tv_nsec); - } - } + result = TimeConversion::convertToNanoSec(systemClock); } return result; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.hpp index f838f47d66..978961d4f8 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/timers/Timers_OsClock.hpp @@ -14,16 +14,10 @@ #ifndef TIMERS_OSCLOCK_HPP_INCLUDED #define TIMERS_OSCLOCK_HPP_INCLUDED -#include - +#include namespace score::mw::lifecycle::internal::saf::timers { -/// Special type for storing nanoseconds. -// NOTE: It is only an alias for uint64_t to make is visible that the value has the physical unit nanoseconds! -// That means that the macros UINT64_MIN and UINT64_MAX can be used if needed. -using NanoSecondType = uint64_t; - /// Operating system clock interface /// The OsClock class provides methods to interact with the operating system /// specific clock interfaces. @@ -44,7 +38,7 @@ class OsClock /// Get monotonic increasing system Clock /// @return System clock in nanoseconds or error indicator. /// @retval 0 in case of an error. - static NanoSecondType getMonotonicSystemClock(void) noexcept(true); + static std::chrono::nanoseconds getMonotonicSystemClock(void) noexcept(true); }; } // namespace score::mw::lifecycle::internal::saf::timers