From ada03e61594626affab424b36b5c4fd1f98e42f3 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 22 Nov 2024 18:53:45 -0800 Subject: [PATCH] [num-utils] add `DivideAndRoundUp()` helper (#10960) This commit introduces the `DivideAndRoundUp()` method, which divides two given unsigned integers and always rounds the result up. --- src/core/common/num_utils.hpp | 15 +++++++++++++++ src/core/mac/wakeup_tx_scheduler.cpp | 7 ++++++- src/core/net/ip6_address.cpp | 2 +- src/core/net/nd6.hpp | 2 +- src/core/thread/csl_tx_scheduler.cpp | 15 +++++++++++---- tests/unit/test_serial_number.cpp | 14 ++++++++++++++ 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/core/common/num_utils.hpp b/src/core/common/num_utils.hpp index d79491827..726cba712 100644 --- a/src/core/common/num_utils.hpp +++ b/src/core/common/num_utils.hpp @@ -195,6 +195,21 @@ template inline IntType DivideAndRoundToClosest(IntType aDivi return (aDividend + (aDivisor / 2)) / aDivisor; } +/** + * This template function divides two numbers and always rounds the result up. + * + * @tparam IntType The integer type. + * + * @param[in] aDividend The dividend value. + * @param[in] aDivisor The divisor value. + * + * @return The result of division and rounding up. + */ +template inline IntType DivideAndRoundUp(IntType aDividend, IntType aDivisor) +{ + return (aDividend + (aDivisor - 1)) / aDivisor; +} + /** * Casts a given `uint32_t` to `unsigned long`. * diff --git a/src/core/mac/wakeup_tx_scheduler.cpp b/src/core/mac/wakeup_tx_scheduler.cpp index 8d60c2b71..17816ee34 100644 --- a/src/core/mac/wakeup_tx_scheduler.cpp +++ b/src/core/mac/wakeup_tx_scheduler.cpp @@ -160,7 +160,12 @@ void WakeupTxScheduler::UpdateFrameRequestAhead(void) uint32_t busSpeedHz = Get().GetBusSpeed(); uint32_t busLatency = Get().GetBusLatency(); - uint32_t busTxTimeUs = ((busSpeedHz == 0) ? 0 : (kWakeupFrameWeight * 8 * 1000000 + busSpeedHz - 1) / busSpeedHz); + uint32_t busTxTimeUs = 0; + + if (busSpeedHz != 0) + { + busSpeedHz = DivideAndRoundUp(kWakeupFrameWeight * 8 * 1000000, busSpeedHz); + } mTxRequestAheadTimeUs = OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + busTxTimeUs + busLatency; } diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp index e66c0c93e..47ca92ef4 100644 --- a/src/core/net/ip6_address.cpp +++ b/src/core/net/ip6_address.cpp @@ -204,7 +204,7 @@ void Prefix::ToString(char *aBuffer, uint16_t aSize) const void Prefix::ToString(StringWriter &aWriter) const { - uint8_t sizeInUint16 = (GetBytesSize() + sizeof(uint16_t) - 1) / sizeof(uint16_t); + uint8_t sizeInUint16 = DivideAndRoundUp(GetBytesSize(), sizeof(uint16_t)); Prefix tidyPrefix = *this; tidyPrefix.Tidy(); diff --git a/src/core/net/nd6.hpp b/src/core/net/nd6.hpp index 0bb7e7fae..6514481c5 100644 --- a/src/core/net/nd6.hpp +++ b/src/core/net/nd6.hpp @@ -108,7 +108,7 @@ public: * * @param[in] aSize The size of option in bytes. */ - void SetSize(uint16_t aSize) { mLength = static_cast((aSize + kLengthUnit - 1) / kLengthUnit); } + void SetSize(uint16_t aSize) { mLength = static_cast(DivideAndRoundUp(aSize, kLengthUnit)); } /** * Returns the size of the option in bytes. diff --git a/src/core/thread/csl_tx_scheduler.cpp b/src/core/thread/csl_tx_scheduler.cpp index ab079bd61..956c70f73 100644 --- a/src/core/thread/csl_tx_scheduler.cpp +++ b/src/core/thread/csl_tx_scheduler.cpp @@ -49,13 +49,20 @@ void CslTxScheduler::UpdateFrameRequestAhead(void) { uint32_t busSpeedHz = Get().GetBusSpeed(); uint32_t busLatency = Get().GetBusLatency(); + uint32_t busTxTime = 0; - // longest frame on bus is 127 bytes with some metadata, use 150 bytes for bus Tx time estimation - uint32_t busTxTimeUs = ((busSpeedHz == 0) ? 0 : (150 * 8 * 1000000 + busSpeedHz - 1) / busSpeedHz); + if (busSpeedHz != 0) + { + // Longest frame on bus is 127 bytes with some metadata, we use + // 150 bytes for bus Tx time estimation + + busTxTime = DivideAndRoundUp(150 * 8 * 1000000, busSpeedHz); + } + + mCslFrameRequestAheadUs = OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + busTxTime + busLatency; - mCslFrameRequestAheadUs = OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + busTxTimeUs + busLatency; LogInfo("Bus TX Time: %lu usec, Latency: %lu usec. Calculated CSL Frame Request Ahead: %lu usec", - ToUlong(busTxTimeUs), ToUlong(busLatency), ToUlong(mCslFrameRequestAheadUs)); + ToUlong(busTxTime), ToUlong(busLatency), ToUlong(mCslFrameRequestAheadUs)); } void CslTxScheduler::Update(void) diff --git a/tests/unit/test_serial_number.cpp b/tests/unit/test_serial_number.cpp index df5f11851..cc80e7b2f 100644 --- a/tests/unit/test_serial_number.cpp +++ b/tests/unit/test_serial_number.cpp @@ -132,6 +132,20 @@ void TestNumUtils(void) VerifyOrQuit(DivideAndRoundToClosest(9, 10) == 1); VerifyOrQuit(DivideAndRoundToClosest(10, 10) == 1); + VerifyOrQuit(DivideAndRoundUp(2, 1) == 2); + VerifyOrQuit(DivideAndRoundUp(1, 3) == 1); + VerifyOrQuit(DivideAndRoundUp(1, 2) == 1); + VerifyOrQuit(DivideAndRoundUp(2, 3) == 1); + VerifyOrQuit(DivideAndRoundUp(3, 2) == 2); + VerifyOrQuit(DivideAndRoundUp(4, 2) == 2); + + VerifyOrQuit(DivideAndRoundUp(0, 10) == 0); + VerifyOrQuit(DivideAndRoundUp(4, 10) == 1); + VerifyOrQuit(DivideAndRoundUp(5, 10) == 1); + VerifyOrQuit(DivideAndRoundUp(9, 10) == 1); + VerifyOrQuit(DivideAndRoundUp(10, 10) == 1); + VerifyOrQuit(DivideAndRoundUp(11, 10) == 2); + VerifyOrQuit(CountBitsInMask(0) == 0); VerifyOrQuit(CountBitsInMask(1) == 1); VerifyOrQuit(CountBitsInMask(2) == 1);