From 88b6822ac18848aba663fec0f3510a1d9275b098 Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Thu, 19 Apr 2018 00:48:13 +0800 Subject: [PATCH] [utils] make heap for general use (#2667) * move heap into utils namespace * add api to get free space of heap --- src/core/Makefile.am | 4 ++-- src/core/common/instance.hpp | 10 ++++----- src/core/crypto/mbedtls.cpp | 5 ++--- src/core/openthread-core-default-config.h | 16 +++++++------- src/core/{crypto => utils}/heap.cpp | 18 ++++++++++++++-- src/core/{crypto => utils}/heap.hpp | 23 +++++++++++++------- tests/unit/Makefile.am | 4 ++-- tests/unit/test_heap.cpp | 26 +++++++++++++---------- 8 files changed, 65 insertions(+), 41 deletions(-) rename src/core/{crypto => utils}/heap.cpp (93%) rename src/core/{crypto => utils}/heap.hpp (94%) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 093467f76..fa775087f 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -135,7 +135,6 @@ SOURCES_COMMON = \ common/trickle_timer.cpp \ crypto/aes_ccm.cpp \ crypto/aes_ecb.cpp \ - crypto/heap.cpp \ crypto/hmac_sha256.cpp \ crypto/mbedtls.cpp \ crypto/pbkdf2_cmac.cpp \ @@ -196,6 +195,7 @@ SOURCES_COMMON = \ utils/channel_manager.cpp \ utils/channel_monitor.cpp \ utils/child_supervision.cpp \ + utils/heap.cpp \ utils/jam_detector.cpp \ utils/missing_strlcpy.c \ utils/missing_strlcat.c \ @@ -252,7 +252,6 @@ HEADERS_COMMON = \ common/trickle_timer.hpp \ crypto/aes_ccm.hpp \ crypto/aes_ecb.hpp \ - crypto/heap.hpp \ crypto/hmac_sha256.hpp \ crypto/mbedtls.hpp \ crypto/pbkdf2_cmac.h \ @@ -324,6 +323,7 @@ HEADERS_COMMON = \ utils/channel_monitor.hpp \ utils/child_supervision.hpp \ utils/slaac_address.hpp \ + utils/heap.hpp \ utils/jam_detector.hpp \ utils/wrap_stdbool.h \ utils/wrap_stdint.h \ diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index cbb9aab54..45ae38004 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -50,8 +50,8 @@ #include "coap/coap.hpp" #include "common/code_utils.hpp" #if !OPENTHREAD_ENABLE_MULTIPLE_INSTANCES -#include "crypto/heap.hpp" #include "crypto/mbedtls.hpp" +#include "utils/heap.hpp" #endif #include "common/notifier.hpp" #include "common/settings.hpp" @@ -275,12 +275,12 @@ public: #if !OPENTHREAD_ENABLE_MULTIPLE_INSTANCES /** - * This method returns a reference to the MbedTlsHeap object. + * This method returns a reference to the Heap object. * - * @returns A reference to the MbedTlsHeap object. + * @returns A reference to the Heap object. * */ - Crypto::Heap &GetMbedTlsHeap(void) { return mMbedTlsHeap; } + Utils::Heap &GetHeap(void) { return mHeap; } #endif /** @@ -386,7 +386,7 @@ private: #if !OPENTHREAD_ENABLE_MULTIPLE_INSTANCES Crypto::MbedTls mMbedTls; - Crypto::Heap mMbedTlsHeap; + Utils::Heap mHeap; #endif Ip6::Ip6 mIp6; diff --git a/src/core/crypto/mbedtls.cpp b/src/core/crypto/mbedtls.cpp index 8db43c5b5..c94ba39c2 100644 --- a/src/core/crypto/mbedtls.cpp +++ b/src/core/crypto/mbedtls.cpp @@ -35,7 +35,6 @@ #include -#include "heap.hpp" #include "common/instance.hpp" #if !OPENTHREAD_ENABLE_MULTIPLE_INSTANCES @@ -45,12 +44,12 @@ namespace Crypto { static void *CAlloc(size_t aCount, size_t aSize) { - return Instance::Get().GetMbedTlsHeap().CAlloc(aCount, aSize); + return Instance::Get().GetHeap().CAlloc(aCount, aSize); } static void Free(void *aPointer) { - Instance::Get().GetMbedTlsHeap().Free(aPointer); + Instance::Get().GetHeap().Free(aPointer); } MbedTls::MbedTls(void) diff --git a/src/core/openthread-core-default-config.h b/src/core/openthread-core-default-config.h index 207484f4d..c28fee747 100644 --- a/src/core/openthread-core-default-config.h +++ b/src/core/openthread-core-default-config.h @@ -989,23 +989,23 @@ #endif /** - * @def OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE + * @def OPENTHREAD_CONFIG_HEAP_SIZE * - * The size of mbedTLS heap buffer when DTLS is enabled. + * The size of heap buffer when DTLS is enabled. * */ -#ifndef OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE -#define OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE (1536 * sizeof(void *)) +#ifndef OPENTHREAD_CONFIG_HEAP_SIZE +#define OPENTHREAD_CONFIG_HEAP_SIZE (1536 * sizeof(void *)) #endif /** - * @def OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE_NO_DTLS + * @def OPENTHREAD_CONFIG_HEAP_SIZE_NO_DTLS * - * The size of mbedTLS heap buffer when DTLS is disabled. + * The size of heap buffer when DTLS is disabled. * */ -#ifndef OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE_NO_DTLS -#define OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE_NO_DTLS 384 +#ifndef OPENTHREAD_CONFIG_HEAP_SIZE_NO_DTLS +#define OPENTHREAD_CONFIG_HEAP_SIZE_NO_DTLS 384 #endif /** diff --git a/src/core/crypto/heap.cpp b/src/core/utils/heap.cpp similarity index 93% rename from src/core/crypto/heap.cpp rename to src/core/utils/heap.cpp index 2538dad62..e226e333d 100644 --- a/src/core/crypto/heap.cpp +++ b/src/core/utils/heap.cpp @@ -40,7 +40,7 @@ #include "common/code_utils.hpp" namespace ot { -namespace Crypto { +namespace Utils { Heap::Heap(void) { @@ -55,6 +55,8 @@ Heap::Heap(void) super.SetNext(BlockOffset(first)); first.SetNext(BlockOffset(guard)); + + mMemory.mFreeSize = kFirstBlockSize; } void *Heap::CAlloc(size_t aCount, size_t aSize) @@ -100,8 +102,12 @@ void *Heap::CAlloc(size_t aCount, size_t aSize) { BlockInsert(BlockSuper(), newBlock); } + + mMemory.mFreeSize -= sizeof(Block); } + mMemory.mFreeSize -= curr->GetSize(); + curr->SetNext(0); memset(curr->GetPointer(), 0, size); @@ -146,11 +152,15 @@ void Heap::Free(void *aPointer) Block &block = BlockOf(aPointer); Block &right = BlockRight(block); + mMemory.mFreeSize += block.GetSize(); + if (IsLeftFree(block)) { Block *prev = &BlockSuper(); Block *left = &BlockNext(*prev); + mMemory.mFreeSize += sizeof(Block); + for (const uint16_t offset = block.GetLeftNext(); left->GetNext() != offset; left = &BlockNext(*left)) { prev = left; @@ -162,6 +172,8 @@ void Heap::Free(void *aPointer) if (right.IsFree()) { + mMemory.mFreeSize += sizeof(Block); + if (right.GetSize() > left->GetSize()) { for (const uint16_t offset = BlockOffset(right); prev->GetNext() != offset; prev = &BlockNext(*prev)) @@ -193,6 +205,8 @@ void Heap::Free(void *aPointer) prev.SetNext(right.GetNext()); block.SetSize(block.GetSize() + right.GetSize() + sizeof(Block)); BlockInsert(prev, block); + + mMemory.mFreeSize += sizeof(Block); } else { @@ -201,5 +215,5 @@ void Heap::Free(void *aPointer) } } -} // namespace Crypto +} // namespace Utils } // namespace ot diff --git a/src/core/crypto/heap.hpp b/src/core/utils/heap.hpp similarity index 94% rename from src/core/crypto/heap.hpp rename to src/core/utils/heap.hpp index f268ce3b4..36bb5fad6 100644 --- a/src/core/crypto/heap.hpp +++ b/src/core/utils/heap.hpp @@ -42,7 +42,7 @@ #include "utils/wrap_stdint.h" namespace ot { -namespace Crypto { +namespace Utils { /** * This class represents a memory block. @@ -206,11 +206,12 @@ public: * This method returns whether the heap is clean. * */ - bool IsClean(void) + bool IsClean(void) const { - const Block &super = BlockSuper(); - const Block &first = BlockRight(super); - return super.GetNext() == BlockOffset(first) && first.GetSize() == kFirstBlockSize; + Heap & self = *const_cast(this); + const Block &super = self.BlockSuper(); + const Block &first = self.BlockRight(super); + return super.GetNext() == self.BlockOffset(first) && first.GetSize() == kFirstBlockSize; } /** @@ -219,13 +220,18 @@ public: */ size_t GetCapacity(void) const { return kFirstBlockSize; } + /** + * This method returns free space of this heap. + */ + size_t GetFreeSize(void) const { return mMemory.mFreeSize; } + private: enum { #if OPENTHREAD_ENABLE_DTLS - kMemorySize = OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE, ///< Size of memory buffer (bytes). + kMemorySize = OPENTHREAD_CONFIG_HEAP_SIZE, ///< Size of memory buffer (bytes). #else - kMemorySize = OPENTHREAD_CONFIG_MBEDTLS_HEAP_SIZE_NO_DTLS, ///< Size of memory buffer (bytes). + kMemorySize = OPENTHREAD_CONFIG_HEAP_SIZE_NO_DTLS, ///< Size of memory buffer (bytes). #endif kAlignSize = sizeof(long), ///< The alignment size. kBlockRemainderSize = kAlignSize - sizeof(uint16_t) * 2, ///< Block unit remainder size. @@ -331,6 +337,7 @@ private: union { + uint16_t mFreeSize; // Make sure memory is long aligned. long mLong[kMemorySize / sizeof(long)]; uint8_t m8[kMemorySize]; @@ -338,7 +345,7 @@ private: } mMemory; }; -} // namespace Crypto +} // namespace Utils } // namespace ot #endif // OT_HEAP_HPP_ diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index cd27f409f..43e4a2040 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -163,8 +163,8 @@ test_link_quality_SOURCES = test_platform.cpp test_link_quality.cpp test_lowpan_LDADD = $(COMMON_LDADD) test_lowpan_SOURCES = test_platform.cpp test_lowpan.cpp test_util.cpp -test_network_data_LDADD = $(COMMON_LDADD) -test_network_data_SOURCES = test_platform.cpp test_network_data.cpp +test_network_data_LDADD = $(COMMON_LDADD) +test_network_data_SOURCES = test_platform.cpp test_network_data.cpp test_mac_frame_LDADD = $(COMMON_LDADD) test_mac_frame_SOURCES = test_platform.cpp test_mac_frame.cpp diff --git a/tests/unit/test_heap.cpp b/tests/unit/test_heap.cpp index f91eac959..81fe90afb 100644 --- a/tests/unit/test_heap.cpp +++ b/tests/unit/test_heap.cpp @@ -28,7 +28,7 @@ #include -#include "core/crypto/heap.hpp" +#include "core/utils/heap.hpp" #include @@ -45,15 +45,17 @@ */ void TestAllocateSingle(void) { - ot::Crypto::Heap heap; + ot::Utils::Heap heap; + + const size_t totalSize = heap.GetFreeSize(); { void *p = heap.CAlloc(1, 0); - VerifyOrQuit(p == NULL, "TestAllocateSingle allocate 1 x 0 byte failed!\n"); + VerifyOrQuit(p == NULL && totalSize == heap.GetFreeSize(), "TestAllocateSingle allocate 1 x 0 byte failed!\n"); heap.Free(p); p = heap.CAlloc(0, 1); - VerifyOrQuit(p == NULL, "TestAllocateSingle allocate 0 x 1 byte failed!\n"); + VerifyOrQuit(p == NULL && totalSize == heap.GetFreeSize(), "TestAllocateSingle allocate 0 x 1 byte failed!\n"); heap.Free(p); } @@ -61,10 +63,10 @@ void TestAllocateSingle(void) { Log("%s allocating %zu bytes...", __func__, size); void *p = heap.CAlloc(1, size); - VerifyOrQuit(p != NULL && !heap.IsClean(), "allocating failed!\n"); + VerifyOrQuit(p != NULL && !heap.IsClean() && heap.GetFreeSize() + size <= totalSize, "allocating failed!\n"); memset(p, 0xff, size); heap.Free(p); - VerifyOrQuit(heap.IsClean(), "freeing failed!\n"); + VerifyOrQuit(heap.IsClean() && heap.GetFreeSize() == totalSize, "freeing failed!\n"); } } @@ -83,13 +85,14 @@ void TestAllocateRandomly(size_t aSizeLimit, unsigned int aSeed) size_t mSize; }; - ot::Crypto::Heap heap; - Node head; - size_t nnodes = 0; + ot::Utils::Heap heap; + Node head; + size_t nnodes = 0; srand(aSeed); - Node *last = &head; + const size_t totalSize = heap.GetFreeSize(); + Node * last = &head; do { @@ -146,7 +149,8 @@ void TestAllocateRandomly(size_t aSizeLimit, unsigned int aSeed) last = next; } - VerifyOrQuit(heap.IsClean(), "TestAllocateRandomly heap not clean after freeing all!\n"); + VerifyOrQuit(heap.IsClean() && heap.GetFreeSize() == totalSize, + "TestAllocateRandomly heap not clean after freeing all!\n"); } /**