From 8fd46dde184d0288601b0fd64a8b11d99c90e829 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 19 Aug 2020 14:04:41 -0700 Subject: [PATCH] [time-ticker] adding 'TimeTicker' class (#5379) This commit adds `TimeTicker` class which emits periodic ticks (with one second period interval) to a set of registered tick receiver modules. The `TimeTicker` would invoke `HandleTimeTick()` method periodically on the registered receiver objects. The `TimeTicker` model helps simplify the implementation of many modules (such as `MeshForwarder`, `MleRoutuer`, `AddressResolver`, `Ip6`, `DuaManager`, etc) which require periodic update/check of some state (avoid each class using its own timer). --- Android.mk | 1 + src/core/BUILD.gn | 2 + src/core/CMakeLists.txt | 1 + src/core/Makefile.am | 2 + src/core/common/instance.cpp | 1 + src/core/common/instance.hpp | 13 ++- src/core/common/time_ticker.cpp | 127 ++++++++++++++++++++++++ src/core/common/time_ticker.hpp | 131 +++++++++++++++++++++++++ src/core/net/ip6.cpp | 19 +--- src/core/net/ip6.hpp | 12 +-- src/core/thread/address_resolver.cpp | 30 ++---- src/core/thread/address_resolver.hpp | 8 +- src/core/thread/dua_manager.cpp | 21 ++-- src/core/thread/dua_manager.hpp | 12 +-- src/core/thread/mesh_forwarder.cpp | 26 ++--- src/core/thread/mesh_forwarder.hpp | 12 +-- src/core/thread/mesh_forwarder_ftd.cpp | 17 +--- src/core/thread/mle_router.cpp | 22 ++--- src/core/thread/mle_router.hpp | 6 +- src/core/thread/mlr_manager.cpp | 17 ++-- src/core/thread/mlr_manager.hpp | 20 ++-- src/core/thread/router_table.cpp | 2 +- src/core/thread/router_table.hpp | 2 +- src/core/utils/child_supervision.cpp | 23 +---- src/core/utils/child_supervision.hpp | 14 +-- 25 files changed, 370 insertions(+), 171 deletions(-) create mode 100644 src/core/common/time_ticker.cpp create mode 100644 src/core/common/time_ticker.hpp diff --git a/Android.mk b/Android.mk index e58662b22..8a7ce8519 100644 --- a/Android.mk +++ b/Android.mk @@ -191,6 +191,7 @@ LOCAL_SRC_FILES := \ src/core/common/settings.cpp \ src/core/common/string.cpp \ src/core/common/tasklet.cpp \ + src/core/common/time_ticker.cpp \ src/core/common/timer.cpp \ src/core/common/tlvs.cpp \ src/core/common/trickle_timer.cpp \ diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 53d7f31d7..866722c26 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -364,6 +364,8 @@ openthread_core_files = [ "common/tasklet.cpp", "common/tasklet.hpp", "common/time.hpp", + "common/time_ticker.cpp", + "common/time_ticker.hpp", "common/timer.cpp", "common/timer.hpp", "common/tlvs.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 94ccfcf21..f5dc4dfe1 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -117,6 +117,7 @@ set(COMMON_SOURCES common/settings.cpp common/string.cpp common/tasklet.cpp + common/time_ticker.cpp common/timer.cpp common/tlvs.cpp common/trickle_timer.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index f473507ab..41cfccbeb 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -159,6 +159,7 @@ SOURCES_COMMON = \ common/settings.cpp \ common/string.cpp \ common/tasklet.cpp \ + common/time_ticker.cpp \ common/timer.cpp \ common/tlvs.cpp \ common/trickle_timer.cpp \ @@ -349,6 +350,7 @@ HEADERS_COMMON = \ common/string.hpp \ common/tasklet.hpp \ common/time.hpp \ + common/time_ticker.hpp \ common/timer.hpp \ common/tlvs.hpp \ common/trickle_timer.hpp \ diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index 550423d8e..fd41269c5 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -74,6 +74,7 @@ Instance::Instance(void) , mRadio(*this) #if OPENTHREAD_MTD || OPENTHREAD_FTD , mNotifier(*this) + , mTimeTicker(*this) , mSettings(*this) , mSettingsDriver(*this) , mMessagePool(*this) diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index eb15e5f73..0be241a1c 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -49,6 +49,7 @@ #include "common/non_copyable.hpp" #include "common/random_manager.hpp" #include "common/tasklet.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "diags/factory_diags.hpp" #include "radio/radio.hpp" @@ -343,10 +344,11 @@ private: Radio mRadio; #if OPENTHREAD_MTD || OPENTHREAD_FTD - // Notifier, Settings, and MessagePool are initialized before - // other member variables since other classes/objects from their - // constructor may use them. + // Notifier, TimeTicker, Settings, and MessagePool are initialized + // before other member variables since other classes/objects from + // their constructor may use them. Notifier mNotifier; + TimeTicker mTimeTicker; Settings mSettings; SettingsDriver mSettingsDriver; MessagePool mMessagePool; @@ -413,6 +415,11 @@ template <> inline Notifier &Instance::Get(void) return mNotifier; } +template <> inline TimeTicker &Instance::Get(void) +{ + return mTimeTicker; +} + template <> inline Settings &Instance::Get(void) { return mSettings; diff --git a/src/core/common/time_ticker.cpp b/src/core/common/time_ticker.cpp new file mode 100644 index 000000000..dfe2deb62 --- /dev/null +++ b/src/core/common/time_ticker.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements a time ticker. + */ + +#include "time_ticker.hpp" + +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" +#include "common/random.hpp" +#include "thread/mle_router.hpp" + +namespace ot { + +TimeTicker::TimeTicker(Instance &aInstance) + : InstanceLocator(aInstance) + , mReceivers(0) + , mTimer(aInstance, HandleTimer, this) +{ +} + +void TimeTicker::RegisterReceiver(Receiver aReceiver) +{ + mReceivers |= Mask(aReceiver); + + if (!mTimer.IsRunning()) + { + mTimer.Start(Random::NonCrypto::GetUint32InRange(0, kTickInterval + 1)); + } +} + +void TimeTicker::UnregisterReceiver(Receiver aReceiver) +{ + mReceivers &= ~Mask(aReceiver); + + if (mReceivers == 0) + { + mTimer.Stop(); + } +} + +void TimeTicker::HandleTimer(Timer &aTimer) +{ + aTimer.GetOwner().HandleTimer(); +} + +void TimeTicker::HandleTimer(void) +{ + mTimer.FireAt(mTimer.GetFireTime() + Random::NonCrypto::AddJitter(kTickInterval, kRestartJitter)); + + if (mReceivers & Mask(kMeshForwarder)) + { + Get().HandleTimeTick(); + } + +#if OPENTHREAD_FTD + if (mReceivers & Mask(kMleRouter)) + { + Get().HandleTimeTick(); + } + + if (mReceivers & Mask(kAddressResolver)) + { + Get().HandleTimeTick(); + } + +#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE + if (mReceivers & Mask(kChildSupervisor)) + { + Get().HandleTimeTick(); + } +#endif +#endif // OPENTHREAD_FTD + +#if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE + if (mReceivers & Mask(kIp6FragmentReassembler)) + { + Get().HandleTimeTick(); + } +#endif + +#if OPENTHREAD_CONFIG_DUA_ENABLE || OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE + if (mReceivers & Mask(kDuaManager)) + { + Get().HandleTimeTick(); + } +#endif + +#if OPENTHREAD_CONFIG_MLR_ENABLE || OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE + if (mReceivers & Mask(kMlrManager)) + { + Get().HandleTimeTick(); + } +#endif +} + +} // namespace ot diff --git a/src/core/common/time_ticker.hpp b/src/core/common/time_ticker.hpp new file mode 100644 index 000000000..ebe0ca1fb --- /dev/null +++ b/src/core/common/time_ticker.hpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for a time ticker. + */ + +#ifndef TIME_TICKER_HPP_ +#define TIME_TICKER_HPP_ + +#include "openthread-core-config.h" + +#include + +#include "common/locator.hpp" +#include "common/non_copyable.hpp" +#include "common/time.hpp" +#include "common/timer.hpp" + +namespace ot { + +/** + * This class represents a time ticker. + * + * The time ticker emits periodic ticks (with 1 second period interval) to a set of registered tick receiver modules. + * The tick receivers (OpenThread objects) are identified by the `Receiver` enumeration. The receiver objects + * must provide `HandleTimeTick()` method which would be invoked by `TimeTicker` periodically. + * + */ +class TimeTicker : public InstanceLocator, private NonCopyable +{ +public: + /** + * This enumeration represents time tick receivers. + * + * This enumeration contains the list of all OpenThread modules that can be registered as time tick receivers. + * + */ + enum Receiver : uint8_t + { + kMeshForwarder, ///< `MeshForwarder` + kMleRouter, ///< `Mle::MleRouter` + kAddressResolver, ///< `AddressResolver` + kChildSupervisor, ///< `Utils::ChildSupervisor` + kIp6FragmentReassembler, ///< `Ip6::Ip6` (handling of fragmented messages) + kDuaManager, ///< `DuaManager` + kMlrManager, ///< `MlrManager` + + kNumReceievrs, ///< Number of receivers. + }; + + /** + * This constructor initializes the `TimeTicker` instance. + * + */ + TimeTicker(Instance &aInstance); + + /** + * This method registers a receiver with `TimeTicker` to receive periodic ticks. + * + * @param[in] aReceiver A tick receiver identifier. + * + */ + void RegisterReceiver(Receiver aReceiver); + + /** + * This method unregisters a receiver with `TimeTicker` to receive periodic ticks. + * + * @param[in] aReceiver A tick receiver identifier. + * + */ + void UnregisterReceiver(Receiver aReceiver); + + /** + * This method indicates whether a receiver is registered with `TimeTicker` to receive periodic ticks. + * + * @param[in] aReceiver A tick receiver identifier. + * + * @retval TRUE If @p aReceiver is registered with `TimeTicker`. + * @retval FALSE If @p aReceiver is not registered with `TimeTicker`. + * + */ + bool IsReceiverRegistered(Receiver aReceiver) const { return (mReceivers & Mask(aReceiver)) != 0; } + +private: + enum : uint32_t + { + kTickInterval = 1000, // in msec. + kRestartJitter = 4, // in msec, jitter added when restarting the timer [-4,+4] ms. + }; + + constexpr static uint32_t Mask(Receiver aReceiver) { return static_cast(1U) << aReceiver; } + + static void HandleTimer(Timer &aTimer); + void HandleTimer(void); + + uint32_t mReceivers; + TimerMilli mTimer; + + static_assert(kNumReceievrs < sizeof(mReceivers) * CHAR_BIT, "Too many `Receiver`s - does not fit in a bit mask"); +}; + +} // namespace ot + +#endif // TIMER_HPP_ diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 0fd12dbe5..7bfe7cef0 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -61,9 +61,6 @@ Ip6::Ip6(Instance &aInstance) , mIcmp(aInstance) , mUdp(aInstance) , mMpl(aInstance) -#if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE - , mTimer(aInstance, Ip6::HandleTimer, this) -#endif { } @@ -778,10 +775,7 @@ otError Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMess assertValue = aMessage.CopyTo(0, 0, aMessage.GetOffset(), *message); OT_ASSERT(assertValue == aMessage.GetOffset()); - if (!mTimer.IsRunning()) - { - mTimer.Start(kStateUpdatePeriod); - } + Get().RegisterReceiver(TimeTicker::kIp6FragmentReassembler); mReassemblyList.Enqueue(*message); @@ -850,18 +844,13 @@ void Ip6::CleanupFragmentationBuffer(void) } } -void Ip6::HandleTimer(Timer &aTimer) -{ - aTimer.GetOwner().HandleUpdateTimer(); -} - -void Ip6::HandleUpdateTimer(void) +void Ip6::HandleTimeTick(void) { UpdateReassemblyList(); - if (mReassemblyList.GetHead() != nullptr) + if (mReassemblyList.GetHead() == nullptr) { - mTimer.Start(kStateUpdatePeriod); + Get().UnregisterReceiver(TimeTicker::kIp6FragmentReassembler); } } diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index 4f66d2a92..e0af78ea7 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -45,6 +45,7 @@ #include "common/locator.hpp" #include "common/message.hpp" #include "common/non_copyable.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "net/icmp6.hpp" #include "net/ip6_address.hpp" @@ -102,6 +103,7 @@ using ot::Encoding::BigEndian::HostSwap32; class Ip6 : public InstanceLocator, private NonCopyable { friend class ot::Instance; + friend class ot::TimeTicker; friend class Mpl; public: @@ -361,11 +363,10 @@ private: otError FragmentDatagram(Message &aMessage, uint8_t aIpProto); otError HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost); #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE - void CleanupFragmentationBuffer(void); - void HandleUpdateTimer(void); - void UpdateReassemblyList(void); - void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode); - static void HandleTimer(Timer &aTimer); + void CleanupFragmentationBuffer(void); + void HandleTimeTick(void); + void UpdateReassemblyList(void); + void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode); #endif otError AddMplOption(Message &aMessage, Header &aHeader); otError AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); @@ -389,7 +390,6 @@ private: Mpl mMpl; #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE - TimerMilli mTimer; MessageQueue mReassemblyList; #endif }; diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index 71e0fbdb4..e638b2c5f 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -64,7 +64,6 @@ AddressResolver::AddressResolver(Instance &aInstance) , mQueryList() , mQueryRetryList() , mIcmpHandler(&AddressResolver::HandleIcmpReceive, this) - , mTimer(aInstance, AddressResolver::HandleTimer, this) { Get().AddResource(mAddressError); Get().AddResource(mAddressQuery); @@ -396,10 +395,7 @@ void AddressResolver::AddSnoopedCacheEntry(const Ip6::Address &aEid, Mac::ShortA entry->SetCanEvict(false); entry->SetTimeout(kSnoopBlockEvictionTimeout); - if (!mTimer.IsRunning()) - { - mTimer.Start(kStateUpdatePeriod); - } + Get().RegisterReceiver(TimeTicker::kAddressResolver); } else { @@ -546,10 +542,7 @@ otError AddressResolver::SendAddressQuery(const Ip6::Address &aEid) exit: - if (!mTimer.IsRunning()) - { - mTimer.Start(kStateUpdatePeriod); - } + Get().RegisterReceiver(TimeTicker::kAddressResolver); if (error != OT_ERROR_NONE && message != nullptr) { @@ -835,14 +828,9 @@ exit: } } -void AddressResolver::HandleTimer(Timer &aTimer) +void AddressResolver::HandleTimeTick(void) { - aTimer.GetOwner().HandleTimer(); -} - -void AddressResolver::HandleTimer(void) -{ - bool continueTimer = false; + bool continueRxingTicks = false; CacheEntry *prev; CacheEntry *entry; @@ -853,7 +841,7 @@ void AddressResolver::HandleTimer(void) continue; } - continueTimer = true; + continueRxingTicks = true; entry->DecrementTimeout(); if (entry->IsTimeoutZero()) @@ -869,7 +857,7 @@ void AddressResolver::HandleTimer(void) continue; } - continueTimer = true; + continueRxingTicks = true; entry->DecrementTimeout(); } @@ -879,7 +867,7 @@ void AddressResolver::HandleTimer(void) { OT_ASSERT(!entry->IsTimeoutZero()); - continueTimer = true; + continueRxingTicks = true; entry->DecrementTimeout(); if (entry->IsTimeoutZero()) @@ -916,9 +904,9 @@ void AddressResolver::HandleTimer(void) } } - if (continueTimer) + if (!continueRxingTicks) { - mTimer.Start(kStateUpdatePeriod); + Get().UnregisterReceiver(TimeTicker::kAddressResolver); } } diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp index 881dd8b29..369614502 100644 --- a/src/core/thread/address_resolver.hpp +++ b/src/core/thread/address_resolver.hpp @@ -39,6 +39,7 @@ #include "coap/coap.hpp" #include "common/linked_list.hpp" #include "common/locator.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "mac/mac.hpp" #include "net/icmp6.hpp" @@ -62,6 +63,8 @@ namespace ot { */ class AddressResolver : public InstanceLocator { + friend class TimeTicker; + public: /** * This type represents an iterator used for iterating through the EID cache table entries. @@ -180,7 +183,6 @@ private: kAddressQueryInitialRetryDelay = OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_INITIAL_RETRY_DELAY, // in seconds kAddressQueryMaxRetryDelay = OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY, // in seconds kSnoopBlockEvictionTimeout = OPENTHREAD_CONFIG_TMF_SNOOP_CACHE_ENTRY_TIMEOUT, // in seconds - kStateUpdatePeriod = 1000u, // in milliseconds kIteratorListIndex = 0, kIteratorEntryIndex = 1, }; @@ -307,8 +309,7 @@ private: const Ip6::MessageInfo & aMessageInfo, const Ip6::Icmp::Header &aIcmpHeader); - static void HandleTimer(Timer &aTimer); - void HandleTimer(void); + void HandleTimeTick(void); void LogCacheEntryChange(EntryChange aChange, Reason aReason, @@ -330,7 +331,6 @@ private: CacheEntryList mQueryRetryList; Ip6::Icmp::Handler mIcmpHandler; - TimerMilli mTimer; }; /** diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp index 95b195940..4a5bcece8 100644 --- a/src/core/thread/dua_manager.cpp +++ b/src/core/thread/dua_manager.cpp @@ -51,7 +51,6 @@ namespace ot { DuaManager::DuaManager(Instance &aInstance) : InstanceLocator(aInstance) - , mTimer(aInstance, DuaManager::HandleTimer, this) , mRegistrationTask(aInstance, DuaManager::HandleRegistrationTask, this) , mDuaNotification(OT_URI_PATH_DUA_REGISTRATION_NOTIFY, &DuaManager::HandleDuaNotification, this) , mIsDuaPending(false) @@ -256,7 +255,7 @@ void DuaManager::UpdateRegistrationDelay(uint8_t aDelay) mDelay.mFields.mRegistrationDelay = aDelay; otLogDebgDua("update regdelay %d", mDelay.mFields.mRegistrationDelay); - ScheduleTimer(); + UpdateTimeTickerRegistration(); } } #endif @@ -273,7 +272,7 @@ void DuaManager::UpdateReregistrationDelay(void) if (mDelay.mFields.mReregistrationDelay == 0 || mDelay.mFields.mReregistrationDelay > delay) { mDelay.mFields.mReregistrationDelay = delay; - ScheduleTimer(); + UpdateTimeTickerRegistration(); otLogDebgDua("update reregdelay %d", mDelay.mFields.mReregistrationDelay); } @@ -288,7 +287,7 @@ void DuaManager::UpdateCheckDelay(uint8_t aDelay) mDelay.mFields.mCheckDelay = aDelay; otLogDebgDua("update checkdelay %d", mDelay.mFields.mCheckDelay); - ScheduleTimer(); + UpdateTimeTickerRegistration(); } } @@ -333,7 +332,7 @@ void DuaManager::HandleBackboneRouterPrimaryUpdate(BackboneRouter::Leader::State } } -void DuaManager::HandleTimer(void) +void DuaManager::HandleTimeTick(void) { bool attempt = false; @@ -377,18 +376,18 @@ void DuaManager::HandleTimer(void) mRegistrationTask.Post(); } - ScheduleTimer(); + UpdateTimeTickerRegistration(); } -void DuaManager::ScheduleTimer(void) +void DuaManager::UpdateTimeTickerRegistration(void) { if (mDelay.mValue == 0) { - mTimer.Stop(); + Get().UnregisterReceiver(TimeTicker::kDuaManager); } - else if (!mTimer.IsRunning()) + else { - mTimer.Start(kStateUpdatePeriod); + Get().RegisterReceiver(TimeTicker::kDuaManager); } } @@ -641,7 +640,7 @@ otError DuaManager::ProcessDuaResponse(Coap::Message &aMessage) #endif // OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE exit: - ScheduleTimer(); + UpdateTimeTickerRegistration(); return error; } diff --git a/src/core/thread/dua_manager.hpp b/src/core/thread/dua_manager.hpp index cd3950d46..2ff92532d 100644 --- a/src/core/thread/dua_manager.hpp +++ b/src/core/thread/dua_manager.hpp @@ -45,6 +45,7 @@ #include "common/notifier.hpp" #include "common/tasklet.hpp" #include "common/time.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "net/netif.hpp" #include "thread/thread_tlvs.hpp" @@ -73,6 +74,7 @@ namespace ot { class DuaManager : public InstanceLocator { friend class ot::Notifier; + friend class ot::TimeTicker; public: /** @@ -160,8 +162,7 @@ public: private: enum { - kNewRouterRegistrationDelay = 5, ///< Delay (in seconds) for waiting link establishment for a new Router. - kStateUpdatePeriod = 1000, ///< 1000ms period (i.e. 1s) + kNewRouterRegistrationDelay = 5, ///< Delay (in seconds) for waiting link establishment for a new Router. }; #if OPENTHREAD_CONFIG_DUA_ENABLE @@ -179,13 +180,11 @@ private: void HandleNotifierEvents(Events aEvents); - static void HandleTimer(Timer &aTimer) { aTimer.GetOwner().HandleTimer(); } - - void HandleTimer(void); + void HandleTimeTick(void); static void HandleRegistrationTask(Tasklet &aTasklet) { aTasklet.GetOwner().PerformNextRegistration(); } - void ScheduleTimer(void); + void UpdateTimeTickerRegistration(void); static void HandleDuaResponse(void * aContext, otMessage * aMessage, @@ -211,7 +210,6 @@ private: void UpdateReregistrationDelay(void); void UpdateCheckDelay(uint8_t aDelay); - TimerMilli mTimer; Tasklet mRegistrationTask; Coap::Resource mDuaNotification; diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 93a15d951..dff16a62a 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -41,6 +41,7 @@ #include "common/logging.hpp" #include "common/message.hpp" #include "common/random.hpp" +#include "common/time_ticker.hpp" #include "net/ip6.hpp" #include "net/ip6_filter.hpp" #include "net/netif.hpp" @@ -79,7 +80,6 @@ void ThreadLinkInfo::SetFrom(const Mac::RxFrame &aFrame) MeshForwarder::MeshForwarder(Instance &aInstance) : InstanceLocator(aInstance) - , mUpdateTimer(aInstance, MeshForwarder::HandleUpdateTimer, this) , mMessageNextOffset(0) , mSendMessage(nullptr) , mMeshSource() @@ -123,7 +123,7 @@ void MeshForwarder::Stop(void) VerifyOrExit(mEnabled, OT_NOOP); mDataPollSender.StopPolling(); - mUpdateTimer.Stop(); + Get().UnregisterReceiver(TimeTicker::kMeshForwarder); Get().Stop(); while ((message = mSendQueue.GetHead()) != nullptr) @@ -1009,10 +1009,7 @@ void MeshForwarder::HandleFragment(const uint8_t * aFrame, mReassemblyList.Enqueue(*message); - if (!mUpdateTimer.IsRunning()) - { - mUpdateTimer.Start(kStateUpdatePeriod); - } + Get().RegisterReceiver(TimeTicker::kMeshForwarder); } else // Received frame is a "next fragment". { @@ -1091,22 +1088,19 @@ void MeshForwarder::ClearReassemblyList(void) } } -void MeshForwarder::HandleUpdateTimer(Timer &aTimer) +void MeshForwarder::HandleTimeTick(void) { - aTimer.GetOwner().HandleUpdateTimer(); -} - -void MeshForwarder::HandleUpdateTimer(void) -{ - bool shouldRun = false; + bool contineRxingTicks = false; #if OPENTHREAD_FTD - shouldRun = mFragmentPriorityList.UpdateOnTimeTick(); + contineRxingTicks = mFragmentPriorityList.UpdateOnTimeTick(); #endif - if (UpdateReassemblyList() || shouldRun) + contineRxingTicks = UpdateReassemblyList() || contineRxingTicks; + + if (!contineRxingTicks) { - mUpdateTimer.Start(kStateUpdatePeriod); + Get().UnregisterReceiver(TimeTicker::kMeshForwarder); } } diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 4b07b8862..9888434e5 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -39,6 +39,7 @@ #include "common/clearable.hpp" #include "common/locator.hpp" #include "common/tasklet.hpp" +#include "common/time_ticker.hpp" #include "mac/channel_mask.hpp" #include "mac/data_poll_sender.hpp" #include "mac/mac.hpp" @@ -150,6 +151,7 @@ class MeshForwarder : public InstanceLocator friend class DataPollSender; friend class IndirectSender; friend class Mle::DiscoverScanner; + friend class TimeTicker; public: /** @@ -297,11 +299,6 @@ private: kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT, // Reassembly timeout (in seconds). }; - enum : uint32_t - { - kStateUpdatePeriod = 1000, // State update period in milliseconds. - }; - enum MessageAction ///< Defines the action parameter in `LogMessageInfo()` method. { kMessageReceive, ///< Indicates that the message was received. @@ -427,8 +424,7 @@ private: Neighbor *UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, otError aError, const Mac::Address &aMacDest); void HandleSentFrame(Mac::TxFrame &aFrame, otError aError); - static void HandleUpdateTimer(Timer &aTimer); - void HandleUpdateTimer(void); + void HandleTimeTick(void); static void ScheduleTransmissionTask(Tasklet &aTasklet); void ScheduleTransmissionTask(void); @@ -513,8 +509,6 @@ private: otLogLevel aLogLevel); #endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1) - TimerMilli mUpdateTimer; - PriorityQueue mSendQueue; MessageQueue mReassemblyList; uint16_t mFragTag; diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 5a0a23c98..82a77d779 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -741,7 +741,7 @@ exit: bool MeshForwarder::FragmentPriorityList::UpdateOnTimeTick(void) { - bool shouldRun = false; + bool contineRxingTicks = false; for (Entry &entry : mEntries) { @@ -751,12 +751,12 @@ bool MeshForwarder::FragmentPriorityList::UpdateOnTimeTick(void) if (!entry.IsExpired()) { - shouldRun = true; + contineRxingTicks = true; } } } - return shouldRun; + return contineRxingTicks; } void MeshForwarder::UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, @@ -772,15 +772,8 @@ void MeshForwarder::UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHead { VerifyOrExit(aFragmentHeader.GetDatagramOffset() == 0, OT_NOOP); - entry = mFragmentPriorityList.AllocateEntry(aSrcRloc16, aFragmentHeader.GetDatagramTag(), aPriority); - - VerifyOrExit(entry != nullptr, OT_NOOP); - - if (!mUpdateTimer.IsRunning()) - { - mUpdateTimer.Start(kStateUpdatePeriod); - } - + mFragmentPriorityList.AllocateEntry(aSrcRloc16, aFragmentHeader.GetDatagramTag(), aPriority); + Get().RegisterReceiver(TimeTicker::kMeshForwarder); ExitNow(); } diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index b01523008..4380ec83e 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -59,7 +59,6 @@ namespace Mle { MleRouter::MleRouter(Instance &aInstance) : Mle(aInstance) , mAdvertiseTimer(aInstance, MleRouter::HandleAdvertiseTimer, nullptr, this) - , mStateUpdateTimer(aInstance, MleRouter::HandleStateUpdateTimer, this) , mAddressSolicit(OT_URI_PATH_ADDRESS_SOLICIT, &MleRouter::HandleAddressSolicit, this) , mAddressRelease(OT_URI_PATH_ADDRESS_RELEASE, &MleRouter::HandleAddressRelease, this) , mChildTable(aInstance) @@ -164,7 +163,7 @@ otError MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus) { case kRoleDetached: SuccessOrExit(error = SendLinkRequest(nullptr)); - mStateUpdateTimer.Start(kStateUpdatePeriod); + Get().RegisterReceiver(TimeTicker::kMleRouter); break; case kRoleChild: @@ -231,7 +230,7 @@ void MleRouter::HandleDetachStart(void) { mRouterTable.ClearNeighbors(); StopLeader(); - mStateUpdateTimer.Stop(); + Get().UnregisterReceiver(TimeTicker::kMleRouter); } void MleRouter::HandleChildStart(AttachMode aMode) @@ -242,7 +241,7 @@ void MleRouter::HandleChildStart(AttachMode aMode) mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter); StopLeader(); - mStateUpdateTimer.Start(kStateUpdatePeriod); + Get().RegisterReceiver(TimeTicker::kMleRouter); if (mRouterEligible) { @@ -358,7 +357,7 @@ void MleRouter::SetStateLeader(uint16_t aRloc16) Get().SubscribeAllRoutersMulticast(); mPreviousPartitionIdRouter = mLeaderData.GetPartitionId(); - mStateUpdateTimer.Start(kStateUpdatePeriod); + Get().RegisterReceiver(TimeTicker::kMleRouter); Get().Start(); Get().StartLeader(); @@ -1710,18 +1709,11 @@ exit: } } -void MleRouter::HandleStateUpdateTimer(Timer &aTimer) -{ - aTimer.GetOwner().HandleStateUpdateTimer(); -} - -void MleRouter::HandleStateUpdateTimer(void) +void MleRouter::HandleTimeTick(void) { bool routerStateUpdate = false; - VerifyOrExit(IsFullThreadDevice(), OT_NOOP); - - mStateUpdateTimer.Start(kStateUpdatePeriod); + VerifyOrExit(IsFullThreadDevice(), Get().UnregisterReceiver(TimeTicker::kMleRouter)); if (mChallengeTimeout > 0) { @@ -1937,7 +1929,7 @@ void MleRouter::HandleStateUpdateTimer(void) } } - mRouterTable.ProcessTimerTick(); + mRouterTable.HandleTimeTick(); SynchronizeChildNetworkData(); diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 73040f2f7..93347cd8a 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -40,6 +40,7 @@ #include "coap/coap.hpp" #include "coap/coap_message.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "common/trickle_timer.hpp" #include "mac/mac_types.hpp" @@ -75,6 +76,7 @@ class MleRouter : public Mle { friend class Mle; friend class ot::Instance; + friend class ot::TimeTicker; public: /** @@ -647,11 +649,9 @@ private: static bool HandleAdvertiseTimer(TrickleTimer &aTimer); bool HandleAdvertiseTimer(void); - static void HandleStateUpdateTimer(Timer &aTimer); - void HandleStateUpdateTimer(void); + void HandleTimeTick(void); TrickleTimer mAdvertiseTimer; - TimerMilli mStateUpdateTimer; Coap::Resource mAddressSolicit; Coap::Resource mAddressRelease; diff --git a/src/core/thread/mlr_manager.cpp b/src/core/thread/mlr_manager.cpp index 4d7cad7cf..43e20b3cc 100644 --- a/src/core/thread/mlr_manager.cpp +++ b/src/core/thread/mlr_manager.cpp @@ -48,7 +48,6 @@ namespace ot { MlrManager::MlrManager(Instance &aInstance) : InstanceLocator(aInstance) - , mTimer(aInstance, MlrManager::HandleTimer, this) , mReregistrationDelay(0) , mSendDelay(0) , mMlrPending(false) @@ -222,20 +221,20 @@ void MlrManager::ScheduleSend(uint16_t aDelay) mSendDelay = aDelay; } - ResetTimer(); + UpdateTimeTickerRegistration(); exit: return; } -void MlrManager::ResetTimer(void) +void MlrManager::UpdateTimeTickerRegistration(void) { if (mSendDelay == 0 && mReregistrationDelay == 0) { - mTimer.Stop(); + Get().UnregisterReceiver(TimeTicker::kMlrManager); } - else if (!mTimer.IsRunning()) + else { - mTimer.Start(kTimerInterval); + Get().RegisterReceiver(TimeTicker::kMlrManager); } } @@ -411,7 +410,7 @@ exit: } } -void MlrManager::HandleTimer(void) +void MlrManager::HandleTimeTick(void) { if (mSendDelay > 0 && --mSendDelay == 0) { @@ -423,7 +422,7 @@ void MlrManager::HandleTimer(void) Reregister(); } - ResetTimer(); + UpdateTimeTickerRegistration(); } void MlrManager::Reregister(void) @@ -476,7 +475,7 @@ void MlrManager::UpdateReregistrationDelay(bool aRereg) } } - ResetTimer(); + UpdateTimeTickerRegistration(); otLogDebgMlr("MlrManager::UpdateReregistrationDelay: rereg=%d, needSendMlr=%d, ReregDelay=%lu", aRereg, needSendMlr, mReregistrationDelay); diff --git a/src/core/thread/mlr_manager.hpp b/src/core/thread/mlr_manager.hpp index 5130c825b..05c42ab78 100644 --- a/src/core/thread/mlr_manager.hpp +++ b/src/core/thread/mlr_manager.hpp @@ -42,6 +42,7 @@ #include "coap/coap_message.hpp" #include "common/locator.hpp" #include "common/notifier.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "net/netif.hpp" #include "thread/thread_tlvs.hpp" @@ -70,6 +71,7 @@ namespace ot { class MlrManager : public InstanceLocator { friend class ot::Notifier; + friend class ot::TimeTicker; public: /** @@ -106,11 +108,6 @@ public: #endif private: - enum - { - kTimerInterval = 1000, - }; - void HandleNotifierEvents(Events aEvents); void SendMulticastListenerRegistration(void); @@ -158,19 +155,16 @@ private: const Ip6::Address &aAddress); void ScheduleSend(uint16_t aDelay); - void ResetTimer(void); + void UpdateTimeTickerRegistration(void); void UpdateReregistrationDelay(bool aRereg); void Reregister(void); - - static void HandleTimer(Timer &aTimer) { aTimer.GetOwner().HandleTimer(); } - void HandleTimer(void); + void HandleTimeTick(void); void LogMulticastAddresses(void); - TimerMilli mTimer; - uint32_t mReregistrationDelay; - uint16_t mSendDelay; - bool mMlrPending : 1; + uint32_t mReregistrationDelay; + uint16_t mSendDelay; + bool mMlrPending : 1; }; } // namespace ot diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp index f1fc808e1..6c600f220 100644 --- a/src/core/thread/router_table.cpp +++ b/src/core/thread/router_table.cpp @@ -498,7 +498,7 @@ exit: return; } -void RouterTable::ProcessTimerTick(void) +void RouterTable::HandleTimeTick(void) { Mle::MleRouter &mle = Get(); diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp index 9ceb53635..62521e7c4 100644 --- a/src/core/thread/router_table.hpp +++ b/src/core/thread/router_table.hpp @@ -398,7 +398,7 @@ public: * This method updates the router table and must be called with a one second period. * */ - void ProcessTimerTick(void); + void HandleTimeTick(void); /** * This method enables range-based `for` loop iteration over all Router entries in the Router table. diff --git a/src/core/utils/child_supervision.cpp b/src/core/utils/child_supervision.cpp index 99202cae7..51989de2b 100644 --- a/src/core/utils/child_supervision.cpp +++ b/src/core/utils/child_supervision.cpp @@ -50,7 +50,6 @@ namespace Utils { ChildSupervisor::ChildSupervisor(Instance &aInstance) : InstanceLocator(aInstance) , mSupervisionInterval(kDefaultSupervisionInterval) - , mTimer(aInstance, ChildSupervisor::HandleTimer, this) { } @@ -110,15 +109,8 @@ void ChildSupervisor::UpdateOnSend(Child &aChild) aChild.ResetSecondsSinceLastSupervision(); } -void ChildSupervisor::HandleTimer(Timer &aTimer) +void ChildSupervisor::HandleTimeTick(void) { - aTimer.GetOwner().HandleTimer(); -} - -void ChildSupervisor::HandleTimer(void) -{ - VerifyOrExit(mSupervisionInterval != 0, OT_NOOP); - for (Child &child : Get().Iterate(Child::kInStateValid)) { child.IncrementSecondsSinceLastSupervision(); @@ -128,11 +120,6 @@ void ChildSupervisor::HandleTimer(void) SendMessage(child); } } - - mTimer.Start(kOneSecond); - -exit: - return; } void ChildSupervisor::CheckState(void) @@ -146,15 +133,15 @@ void ChildSupervisor::CheckState(void) shouldRun = ((mSupervisionInterval != 0) && !Get().IsDisabled() && Get().HasChildren(Child::kInStateValid)); - if (shouldRun && !mTimer.IsRunning()) + if (shouldRun && !Get().IsReceiverRegistered(TimeTicker::kChildSupervisor)) { - mTimer.Start(kOneSecond); + Get().RegisterReceiver(TimeTicker::kChildSupervisor); otLogInfoUtil("Starting Child Supervision"); } - if (!shouldRun && mTimer.IsRunning()) + if (!shouldRun && Get().IsReceiverRegistered(TimeTicker::kChildSupervisor)) { - mTimer.Stop(); + Get().UnregisterReceiver(TimeTicker::kChildSupervisor); otLogInfoUtil("Stopping Child Supervision"); } } diff --git a/src/core/utils/child_supervision.hpp b/src/core/utils/child_supervision.hpp index bb07bcccd..89ab4e048 100644 --- a/src/core/utils/child_supervision.hpp +++ b/src/core/utils/child_supervision.hpp @@ -42,6 +42,7 @@ #include "common/locator.hpp" #include "common/message.hpp" #include "common/notifier.hpp" +#include "common/time_ticker.hpp" #include "common/timer.hpp" #include "mac/mac_types.hpp" #include "thread/topology.hpp" @@ -91,6 +92,7 @@ namespace Utils { class ChildSupervisor : public InstanceLocator { friend class ot::Notifier; + friend class ot::TimeTicker; public: /** @@ -159,14 +161,12 @@ private: kOneSecond = 1000, // One second interval (in ms). }; - void SendMessage(Child &aChild); - void CheckState(void); - static void HandleTimer(Timer &aTimer); - void HandleTimer(void); - void HandleNotifierEvents(Events aEvents); + void SendMessage(Child &aChild); + void CheckState(void); + void HandleTimeTick(void); + void HandleNotifierEvents(Events aEvents); - uint16_t mSupervisionInterval; - TimerMilli mTimer; + uint16_t mSupervisionInterval; }; #else // #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE && OPENTHREAD_FTD