From a2cdb483b24c1b978fdb441c50b1d1e861273166 Mon Sep 17 00:00:00 2001 From: Kevin Schoedel <67607049+kpschoedel@users.noreply.github.com> Date: Fri, 5 Nov 2021 16:18:38 -0400 Subject: [PATCH] Migrate System::Timer to BitMapObjectPool (#11487) #### Problem The multiple object pool implementations are being consolidated, but `System::Timer` isn't ready. #### Change overview Transitionally, convert `System::Timer` to use `BitMapObjectPool` instead of `System::ObjectPool`, so that it doesn't obstruct refactoring. Any platform using both `System::Timer` and `CHIP_SYSTEM_CONFIG_USE_HEAP` will show a `.bss` increase from this PR; this will be undone by a later step in pool conversion. #### Testing CI; no changes to functionality. --- src/system/SystemTimer.cpp | 31 ++++++++++++++++++++++++------- src/system/SystemTimer.h | 22 ++++++++++++++++------ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/system/SystemTimer.cpp b/src/system/SystemTimer.cpp index 97caaf32f7ec4d..d9a1600802a106 100644 --- a/src/system/SystemTimer.cpp +++ b/src/system/SystemTimer.cpp @@ -74,28 +74,45 @@ namespace System { ******************************************************************************* */ -ObjectPool Timer::sPool; +BitMapObjectPool Timer::sPool; +Stats::count_t Timer::mNumInUse = 0; +Stats::count_t Timer::mHighWatermark = 0; Timer * Timer::New(System::Layer & systemLayer, System::Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) { - Timer * timer = Timer::sPool.TryCreate(); + Timer * timer = Timer::sPool.CreateObject(); if (timer == nullptr) { ChipLogError(chipSystemLayer, "Timer pool EMPTY"); } else { - timer->AppState = appState; + timer->mAppState = appState; timer->mSystemLayer = &systemLayer; timer->mAwakenTime = SystemClock().GetMonotonicTimestamp() + delay; if (!__sync_bool_compare_and_swap(&timer->mOnComplete, nullptr, onComplete)) { chipDie(); } +#if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS + static_assert(CHIP_SYSTEM_CONFIG_NUM_TIMERS < CHIP_SYS_STATS_COUNT_MAX, "Stats count is too small"); + if (++mNumInUse > mHighWatermark) + { + mHighWatermark = mNumInUse; + } +#endif // CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS } return timer; } +void Timer::Release() +{ + Timer::sPool.ReleaseObject(this); +#if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS + --mNumInUse; +#endif // CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS +} + void Timer::Clear() { TimerCompleteCallback lOnComplete = this->mOnComplete; @@ -107,7 +124,7 @@ void Timer::Clear() VerifyOrReturn(__sync_bool_compare_and_swap(&mOnComplete, lOnComplete, nullptr)); // Since this thread changed the state of mOnComplete, release the timer. - AppState = nullptr; + mAppState = nullptr; mSystemLayer = nullptr; } @@ -116,7 +133,7 @@ void Timer::HandleComplete() // Save information needed to perform the callback. Layer * lLayer = this->mSystemLayer; const TimerCompleteCallback lOnComplete = this->mOnComplete; - void * lAppState = this->AppState; + void * lAppState = this->mAppState; // Check if timer is armed VerifyOrReturn(lOnComplete != nullptr, ); @@ -124,7 +141,7 @@ void Timer::HandleComplete() VerifyOrReturn(__sync_bool_compare_and_swap(&this->mOnComplete, lOnComplete, nullptr), ); // Since this thread changed the state of mOnComplete, release the timer. - AppState = nullptr; + mAppState = nullptr; mSystemLayer = nullptr; this->Release(); @@ -193,7 +210,7 @@ Timer * Timer::List::Remove(TimerCompleteCallback aOnComplete, void * aAppState) Timer * previous = nullptr; for (Timer * timer = mHead; timer != nullptr; timer = timer->mNextTimer) { - if (timer->mOnComplete == aOnComplete && timer->AppState == aAppState) + if (timer->mOnComplete == aOnComplete && timer->mAppState == aAppState) { if (previous == nullptr) { diff --git a/src/system/SystemTimer.h b/src/system/SystemTimer.h index 2534d4f6108f37..390307ba97f2d8 100644 --- a/src/system/SystemTimer.h +++ b/src/system/SystemTimer.h @@ -32,11 +32,12 @@ // Include dependent headers #include +#include #include #include +#include #include -#include #include #if CHIP_SYSTEM_CONFIG_USE_DISPATCH @@ -57,7 +58,7 @@ using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState); /** * This is an Object-pool based class that System::Layer implementations can use to assist in providing timer functions. */ -class DLL_EXPORT Timer : public Object +class DLL_EXPORT Timer { public: /** @@ -185,11 +186,16 @@ class DLL_EXPORT Timer : public Object Timer() = default; /** - * Obtain a new timer from the system object pool. + * Obtain a new timer from the object pool. */ static Timer * New(System::Layer & systemLayer, System::Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState); + /** + * Return a timer to the object pool. + */ + void Release(); + /** * Return the expiration time. */ @@ -215,20 +221,24 @@ class DLL_EXPORT Timer : public Object /** * Read timer pool statistics. */ - static void GetStatistics(chip::System::Stats::count_t & aNumInUse, chip::System::Stats::count_t & aHighWatermark) + static void GetStatistics(Stats::count_t & aNumInUse, Stats::count_t & aHighWatermark) { - sPool.GetStatistics(aNumInUse, aHighWatermark); + aNumInUse = mNumInUse; + aHighWatermark = mHighWatermark; } private: friend class LayerImplLwIP; - static ObjectPool sPool; + static BitMapObjectPool sPool; + static Stats::count_t mNumInUse; + static Stats::count_t mHighWatermark; TimerCompleteCallback mOnComplete; Clock::Timestamp mAwakenTime; Timer * mNextTimer; Layer * mSystemLayer; + void * mAppState; #if CHIP_SYSTEM_CONFIG_USE_DISPATCH friend class LayerImplSelect;