From 5f847e0ecc55e701d4dc6157f454f54721d67278 Mon Sep 17 00:00:00 2001 From: Kevin Schoedel <67607049+kpschoedel@users.noreply.github.com> Date: Fri, 19 Nov 2021 22:58:49 -0500 Subject: [PATCH] Remove System::Object (#12051) #### Problem All uses of `System::Object` pools have now converted to use `chip::ObjectPool` from `lib/support/Pool.h`. #### Change overview - Remove `System::Object` - Fix some formerly transitive includes. #### Testing CI for build. No change to active code. --- examples/shell/shell_common/cmd_send.cpp | 1 + .../tests/TestSetupFaultInjectionPosix.cpp | 4 +- .../UserDirectedCommissioningClient.cpp | 2 + src/system/BUILD.gn | 2 - src/system/SystemLayer.h | 1 - src/system/SystemObject.cpp | 106 ---- src/system/SystemObject.h | 456 ------------------ src/system/SystemTimer.h | 3 +- src/system/tests/BUILD.gn | 1 - src/system/tests/TestSystemObject.cpp | 456 ------------------ src/transport/raw/tests/TestTCP.cpp | 1 - 11 files changed, 8 insertions(+), 1025 deletions(-) delete mode 100644 src/system/SystemObject.cpp delete mode 100644 src/system/SystemObject.h delete mode 100644 src/system/tests/TestSystemObject.cpp diff --git a/examples/shell/shell_common/cmd_send.cpp b/examples/shell/shell_common/cmd_send.cpp index 1139cde796e8de..26363ebdc8a10c 100644 --- a/examples/shell/shell_common/cmd_send.cpp +++ b/examples/shell/shell_common/cmd_send.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/src/inet/tests/TestSetupFaultInjectionPosix.cpp b/src/inet/tests/TestSetupFaultInjectionPosix.cpp index f7f8129e48ff1d..125f90b90a1f9a 100644 --- a/src/inet/tests/TestSetupFaultInjectionPosix.cpp +++ b/src/inet/tests/TestSetupFaultInjectionPosix.cpp @@ -32,9 +32,11 @@ #include #include #include -#include #include +#include +#include + struct RestartCallbackContext { int mArgc; diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp index febb51da343147..775de9c001e9b2 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp @@ -25,6 +25,8 @@ #include "UserDirectedCommissioning.h" +#include + namespace chip { namespace Protocols { namespace UserDirectedCommissioning { diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index 0aaa7a9e192674..874bc3cdc0171d 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -139,8 +139,6 @@ static_library("system") { "SystemLayerImpl.h", "SystemMutex.cpp", "SystemMutex.h", - "SystemObject.cpp", - "SystemObject.h", "SystemPacketBuffer.cpp", "SystemPacketBuffer.h", "SystemStats.cpp", diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h index 2377af2333b91c..0aa97ce24ca80a 100644 --- a/src/system/SystemLayer.h +++ b/src/system/SystemLayer.h @@ -37,7 +37,6 @@ #include #include #include -#include #include #if CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/system/SystemObject.cpp b/src/system/SystemObject.cpp deleted file mode 100644 index fc1ebf987f9836..00000000000000 --- a/src/system/SystemObject.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2016-2017 Nest Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This file contains definitions of member functions for class - * chip::System::Object. - */ - -// Include module header -#include - -// Include local headers -#include -#include - -// Include local headers -#include -#include - -namespace chip { -namespace System { - -/** - * @brief - * Decrements the reference count for the CHIP System Layer object. Recycles the object back into the pool if the reference - * count is decremented to zero. No destructor is invoked. - */ -DLL_EXPORT void Object::Release() -{ - unsigned int oldCount = __sync_fetch_and_sub(&this->mRefCount, 1); - - if (oldCount == 1) - { -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - std::lock_guard lock(*mMutexRef); - this->mPrev->mNext = this->mNext; - if (this->mNext) - this->mNext->mPrev = this->mPrev; - delete this; -#endif - __sync_synchronize(); - } - else if (oldCount == 0) - { - abort(); - } -} - -DLL_EXPORT bool Object::TryCreate(size_t aOctets) -{ - if (!__sync_bool_compare_and_swap(&this->mRefCount, 0, 1)) - { - return false; // object already in use - } - - this->AppState = nullptr; - memset(reinterpret_cast(this) + sizeof(*this), 0, aOctets - sizeof(*this)); - - return true; -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -void Object::DeferredRelease(LayerLwIP * aSystemLayer, Object::ReleaseDeferralErrorTactic aTactic) -{ - VerifyOrReturn(aSystemLayer != nullptr, ChipLogError(chipSystemLayer, "aSystemLayer is nullptr")); - - CHIP_ERROR lError = aSystemLayer->ScheduleLambda([this] { this->Release(); }); - - if (lError != CHIP_NO_ERROR) - { - switch (aTactic) - { - case kReleaseDeferralErrorTactic_Ignore: - break; - - case kReleaseDeferralErrorTactic_Release: - this->Release(); - break; - - case kReleaseDeferralErrorTactic_Die: - VerifyOrDieWithMsg(false, chipSystemLayer, "Object::DeferredRelease %p->PostEvent failed err(%" CHIP_ERROR_FORMAT ")", - aSystemLayer, lError.Format()); - break; - } - } -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -} // namespace System -} // namespace chip diff --git a/src/system/SystemObject.h b/src/system/SystemObject.h deleted file mode 100644 index 155f8f92bb3245..00000000000000 --- a/src/system/SystemObject.h +++ /dev/null @@ -1,456 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2016-2017 Nest Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This file contains declarations of the following classes and - * templates: - * - * - class chip::System::Object - * - template union chip::System::ObjectArena - * - template class chip::System::ObjectPool - */ - -#pragma once - -// Include configuration headers -#include - -// Include dependent headers -#include -#include -#include -#include - -#include -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP -#include -#include -#include -#endif - -#include - -#include -#include - -#ifndef SYSTEM_OBJECT_HWM_TEST_HOOK -#define SYSTEM_OBJECT_HWM_TEST_HOOK() -#endif - -namespace chip { -namespace System { - -// Forward class and class template declarations -class Layer; -class LayerSockets; -class LayerLwIP; -template -class ObjectPoolStatic; -template -class ObjectPoolDynamic; - -/** - * @class Object - * - * @brief - * This represents a reference-counted object allocated from space contained in an ObjectPool object. - * - * @note - * Instance of this class may only be constructed using the related ObjectPool class template. The copy constructor and the - * assignment operator are deleted. A reference counting system is used to track retentions of instances of this class. - * When an object is initially retained, its reference count is one. Additional retentions may increment the reference count. - * When the object is released, the reference count is decremented. When the reference count is zero, the object is recycled - * back to the pool for reallocation. There is no destructor available. Subclasses must be designed to ensure that all - * encapsulated resources are released when the final retention is released and the object is recycled. - * - * While this class is defined as concrete, it should be regarded as abstract. - */ -class DLL_EXPORT Object -{ - template - friend class ObjectPoolStatic; - template - friend class ObjectPoolDynamic; - -public: - Object() : mRefCount(0) - { -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - mNext = nullptr; - mPrev = nullptr; -#endif - } - - virtual ~Object() {} - - /** Test whether this object is retained. Concurrency safe. */ - bool IsRetained() const; - - void Retain(); - void Release(); - Layer & SystemLayer() const; - - /**< What to do when DeferredRelease fails to post a kEvent_ReleaseObj. */ - enum ReleaseDeferralErrorTactic - { - kReleaseDeferralErrorTactic_Ignore, /**< No action. */ - kReleaseDeferralErrorTactic_Release, /**< Release immediately. */ - kReleaseDeferralErrorTactic_Die, /**< Die with message. */ - }; - -protected: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - void DeferredRelease(LayerLwIP * aSystemLayer, ReleaseDeferralErrorTactic aTactic); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -private: - Object(const Object &) = delete; - Object & operator=(const Object &) = delete; - -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - Object * mNext; - Object * mPrev; - std::mutex * mMutexRef; -#endif - - unsigned int mRefCount; /**< Count of remaining calls to Release before object is dead. */ - - /** - * @brief - * Attempts to perform an initial retention of this object, in a THREAD-SAFE manner. - * - * @note - * If reference count is non-zero, tryCreate will fail and return false. - * If reference count is zero, then: - * - reference count will be set to 1 - * - The size of the created object (assumed to be derived from SystemObject) is aOctects. - * the method will memset to 0 the bytes following sizeof(SystemObject). - * - * Typical usage is like: - * class Foo: public SystemObject {...} - * .... - * Foo foo; - * foo.TryCreate(sizeof(foo)); - * - * IMPORTANT inheritance precondition: - * 0 memset assumes that SystemObject is the top of the inheritance. This will NOT work properly: - * class Bar: public Baz, SystemObject {...} - * Bar bar; - * bar.TryCreate(sizeof(bar)); /// NOT safe: this will clear sizeof(Baz) extra bytes in unallocated space. - */ - bool TryCreate(size_t aOctets); - -public: - void * AppState; /**< Generic pointer to app-specific data associated with the object. */ -}; - -/** - * @brief - * Tests whether this object is retained. - * - * @note - * No memory barrier is applied. If this returns \c false in one thread context, then it does not imply that another thread - * cannot have previously retained the object for \c aLayer. If it returns \c true, then the logic using \c mRefCount is - * responsible for ensuring concurrency safety for this object. - */ -inline bool Object::IsRetained() const -{ - return this->mRefCount > 0; -} - -/** - * @brief - * Increments the reference count for the CHIP System Layer object. The object is assumed to be live. - */ -inline void Object::Retain() -{ - __sync_fetch_and_add(&this->mRefCount, 1); -} - -/** - * @brief - * A union template used for representing a well-aligned block of memory. - * - * @tparam ALIGN a typename with the alignment properties for the block. - * @tparam SIZE a constant size of the block in bytes. - */ -template -union ObjectArena -{ - uint8_t uMemory[SIZE]; - ALIGN uAlign; -}; - -/** - * @class ObjectPoolStatic - * - * @brief - * This is the data class for static object pools. - * - * @tparam T a subclass of Object to be allocated. - * @tparam N a positive integer number of objects of class T to allocate from the arena. - */ -template -class ObjectPoolStatic -{ -public: - T * TryCreate() - { - T * lReturn = nullptr; - (void) static_cast(lReturn); /* In C++-11, this would be a static_assert that T inherits Object. */ - - size_t lIndex = 0; - for (lIndex = 0; lIndex < N; ++lIndex) - { - T & lObject = reinterpret_cast(mArena.uMemory)[lIndex]; - - if (lObject.TryCreate(sizeof(T))) - { - lReturn = &lObject; - break; - } - } -#if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS - size_t lNumInUse = 0; - - if (lReturn != nullptr) - { - lIndex++; - lNumInUse = lIndex; - GetNumObjectsInUse(lIndex, lNumInUse); - } - else - { - lNumInUse = N; - } - - UpdateHighWatermark(lNumInUse); -#endif - return lReturn; - } -#if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS - /** - * Return the number of objects in use starting at a given index - * - * @param[in] aStartIndex The index to start counting from; pass 0 to count over - * the whole pool. - * @param[in,out] aNumInUse The number of objects in use. If aStartIndex is not 0, - * the function adds to the counter without resetting it first. - */ - void GetNumObjectsInUse(size_t aStartIndex, size_t & aNumInUse) - { - size_t count = 0; - - for (size_t lIndex = aStartIndex; lIndex < N; ++lIndex) - { - T & lObject = reinterpret_cast(mArena.uMemory)[lIndex]; - - if (lObject.IsRetained()) - { - count++; - } - } - - if (aStartIndex == 0) - { - aNumInUse = 0; - } - - aNumInUse += count; - } - void UpdateHighWatermark(const size_t & aCandidate) - { - size_t lTmp; - while (aCandidate > (lTmp = mHighWatermark)) - { - SYSTEM_OBJECT_HWM_TEST_HOOK(); - (void) __sync_bool_compare_and_swap(&mHighWatermark, lTmp, aCandidate); - } - } - volatile size_t mHighWatermark; -#endif - - void GetStatistics(chip::System::Stats::count_t & aNumInUse, chip::System::Stats::count_t & aHighWatermark) - { -#if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS - size_t lNumInUse; - size_t lHighWatermark; - - GetNumObjectsInUse(0, lNumInUse); - lHighWatermark = mHighWatermark; - - if (lNumInUse > CHIP_SYS_STATS_COUNT_MAX) - { - lNumInUse = CHIP_SYS_STATS_COUNT_MAX; - } - if (lHighWatermark > CHIP_SYS_STATS_COUNT_MAX) - { - lHighWatermark = CHIP_SYS_STATS_COUNT_MAX; - } - aNumInUse = static_cast(lNumInUse); - aHighWatermark = static_cast(lHighWatermark); -#endif - } - /** - * @brief - * Run a functor for each active object in the pool - * - * @param function The functor of type `bool (*)(T*)`, return false to break the iteration - * @return bool Returns false if broke during iteration - */ - template - bool ForEachActiveObject(Function && function) - { - for (size_t i = 0; i < N; ++i) - { - T & lObject = reinterpret_cast(mArena.uMemory)[i]; - - if (lObject.IsRetained()) - { - if (!function(&lObject)) - return false; - } - } - return true; - } - void Reset() - { - memset(mArena.uMemory, 0, N * sizeof(T)); -#if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS - mHighWatermark = 0; -#endif - } - ObjectArena mArena; -}; - -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP -/** - * @class ObjectPoolDynamic - * - * @brief - * This is the data class for dynamic object pools. - * - * @tparam T a subclass of Object to be allocated. - */ -template -class ObjectPoolDynamic -{ -public: - T * TryCreate() - { - - T * newNode = new T(); - - if (newNode->TryCreate(sizeof(T))) - { - std::lock_guard lock(mMutex); - Object * p = &mDummyHead; - if (p->mNext) - { - p->mNext->mPrev = newNode; - } - newNode->mNext = p->mNext; - p->mNext = newNode; - newNode->mPrev = p; - newNode->mMutexRef = &mMutex; - return newNode; - } - else - { - delete newNode; - return nullptr; - } - } - - /** - * @brief - * Run a functor for each active object in the pool - * - * @param function The functor of type `bool (*)(T*)`, return false to break the iteration - * @return bool Returns false if broke during iteration - */ - template - bool ForEachActiveObject(Function && function) - { - std::lock_guard lock(mMutex); - Object * p = mDummyHead.mNext; - while (p) - { - if (!function(static_cast(p))) - { - return false; - } - p = p->mNext; - } - return true; - } - void Reset() - { - std::lock_guard lock(mMutex); - Object * p = mDummyHead.mNext; - - while (p) - { - Object * del = p; - p = p->mNext; - delete del; - } - - mDummyHead.mNext = nullptr; - } - void GetStatistics(chip::System::Stats::count_t & aNumInUse, chip::System::Stats::count_t & aHighWatermark) {} - std::mutex mMutex; - Object mDummyHead; - friend class TestObject; -}; -#endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP -template -using ObjectPool = ObjectPoolDynamic; -#else -template -using ObjectPool = ObjectPoolStatic; -#endif - -enum class ObjectPoolMem -{ - kStatic, -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - kDynamic -#endif -}; - -template -class MemTypeObjectPool; - -template -class MemTypeObjectPool : public ObjectPoolStatic -{ -}; - -#if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP -template -class MemTypeObjectPool : public ObjectPoolDynamic -{ -}; -#endif - -} // namespace System -} // namespace chip diff --git a/src/system/SystemTimer.h b/src/system/SystemTimer.h index 91efa2a0cfcdca..1fd3138873f7d1 100644 --- a/src/system/SystemTimer.h +++ b/src/system/SystemTimer.h @@ -36,7 +36,6 @@ #include #include -#include #include #include @@ -51,6 +50,8 @@ namespace chip { namespace System { +class Layer; + using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState); #if CHIP_SYSTEM_CONFIG_USE_TIMER_POOL diff --git a/src/system/tests/BUILD.gn b/src/system/tests/BUILD.gn index 432bc11d366ac7..64653bf61cced1 100644 --- a/src/system/tests/BUILD.gn +++ b/src/system/tests/BUILD.gn @@ -24,7 +24,6 @@ chip_test_suite("tests") { test_sources = [ "TestSystemClock.cpp", "TestSystemErrorStr.cpp", - "TestSystemObject.cpp", "TestSystemPacketBuffer.cpp", "TestSystemScheduleLambda.cpp", "TestSystemTimer.cpp", diff --git a/src/system/tests/TestSystemObject.cpp b/src/system/tests/TestSystemObject.cpp deleted file mode 100644 index bc710fdd1e759e..00000000000000 --- a/src/system/tests/TestSystemObject.cpp +++ /dev/null @@ -1,456 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * Copyright (c) 2016-2017 Nest Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This is a unit test suite for chip::System::Object, * - * the part of the CHIP System Layer that implements objects and - * their static allocation pools. - * - */ - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -// Install a sleep in the high water mark function, to force -// collisions between the threads that call it. - -// clang-format off -#include -#define SYSTEM_OBJECT_HWM_TEST_HOOK() do { chip::test_utils::SleepMillis(1); } while(0) -// clang-format on - -#include - -#include -#include -#include - -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING -#include -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - -#include -#include -#include -#include -#include - -// Test context -using namespace chip::System; - -namespace chip { -namespace System { - -static int Initialize(void * aContext); -static int Finalize(void * aContext); - -class TestObject : public Object -{ -public: - CHIP_ERROR Init(); - - static void CheckIteration(nlTestSuite * inSuite, void * aContext); - static void CheckRetention(nlTestSuite * inSuite, void * aContext); - static void CheckConcurrency(nlTestSuite * inSuite, void * aContext); -#if !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - static void CheckHighWatermark(nlTestSuite * inSuite, void * aContext); - static void CheckHighWatermarkConcurrency(nlTestSuite * inSuite, void * aContext); -#endif - -private: - static constexpr int kNumThreads = 16; - static constexpr int kLoopIterations = 1000; - static constexpr int kMaxDelayIterations = 3; - static constexpr int kPoolSize = (kNumThreads * 7) + 1; - - static_assert(kNumThreads > 1, "kNumThreads should be more than 1"); - static_assert(kPoolSize < CHIP_SYS_STATS_COUNT_MAX, "kPoolSize is not less than CHIP_SYS_STATS_COUNT_MAX"); - - static ObjectPool sPool; - -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING - unsigned int mDelay; - - void Delay(volatile unsigned int & aAccumulator); - static void * CheckConcurrencyThread(void * aContext); -#if !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - static void * CheckHighWatermarkThread(void * aContext); -#endif - static void MultithreadedTest(nlTestSuite * inSuite, void * aContext, void * (*aStartRoutine)(void *) ); -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - - // Not defined - TestObject & operator=(const TestObject &) = delete; -}; - -ObjectPool TestObject::sPool; - -CHIP_ERROR TestObject::Init() -{ -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING - this->mDelay = kMaxDelayIterations > 0 ? 1 : 0; - if (kMaxDelayIterations > 1) - { - this->mDelay += static_cast(rand() % kMaxDelayIterations); - } -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - - return CHIP_NO_ERROR; -} - -namespace { -struct TestContext -{ - nlTestSuite * mTestSuite; - volatile unsigned int mAccumulator; -}; - -struct TestContext sContext; -} // namespace - -// Test Object Iteration - -void TestObject::CheckIteration(nlTestSuite * inSuite, void * aContext) -{ - TestContext & lContext = *static_cast(aContext); - unsigned int i; - - sPool.Reset(); - - for (i = 0; i < kPoolSize; ++i) - { - TestObject * lCreated = sPool.TryCreate(); - - NL_TEST_ASSERT(lContext.mTestSuite, lCreated != nullptr); - lCreated->Init(); - } - - i = 0; - sPool.ForEachActiveObject([&](TestObject * lCreated) { - NL_TEST_ASSERT(lContext.mTestSuite, lCreated->IsRetained()); - i++; - return true; - }); - NL_TEST_ASSERT(lContext.mTestSuite, i == kPoolSize); - - i = 0; - sPool.ForEachActiveObject([&](TestObject * lCreated) { - i++; - if (i == kPoolSize / 2) - return false; - - return true; - }); - NL_TEST_ASSERT(lContext.mTestSuite, i == kPoolSize / 2); -} - -// Test Object retention - -void TestObject::CheckRetention(nlTestSuite * inSuite, void * aContext) -{ - TestContext & lContext = *static_cast(aContext); - unsigned int i; - - sPool.Reset(); - - for (i = 0; i < kPoolSize; ++i) - { - TestObject * lCreated = sPool.TryCreate(); - - NL_TEST_ASSERT(lContext.mTestSuite, lCreated != nullptr); - - lCreated->Init(); - } - - i = 0; - TestObject::sPool.ForEachActiveObject([&](TestObject * lGotten) { - lGotten->Retain(); - i++; - return true; - }); - NL_TEST_ASSERT(lContext.mTestSuite, i == kPoolSize); - - i = 0; - TestObject::sPool.ForEachActiveObject([&](TestObject * lGotten) { - lGotten->Release(); - i++; - return true; - }); - NL_TEST_ASSERT(lContext.mTestSuite, i == kPoolSize); -} - -// Test Object concurrency - -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING -void TestObject::Delay(volatile unsigned int & aAccumulator) -{ - unsigned int lSum = 0; - - if (kMaxDelayIterations > 0) - { - for (unsigned int z = 0; z < this->mDelay; ++z) - { - lSum += static_cast(rand()); - } - - lSum = lSum / this->mDelay; - } - - aAccumulator = lSum; -} - -void * TestObject::CheckConcurrencyThread(void * aContext) -{ - const unsigned int kNumObjects = kPoolSize / kNumThreads; - TestObject * lObject = nullptr; - TestContext & lContext = *static_cast(aContext); - unsigned int i; - - // Take this thread's share of objects - - for (i = 0; i < kNumObjects; ++i) - { - lObject = nullptr; - while (lObject == nullptr) - { - lObject = sPool.TryCreate(); - } - - NL_TEST_ASSERT(lContext.mTestSuite, lObject->IsRetained()); - - lObject->Init(); - lObject->Delay(lContext.mAccumulator); - } - - // For each iteration, take one more object, and free it form the pool - - for (i = 0; i < kLoopIterations; ++i) - { - lObject = nullptr; - while (lObject == nullptr) - { - lObject = sPool.TryCreate(); - } - - NL_TEST_ASSERT(lContext.mTestSuite, lObject->IsRetained()); - - lObject->Init(); - lObject->Delay(lContext.mAccumulator); - - lObject->Release(); - } - - return aContext; -} - -#if !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP -void * TestObject::CheckHighWatermarkThread(void * aContext) -{ - TestContext & lContext = *static_cast(aContext); - int i; - chip::System::Stats::count_t lNumInUse; - chip::System::Stats::count_t lHighWatermark; - - i = (rand() % CHIP_SYS_STATS_COUNT_MAX); - - sPool.UpdateHighWatermark(static_cast(i)); - - sPool.GetStatistics(lNumInUse, lHighWatermark); - - NL_TEST_ASSERT(lContext.mTestSuite, lHighWatermark >= i); - if (lHighWatermark < i) - { - printf("hwm: %d, i: %d\n", lHighWatermark, i); - } - - return aContext; -} -#endif - -void TestObject::MultithreadedTest(nlTestSuite * inSuite, void * aContext, void * (*aStartRoutine)(void *) ) -{ - TestContext & lContext = *static_cast(aContext); - pthread_t lThread[kNumThreads]; - - sPool.Reset(); - - for (unsigned int i = 0; i < kNumThreads; ++i) - { - int lError = pthread_create(&lThread[i], nullptr, aStartRoutine, &lContext); - - NL_TEST_ASSERT(lContext.mTestSuite, lError == 0); - } - - for (pthread_t thread : lThread) - { - int lError = pthread_join(thread, nullptr); - - NL_TEST_ASSERT(lContext.mTestSuite, lError == 0); - } -} -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - -void TestObject::CheckConcurrency(nlTestSuite * inSuite, void * aContext) -{ -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING - MultithreadedTest(inSuite, aContext, CheckConcurrencyThread); -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING -} - -#if !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP -void TestObject::CheckHighWatermarkConcurrency(nlTestSuite * inSuite, void * aContext) -{ - sPool.Reset(); - -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING - for (unsigned int i = 0; i < 100; i++) - { - MultithreadedTest(inSuite, aContext, CheckHighWatermarkThread); - } -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING -} - -void TestObject::CheckHighWatermark(nlTestSuite * inSuite, void * aContext) -{ - sPool.Reset(); - - const int kNumObjects = kPoolSize; - TestObject * lObject = nullptr; - TestContext & lContext = *static_cast(aContext); - chip::System::Stats::count_t lNumInUse; - chip::System::Stats::count_t lHighWatermark; - - // Take all objects one at a time and check the watermark - // increases monotonically - for (int i = 0; i < kNumObjects; ++i) - { - lObject = sPool.TryCreate(); - - NL_TEST_ASSERT(lContext.mTestSuite, lObject->IsRetained()); - - sPool.GetStatistics(lNumInUse, lHighWatermark); - NL_TEST_ASSERT(lContext.mTestSuite, lNumInUse == (i + 1)); - NL_TEST_ASSERT(lContext.mTestSuite, lHighWatermark == lNumInUse); - - lObject->Init(); - } - - // Fail an allocation and check that both stats don't change - NL_TEST_ASSERT(lContext.mTestSuite, sPool.TryCreate() == nullptr); - - sPool.GetStatistics(lNumInUse, lHighWatermark); - NL_TEST_ASSERT(lContext.mTestSuite, lNumInUse == kNumObjects); - NL_TEST_ASSERT(lContext.mTestSuite, lHighWatermark == kNumObjects); - - // Free the last object and check that the watermark does not - // change. - lObject->Release(); - NL_TEST_ASSERT(lContext.mTestSuite, !lObject->IsRetained()); - - sPool.GetStatistics(lNumInUse, lHighWatermark); - NL_TEST_ASSERT(lContext.mTestSuite, lNumInUse == (kNumObjects - 1)); - NL_TEST_ASSERT(lContext.mTestSuite, lHighWatermark == kNumObjects); -} -#endif // !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - -// Test Suite - -/** - * Test Suite. It lists all the test functions. - */ -// clang-format off -static const nlTest sTests[] = -{ - NL_TEST_DEF("Iteration", TestObject::CheckIteration), - NL_TEST_DEF("Retention", TestObject::CheckRetention), - NL_TEST_DEF("Concurrency", TestObject::CheckConcurrency), -#if !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP - NL_TEST_DEF("HighWatermark", TestObject::CheckHighWatermark), - NL_TEST_DEF("HighWatermarkConcurrency", TestObject::CheckHighWatermarkConcurrency), -#endif - NL_TEST_SENTINEL() -}; - -static nlTestSuite sTestSuite = -{ - "chip-system-object", - &sTests[0], - Initialize, - Finalize -}; -// clang-format on - -/** - * Initialize the test suite. - */ -static int Initialize(void * aContext) -{ - TestContext & lContext = *reinterpret_cast(aContext); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_VERSION_MAJOR <= 2 && LWIP_VERSION_MINOR < 1 - static sys_mbox_t * sLwIPEventQueue = NULL; - - if (sLwIPEventQueue == NULL) - { - sys_mbox_new(sLwIPEventQueue, 100); - } -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - lContext.mTestSuite = &sTestSuite; - lContext.mAccumulator = 0; - - return SUCCESS; -} - -/** - * Finalize the test suite. - */ -static int Finalize(void * aContext) -{ - TestContext & lContext = *reinterpret_cast(aContext); - - lContext.mTestSuite = nullptr; - - return SUCCESS; -} - -} // namespace System -} // namespace chip - -int TestSystemObject(void) -{ - // Initialize standard pseudo-random number generator - srand(0); - - // Run test suit againt one lContext. - nlTestRunner(&sTestSuite, &chip::System::sContext); - - return nlTestRunnerStats(&sTestSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestSystemObject) diff --git a/src/transport/raw/tests/TestTCP.cpp b/src/transport/raw/tests/TestTCP.cpp index 5266c79a7632ea..a49f2bc69b86e0 100644 --- a/src/transport/raw/tests/TestTCP.cpp +++ b/src/transport/raw/tests/TestTCP.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include