Skip to content

Commit

Permalink
iox-eclipse-iceoryx#161 executionCounter for timer
Browse files Browse the repository at this point in the history
Signed-off-by: Kroenke Dietrich (CC-AD/ESW1) <Dietrich.Kroenke2@de.bosch.com>
  • Loading branch information
sculpordwarf authored and dkroenke committed Jul 29, 2020
1 parent 2404e97 commit 451df11
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class Timer
std::atomic<bool> m_inUse{false};
std::atomic<bool> m_isTimerActive{false};
std::atomic<uint64_t> m_cycle{0u};
uint64_t m_callbackExecutionCycle{0u};
TimerType m_timerType{TimerType::HARD_TIMER};

OsTimer* m_timer{nullptr};
Expand Down
23 changes: 20 additions & 3 deletions iceoryx_utils/source/posix_wrapper/timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,20 @@ void Timer::OsTimer::executeCallback(const uint64_t currentCycle) noexcept
auto& handle = OsTimer::s_callbackHandlePool[m_callbackHandleIndex];
uint64_t nextCycle = currentCycle;

// if a callbackHelper is interrupted before acquiring the accessMutex
// and continues after another thread executing callbackHelper as finished
// executeCallback and returns then m_callback() is called one more time
// then necessary.
// to avoid this executeCallback sets after every callback
// m_callbackExecutionCycle = m_cycle (current value is stored in nextCycle). if the
// interrupted thread then wins and acquires the lock the currentCycle is
// smaller then m_callbackExecutionCycle since the callback was already called by
// the previous thread
if (handle.m_timerType == TimerType::ASAP_TIMER && currentCycle <= handle.m_callbackExecutionCycle)
{
return;
}

// we are using compare exchange to gain a behavior where the missed
// timer callbacks do not accumulate. lets say the callback was triggered
// 5 times till the last callback fired then we do not want to run the
Expand All @@ -234,7 +248,8 @@ void Timer::OsTimer::executeCallback(const uint64_t currentCycle) noexcept
do
{
m_callback();
} while (handle.m_isTimerActive
handle.m_callbackExecutionCycle = nextCycle;
} while (handle.m_isTimerActive.load(std::memory_order_relaxed)
&& !handle.m_cycle.compare_exchange_strong(
nextCycle, nextCycle, std::memory_order_relaxed, std::memory_order_relaxed));
}
Expand Down Expand Up @@ -274,16 +289,18 @@ cxx::expected<TimerError> Timer::OsTimer::start(const RunMode runMode, const Tim
auto& handle = OsTimer::s_callbackHandlePool[m_callbackHandleIndex];

handle.m_timerType = timerType;
handle.m_cycle.store(0u, std::memory_order_relaxed);
handle.m_callbackExecutionCycle = 0u;
handle.m_isTimerActive.store(true, std::memory_order_relaxed);

return cxx::success<void>();
}

cxx::expected<TimerError> Timer::OsTimer::stop() noexcept
{
auto& handle = OsTimer::s_callbackHandlePool[m_callbackHandleIndex];
// Signal callbackHelper() that no callbacks shall be executed anymore
auto wasActive =
OsTimer::s_callbackHandlePool[m_callbackHandleIndex].m_isTimerActive.exchange(false, std::memory_order_relaxed);
auto wasActive = handle.m_isTimerActive.exchange(false, std::memory_order_relaxed);

if (!wasActive)
{
Expand Down

0 comments on commit 451df11

Please sign in to comment.