diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index fd9f78499..4bc921ceb 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -121,7 +121,7 @@ static otNetifAddress sAutoAddresses[8]; void Interpreter::Init(void) { sIp6->mIcmp.SetEchoReplyHandler(&HandleEchoResponse, NULL); - sPingTimer = new(&sPingTimerBuf) Timer(&HandlePingTimer, NULL); + sPingTimer = new(&sPingTimerBuf) Timer(sIp6->mTimerScheduler, &HandlePingTimer, NULL); sLength = 8; sCount = 1; sInterval = 1000; diff --git a/src/core/common/timer.cpp b/src/core/common/timer.cpp index eb64990d9..eebb9f423 100644 --- a/src/core/common/timer.cpp +++ b/src/core/common/timer.cpp @@ -33,21 +33,27 @@ #include #include +#include #include namespace Thread { -static Timer *sHead = NULL; -static Timer *sTail = NULL; +// FIXME: the otPlatAlarm callback should provide the context +static TimerScheduler *sTimerScheduler; + +TimerScheduler::TimerScheduler(void): + mHead(NULL) +{ + sTimerScheduler = this; +} void TimerScheduler::Add(Timer &aTimer) { Remove(aTimer); - if (sHead == NULL) + if (mHead == NULL) { - sHead = &aTimer; - sTail = &aTimer; + mHead = &aTimer; SetAlarm(); } else @@ -55,7 +61,7 @@ void TimerScheduler::Add(Timer &aTimer) Timer *prev = NULL; Timer *cur; - for (cur = sHead; cur; cur = cur->mNext) + for (cur = mHead; cur; cur = cur->mNext) { if (TimerCompare(aTimer, *cur)) { @@ -66,8 +72,8 @@ void TimerScheduler::Add(Timer &aTimer) } else { - aTimer.mNext = sHead; - sHead = &aTimer; + aTimer.mNext = mHead; + mHead = &aTimer; SetAlarm(); } @@ -79,56 +85,38 @@ void TimerScheduler::Add(Timer &aTimer) if (cur == NULL) { - sTail->mNext = &aTimer; - sTail = &aTimer; + prev->mNext = &aTimer; } } } void TimerScheduler::Remove(Timer &aTimer) { - VerifyOrExit(aTimer.mNext != NULL || sTail == &aTimer, ;); - - if (sHead == &aTimer) + if (mHead == &aTimer) { - sHead = aTimer.mNext; - - if (sTail == &aTimer) - { - sTail = NULL; - } - + mHead = aTimer.mNext; + aTimer.mNext = NULL; SetAlarm(); } else { - for (Timer *cur = sHead; cur; cur = cur->mNext) + for (Timer *cur = mHead; cur; cur = cur->mNext) { if (cur->mNext == &aTimer) { cur->mNext = aTimer.mNext; - - if (sTail == &aTimer) - { - sTail = cur; - } - + aTimer.mNext = NULL; break; } } } - - aTimer.mNext = NULL; - -exit: - return; } bool TimerScheduler::IsAdded(const Timer &aTimer) { bool rval = false; - for (Timer *cur = sHead; cur; cur = cur->mNext) + for (Timer *cur = mHead; cur; cur = cur->mNext) { if (cur == &aTimer) { @@ -145,16 +133,15 @@ void TimerScheduler::SetAlarm(void) uint32_t now = otPlatAlarmGetNow(); uint32_t elapsed; uint32_t remaining; - Timer *timer = sHead; - if (timer == NULL) + if (mHead == NULL) { otPlatAlarmStop(); } else { - elapsed = now - timer->mT0; - remaining = (timer->mDt > elapsed) ? timer->mDt - elapsed : 0; + elapsed = now - mHead->mT0; + remaining = (mHead->mDt > elapsed) ? mHead->mDt - elapsed : 0; otPlatAlarmStartAt(now, remaining); } @@ -162,14 +149,14 @@ void TimerScheduler::SetAlarm(void) extern "C" void otPlatAlarmFired(void) { - TimerScheduler::FireTimers(); + sTimerScheduler->FireTimers(); } void TimerScheduler::FireTimers(void) { uint32_t now = otPlatAlarmGetNow(); uint32_t elapsed; - Timer *timer = sHead; + Timer *timer = mHead; if (timer) { diff --git a/src/core/common/timer.hpp b/src/core/common/timer.hpp index a44066b50..735f14475 100644 --- a/src/core/common/timer.hpp +++ b/src/core/common/timer.hpp @@ -65,43 +65,49 @@ class TimerScheduler public: /** - * This static method adds a timer instance to the timer scheduler. + * This constructor initializes the object. + * + */ + TimerScheduler(void); + + /** + * This method adds a timer instance to the timer scheduler. * * @param[in] aTimer A reference to the timer instance. * */ - static void Add(Timer &aTimer); + void Add(Timer &aTimer); /** - * This static method removes a timer instance to the timer scheduler. + * This method removes a timer instance to the timer scheduler. * * @param[in] aTimer A reference to the timer instance. * */ - static void Remove(Timer &aTimer); + void Remove(Timer &aTimer); /** - * This static method returns whether or not the timer instance is already added. + * This method returns whether or not the timer instance is already added. * * @retval TRUE If the timer instance is already added. * @retval FALSE If the timer instance is not added. * */ - static bool IsAdded(const Timer &aTimer); + bool IsAdded(const Timer &aTimer); /** - * This static method processes all running timers. + * This method processes all running timers. * * @param[in] aContext A pointer to arbitrary context information. * */ - static void FireTimers(void); + void FireTimers(void); private: - static void SetAlarm(void); + void SetAlarm(void); /** - * This static method compares two timers and returns a value to indicate + * This method compares two timers and returns a value to indicate * which timer will fire earlier. * * @param[in] aTimerA The first timer for comparison. @@ -111,6 +117,8 @@ private: * @returns false if aTimerA will fire at the same time or after aTimerB. */ static bool TimerCompare(const Timer &aTimerA, const Timer &aTimerB); + + Timer *mHead; }; /** @@ -132,16 +140,18 @@ public: /** * This constructor creates a timer instance. * - * @param[in] aHandler A pointer to a function that is called when the timer expires. - * @param[in] aContext A pointer to arbitrary context information. + * @param[in] aScheduler A refrence to the timer scheduler. + * @param[in] aHandler A pointer to a function that is called when the timer expires. + * @param[in] aContext A pointer to arbitrary context information. * */ - Timer(Handler aHandler, void *aContext) { - mHandler = aHandler; - mContext = aContext; - mT0 = 0; - mDt = 0; - mNext = NULL; + Timer(TimerScheduler &aScheduler, Handler aHandler, void *aContext): + mScheduler(aScheduler), + mHandler(aHandler), + mContext(aContext), + mT0(0), + mDt(0), + mNext(NULL) { } /** @@ -166,7 +176,7 @@ public: * @retval TRUE If the timer is running. * @retval FALSE If the timer is not running. */ - bool IsRunning(void) const { return TimerScheduler::IsAdded(*this); } + bool IsRunning(void) const { return mScheduler.IsAdded(*this); } /** * This method schedules the timer to fire a @p dt milliseconds from now. @@ -181,13 +191,13 @@ public: * @param[in] aT0 The start time in milliseconds. * @param[in] aDt The expire time in milliseconds from @p t0. */ - void StartAt(uint32_t aT0, uint32_t aDt) { mT0 = aT0; mDt = aDt; TimerScheduler::Add(*this); } + void StartAt(uint32_t aT0, uint32_t aDt) { mT0 = aT0; mDt = aDt; mScheduler.Add(*this); } /** * This method stops the timer. * */ - void Stop(void) { TimerScheduler::Remove(*this); } + void Stop(void) { mScheduler.Remove(*this); } /** * This static method returns the current time in milliseconds. @@ -216,11 +226,12 @@ public: private: void Fired(void) { mHandler(mContext); } - Handler mHandler; ///< A pointer to the function that is called when the timer expires. - void *mContext; ///< A pointer to arbitrary context information. - uint32_t mT0; ///< The start time of the timer in milliseconds. - uint32_t mDt; ///< The time delay from the start time in milliseconds. - Timer *mNext; ///< The next timer in the scheduler list. + TimerScheduler &mScheduler; + Handler mHandler; + void *mContext; + uint32_t mT0; + uint32_t mDt; + Timer *mNext; }; /** diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index ae0c89f64..6fec0f23a 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -68,9 +68,9 @@ void Mac::StartCsmaBackoff(void) Mac::Mac(ThreadNetif &aThreadNetif): mBeginTransmit(aThreadNetif.GetIp6().mTaskletScheduler, &HandleBeginTransmit, this), - mAckTimer(&HandleAckTimer, this), - mBackoffTimer(&HandleBeginTransmit, this), - mReceiveTimer(&HandleReceiveTimer, this), + mAckTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleAckTimer, this), + mBackoffTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleBeginTransmit, this), + mReceiveTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleReceiveTimer, this), mKeyManager(aThreadNetif.GetKeyManager()), mMle(aThreadNetif.GetMle()), mNetif(aThreadNetif), diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 91f46c055..e8f2460ca 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -51,6 +51,7 @@ Ip6::Ip6(void): mRoutes(*this), mIcmp(*this), mUdp(*this), + mMpl(*this), mForwardingEnabled(false), mReceiveIp6DatagramCallback(NULL), mReceiveIp6DatagramCallbackContext(NULL), diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index a6ef0ac6a..69216e1da 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -328,6 +328,7 @@ public: Udp mUdp; TaskletScheduler mTaskletScheduler; + TimerScheduler mTimerScheduler; private: void ProcessReceiveCallback(const Message &aMessage, const MessageInfo &aMessageInfo, uint8_t aIpProto); diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp index 4583b2b61..954f161c7 100644 --- a/src/core/net/ip6_mpl.cpp +++ b/src/core/net/ip6_mpl.cpp @@ -33,13 +33,14 @@ #include #include +#include #include namespace Thread { namespace Ip6 { -Mpl::Mpl(): - mTimer(&HandleTimer, this) +Mpl::Mpl(Ip6 &aIp6): + mTimer(aIp6.mTimerScheduler, &HandleTimer, this) { memset(mEntries, 0, sizeof(mEntries)); mSequence = 0; diff --git a/src/core/net/ip6_mpl.hpp b/src/core/net/ip6_mpl.hpp index ec8428d06..43030e6ad 100644 --- a/src/core/net/ip6_mpl.hpp +++ b/src/core/net/ip6_mpl.hpp @@ -173,8 +173,10 @@ public: /** * This constructor initializes the MPL object. * + * @param[in] aIp6 A reference to the IPv6 network object. + * */ - Mpl(void); + Mpl(Ip6 &aIp6); /** * This method initializes the MPL option. diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index 043a7f663..f6240e79b 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -55,7 +55,7 @@ AddressResolver::AddressResolver(ThreadNetif &aThreadNetif) : mAddressNotification(OPENTHREAD_URI_ADDRESS_NOTIFY, &HandleAddressNotification, this), mIcmpHandler(&HandleDstUnreach, this), mSocket(aThreadNetif.GetIp6().mUdp), - mTimer(&HandleTimer, this), + mTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleTimer, this), mMeshForwarder(aThreadNetif.GetMeshForwarder()), mCoapServer(aThreadNetif.GetCoapServer()), mMle(aThreadNetif.GetMle()), diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 638ed4ef6..69be3f478 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -53,9 +53,9 @@ namespace Thread { MeshForwarder::MeshForwarder(ThreadNetif &aThreadNetif): mMacReceiver(&HandleReceivedFrame, this), mMacSender(&HandleFrameRequest, &HandleSentFrame, this), - mDiscoverTimer(&HandleDiscoverTimer, this), - mPollTimer(&HandlePollTimer, this), - mReassemblyTimer(&HandleReassemblyTimer, this), + mDiscoverTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleDiscoverTimer, this), + mPollTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandlePollTimer, this), + mReassemblyTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleReassemblyTimer, this), mScheduleTransmissionTask(aThreadNetif.GetIp6().mTaskletScheduler, ScheduleTransmissionTask, this), mNetif(aThreadNetif), mAddressResolver(aThreadNetif.GetAddressResolver()), diff --git a/src/core/thread/meshcop_dataset_manager.cpp b/src/core/thread/meshcop_dataset_manager.cpp index 791d4c780..71da16edf 100644 --- a/src/core/thread/meshcop_dataset_manager.cpp +++ b/src/core/thread/meshcop_dataset_manager.cpp @@ -55,7 +55,7 @@ DatasetManager::DatasetManager(ThreadNetif &aThreadNetif, const char *aUriSet, c mNetworkDataLeader(aThreadNetif.GetNetworkDataLeader()), mResourceSet(aUriSet, &HandleSet, this), mResourceGet(aUriGet, &HandleGet, this), - mTimer(&HandleTimer, this), + mTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleTimer, this), mSocket(aThreadNetif.GetIp6().mUdp), mUriSet(aUriSet), mUriGet(aUriGet), @@ -688,7 +688,7 @@ ThreadError ActiveDataset::ApplyConfiguration(void) PendingDataset::PendingDataset(ThreadNetif &aThreadNetif): DatasetManager(aThreadNetif, OPENTHREAD_URI_PENDING_SET, OPENTHREAD_URI_PENDING_GET), - mTimer(HandleTimer, this) + mTimer(aThreadNetif.GetIp6().mTimerScheduler, HandleTimer, this) { } diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 993afc2cd..9ad7259af 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -61,7 +61,7 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mMesh(aThreadNetif.GetMeshForwarder()), mMleRouter(aThreadNetif.GetMle()), mNetworkData(aThreadNetif.GetNetworkDataLeader()), - mParentRequestTimer(&HandleParentRequestTimer, this), + mParentRequestTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleParentRequestTimer, this), mSocket(aThreadNetif.GetIp6().mUdp), mSendChildUpdateRequest(aThreadNetif.GetIp6().mTaskletScheduler, &HandleSendChildUpdateRequest, this) { diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 5cc593935..36b914a68 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -50,8 +50,8 @@ namespace Mle { MleRouter::MleRouter(ThreadNetif &aThreadNetif): Mle(aThreadNetif), - mAdvertiseTimer(&HandleAdvertiseTimer, this), - mStateUpdateTimer(&HandleStateUpdateTimer, this), + mAdvertiseTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleAdvertiseTimer, this), + mStateUpdateTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleStateUpdateTimer, this), mSocket(aThreadNetif.GetIp6().mUdp), mAddressSolicit(OPENTHREAD_URI_ADDRESS_SOLICIT, &HandleAddressSolicit, this), mAddressRelease(OPENTHREAD_URI_ADDRESS_RELEASE, &HandleAddressRelease, this), diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index c2ac98077..a9812be9c 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -53,7 +53,7 @@ namespace NetworkData { Leader::Leader(ThreadNetif &aThreadNetif): NetworkData(aThreadNetif), - mTimer(&HandleTimer, this), + mTimer(aThreadNetif.GetIp6().mTimerScheduler, &HandleTimer, this), mServerData(OPENTHREAD_URI_SERVER_DATA, &HandleServerData, this), mCoapServer(aThreadNetif.GetCoapServer()), mNetif(aThreadNetif) diff --git a/tests/unit/test_timer.cpp b/tests/unit/test_timer.cpp index 335055246..a875f83de 100644 --- a/tests/unit/test_timer.cpp +++ b/tests/unit/test_timer.cpp @@ -42,6 +42,7 @@ enum kCallCountIndexMax }; +static Thread::TimerScheduler sTimerScheduler; static uint32_t sNow; static uint32_t sPlatT0; static uint32_t sPlatDt; @@ -93,7 +94,7 @@ int TestOneTimer(void) { const uint32_t kTimeT0 = 1000; const uint32_t kTimerInterval = 10; - Thread::Timer timer(TestTimerHandler, NULL); + Thread::Timer timer(sTimerScheduler, TestTimerHandler, NULL); // Test one Timer basic operation. @@ -325,16 +326,16 @@ int TestTenTimers(void) }; uint32_t timerContextHandleCounter[kNumTimers] = {0}; - Thread::Timer timer0(TestTimerHandler, &timerContextHandleCounter[0]); - Thread::Timer timer1(TestTimerHandler, &timerContextHandleCounter[1]); - Thread::Timer timer2(TestTimerHandler, &timerContextHandleCounter[2]); - Thread::Timer timer3(TestTimerHandler, &timerContextHandleCounter[3]); - Thread::Timer timer4(TestTimerHandler, &timerContextHandleCounter[4]); - Thread::Timer timer5(TestTimerHandler, &timerContextHandleCounter[5]); - Thread::Timer timer6(TestTimerHandler, &timerContextHandleCounter[6]); - Thread::Timer timer7(TestTimerHandler, &timerContextHandleCounter[7]); - Thread::Timer timer8(TestTimerHandler, &timerContextHandleCounter[8]); - Thread::Timer timer9(TestTimerHandler, &timerContextHandleCounter[9]); + Thread::Timer timer0(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[0]); + Thread::Timer timer1(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[1]); + Thread::Timer timer2(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[2]); + Thread::Timer timer3(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[3]); + Thread::Timer timer4(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[4]); + Thread::Timer timer5(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[5]); + Thread::Timer timer6(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[6]); + Thread::Timer timer7(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[7]); + Thread::Timer timer8(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[8]); + Thread::Timer timer9(sTimerScheduler, TestTimerHandler, &timerContextHandleCounter[9]); Thread::Timer *timers[kNumTimers] = {&timer0, &timer1, &timer2, &timer3, &timer4, &timer5, &timer6, &timer7, &timer8, &timer9}; size_t i;