Skip to content

Commit

Permalink
Migrate System::Timer to BitMapObjectPool (#11487)
Browse files Browse the repository at this point in the history
#### 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.
  • Loading branch information
kpschoedel authored and pull[bot] committed Jul 18, 2022
1 parent 74af27c commit 2441656
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 13 deletions.
31 changes: 24 additions & 7 deletions src/system/SystemTimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,28 +74,45 @@ namespace System {
*******************************************************************************
*/

ObjectPool<Timer, CHIP_SYSTEM_CONFIG_NUM_TIMERS> Timer::sPool;
BitMapObjectPool<Timer, CHIP_SYSTEM_CONFIG_NUM_TIMERS> 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;
Expand All @@ -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;
}

Expand All @@ -116,15 +133,15 @@ 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, );
// Atomically disarm if the value has not changed.
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();

Expand Down Expand Up @@ -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)
{
Expand Down
22 changes: 16 additions & 6 deletions src/system/SystemTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@

// Include dependent headers
#include <lib/support/DLLUtil.h>
#include <lib/support/Pool.h>

#include <system/SystemClock.h>
#include <system/SystemError.h>
#include <system/SystemLayer.h>
#include <system/SystemMutex.h>
#include <system/SystemObject.h>
#include <system/SystemStats.h>

#if CHIP_SYSTEM_CONFIG_USE_DISPATCH
Expand All @@ -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:
/**
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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<Timer, CHIP_SYSTEM_CONFIG_NUM_TIMERS> sPool;
static BitMapObjectPool<Timer, CHIP_SYSTEM_CONFIG_NUM_TIMERS> 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;
Expand Down

0 comments on commit 2441656

Please sign in to comment.