From 8367f009235a6754f6b25ed1ef0a33090b4b922e Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Fri, 13 Nov 2020 10:37:51 +0800 Subject: [PATCH] [memory] use heap for messages (#5792) This commit adds an option to allow share heap memory with message buffer pool. For MTD, there is usually no border agent or commissioner service. This change allows the heap for meshcop to be used by application or network management data after the device is attached. Thus the total memory usage can be reduced. --- .github/workflows/simulation.yml | 4 + etc/cmake/options.cmake | 5 ++ etc/gn/openthread.gni | 3 + examples/common-switches.mk | 5 ++ script/check-size | 1 + script/test | 4 +- src/core/BUILD.gn | 4 + src/core/common/message.cpp | 73 +++++++------------ src/core/common/message.hpp | 4 +- .../config/openthread-core-config-check.h | 9 +++ .../config/openthread-core-default-config.h | 12 +++ tests/toranj/openthread-core-toranj-config.h | 8 ++ 12 files changed, 82 insertions(+), 50 deletions(-) diff --git a/.github/workflows/simulation.yml b/.github/workflows/simulation.yml index 674afed25..831a9181e 100644 --- a/.github/workflows/simulation.yml +++ b/.github/workflows/simulation.yml @@ -194,6 +194,9 @@ jobs: cli-mtd: runs-on: ubuntu-18.04 + strategy: + matrix: + message_use_heap: [0, 1] env: CFLAGS: -m32 CXXFLAGS: -m32 @@ -202,6 +205,7 @@ jobs: REFERENCE_DEVICE: 1 USE_MTD: 1 VIRTUAL_TIME: 1 + MESSAGE_USE_HEAP: ${{ matrix.message_use_heap }} steps: - uses: actions/checkout@v2 - name: Bootstrap diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index ce0c180fe..ea3479006 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -146,6 +146,11 @@ if(OT_DUA) target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DUA_ENABLE=1") endif() +option(OT_MESSAGE_USE_HEAP "enable heap allocator for message buffers") +if(OT_MESSAGE_USE_HEAP) + target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1") +endif() + option(OT_MLR "enable Multicast Listener Registration feature for Thread 1.2") if(OT_MLR) target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_MLR_ENABLE=1") diff --git a/etc/gn/openthread.gni b/etc/gn/openthread.gni index 68ede5dc8..e69261201 100644 --- a/etc/gn/openthread.gni +++ b/etc/gn/openthread.gni @@ -162,6 +162,9 @@ if (openthread_enable_core_config_args) { # Enable mac filter support openthread_config_mac_filter_enable = false + # Enable use built-in heap for message buffers + openthread_config_message_use_heap = false + # Enable MLE long routes extension (experimental, breaks Thread conformance] openthread_config_mle_long_routes_enable = false diff --git a/examples/common-switches.mk b/examples/common-switches.mk index 0649a61e0..a9630c18d 100644 --- a/examples/common-switches.mk +++ b/examples/common-switches.mk @@ -61,6 +61,7 @@ LOG_OUTPUT ?= APP endif LINK_RAW ?= 0 MAC_FILTER ?= 0 +MESSAGE_USE_HEAP ?= 0 MLE_LONG_ROUTES ?= 0 MLR ?= 0 MTD_NETDIAG ?= 0 @@ -214,6 +215,10 @@ ifeq ($(MAC_FILTER),1) COMMONCFLAGS += -DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1 endif +ifeq ($(MESSAGE_USE_HEAP),1) +COMMONCFLAGS += -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1 +endif + # Enable MLE long routes extension (experimental, breaks Thread conformance) ifeq ($(MLE_LONG_ROUTES),1) COMMONCFLAGS += -DOPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE=1 diff --git a/script/check-size b/script/check-size index 4387e5432..bd1a554a9 100755 --- a/script/check-size +++ b/script/check-size @@ -120,6 +120,7 @@ size_nrf52840_version() "JOINER=1" "LINK_RAW=1" "MAC_FILTER=1" + "MESSAGE_USE_HEAP=1" "MTD_NETDIAG=1" "SERVICE=1" "SLAAC=1" diff --git a/script/test b/script/test index 7de8fe87e..80b328cd0 100755 --- a/script/test +++ b/script/test @@ -48,7 +48,7 @@ readonly VERBOSE="${VERBOSE:-0}" build_simulation() { local version="$1" - local options=("-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON" "-DOT_REFERENCE_DEVICE=ON") + local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON" "-DOT_REFERENCE_DEVICE=ON") if [[ ${version} == "1.2" ]]; then options+=("-DOT_DUA=ON") @@ -87,7 +87,7 @@ build_simulation() build_posix() { local version="$1" - local options=("-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON") + local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON") if [[ ${version} == "1.2" ]]; then options+=("-DOT_DUA=ON") diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index d6e565d44..859a19935 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -176,6 +176,10 @@ if (openthread_enable_core_config_args) { defines += [ "OPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1" ] } + if (openthread_config_message_use_heap) { + defines += [ "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1" ] + } + if (openthread_config_mle_long_routes_enable) { defines += [ "OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE=1" ] } diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp index 54e582604..1f1bfe9cb 100644 --- a/src/core/common/message.cpp +++ b/src/core/common/message.cpp @@ -41,11 +41,12 @@ #include "net/checksum.hpp" #include "net/ip6.hpp" +#if OPENTHREAD_MTD || OPENTHREAD_FTD namespace ot { MessagePool::MessagePool(Instance &aInstance) : InstanceLocator(aInstance) -#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT +#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE , mNumFreeBuffers(kNumBuffers) #endif { @@ -103,21 +104,24 @@ Buffer *MessagePool::NewBuffer(Message::Priority aPriority) { Buffer *buffer = nullptr; - SuccessOrExit(ReclaimBuffers(1, aPriority)); - -#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT - - buffer = static_cast(otPlatMessagePoolNew(&GetInstance())); - + while (( +#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE + buffer = static_cast(GetInstance().HeapCAlloc(sizeof(Buffer), 1)) +#elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT + buffer = static_cast(otPlatMessagePoolNew(&GetInstance())) #else - - buffer = mBufferPool.Allocate(); - VerifyOrExit(buffer != nullptr); - - mNumFreeBuffers--; - buffer->SetNextBuffer(nullptr); - + buffer = mBufferPool.Allocate() #endif + ) == nullptr) + { + SuccessOrExit(ReclaimBuffers(aPriority)); + } + +#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE + mNumFreeBuffers--; +#endif + + buffer->SetNextBuffer(nullptr); exit: if (buffer == nullptr) @@ -133,7 +137,9 @@ void MessagePool::FreeBuffers(Buffer *aBuffer) while (aBuffer != nullptr) { Buffer *next = aBuffer->GetNextBuffer(); -#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT +#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE + GetInstance().HeapFree(aBuffer); +#elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT otPlatMessagePoolFree(&GetInstance(), aBuffer); #else mBufferPool.Free(*aBuffer); @@ -143,30 +149,18 @@ void MessagePool::FreeBuffers(Buffer *aBuffer) } } -otError MessagePool::ReclaimBuffers(int aNumBuffers, Message::Priority aPriority) +otError MessagePool::ReclaimBuffers(Message::Priority aPriority) { -#if OPENTHREAD_MTD || OPENTHREAD_FTD - while (aNumBuffers > GetFreeBufferCount()) - { - SuccessOrExit(Get().EvictMessage(aPriority)); - } - -exit: -#else - OT_UNUSED_VARIABLE(aPriority); -#endif - - // First comparison is to get around issues with comparing - // signed and unsigned numbers, if aNumBuffers is negative then - // the second comparison wont be attempted. - return (aNumBuffers < 0 || aNumBuffers <= GetFreeBufferCount()) ? OT_ERROR_NONE : OT_ERROR_NO_BUFS; + return Get().EvictMessage(aPriority); } uint16_t MessagePool::GetFreeBufferCount(void) const { uint16_t rval; -#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT +#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE + rval = static_cast(GetInstance().GetHeap().GetFreeSize() / sizeof(Buffer)); +#elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT rval = otPlatMessagePoolNumFreeBuffers(&GetInstance()); #else rval = mNumFreeBuffers; @@ -254,23 +248,9 @@ otError Message::SetLength(uint16_t aLength) { otError error = OT_ERROR_NONE; uint16_t totalLengthRequest = GetReserved() + aLength; - uint16_t totalLengthCurrent = GetReserved() + GetLength(); - int bufs = 0; VerifyOrExit(totalLengthRequest >= GetReserved(), error = OT_ERROR_INVALID_ARGS); - if (totalLengthRequest > kHeadBufferDataSize) - { - bufs = (((totalLengthRequest - kHeadBufferDataSize) - 1) / kBufferDataSize) + 1; - } - - if (totalLengthCurrent > kHeadBufferDataSize) - { - bufs -= (((totalLengthCurrent - kHeadBufferDataSize) - 1) / kBufferDataSize) + 1; - } - - SuccessOrExit(error = GetMessagePool()->ReclaimBuffers(bufs, GetPriority())); - SuccessOrExit(error = ResizeMessage(totalLengthRequest)); GetMetadata().mLength = aLength; @@ -871,3 +851,4 @@ void PriorityQueue::GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) con } } // namespace ot +#endif // OPENTHREAD_MTD || OPENTHREAD_FTD diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index 10b602a68..e98072dae 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -1471,9 +1471,9 @@ public: private: Buffer *NewBuffer(Message::Priority aPriority); void FreeBuffers(Buffer *aBuffer); - otError ReclaimBuffers(int aNumBuffers, Message::Priority aPriority); + otError ReclaimBuffers(Message::Priority aPriority); -#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT == 0 +#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE uint16_t mNumFreeBuffers; Pool mBufferPool; #endif diff --git a/src/core/config/openthread-core-config-check.h b/src/core/config/openthread-core-config-check.h index c3cf4f5ac..aefd661df 100644 --- a/src/core/config/openthread-core-config-check.h +++ b/src/core/config/openthread-core-config-check.h @@ -546,4 +546,13 @@ "(and OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY)" #endif +#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE +#if !OPENTHREAD_CONFIG_DTLS_ENABLE +#error "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE is strongly discouraged when OPENTHREAD_CONFIG_DTLS_ENABLE is off." +#endif +#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT +#error "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE conflicts with OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT." +#endif +#endif + #endif // OPENTHREAD_CORE_CONFIG_CHECK_H_ diff --git a/src/core/config/openthread-core-default-config.h b/src/core/config/openthread-core-default-config.h index d67c500fb..d8b1a2e42 100644 --- a/src/core/config/openthread-core-default-config.h +++ b/src/core/config/openthread-core-default-config.h @@ -127,6 +127,18 @@ #define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE + * + * Whether use heap allocator for message buffers. + * + * @note If this is set, OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS is ignored. + * + */ +#ifndef OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE +#define OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE 0 +#endif + /** * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS * diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index 5b8d0ef31..df9d8dfca 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -119,6 +119,14 @@ */ #define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 256 +/** + * @def OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE + * + * Whether use heap allocator for message buffers. + * + */ +#define OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE 1 + /** * @def OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES *