@@ -1206,6 +1206,16 @@ void WeaveExchangeManager::RetransPendingAppGroupMsgs(uint64_t peerNodeId)
12061206uint32_t WeaveExchangeManager::GetTickCounterFromTimeDelta (uint64_t newTime,
12071207 uint64_t oldTime)
12081208{
1209+ // Note on math: we have a utility function that will compute U64 var / U32
1210+ // compile-time const => U32. At the moment, we are leaving
1211+ // mWRMPTimerInterval as a member variable in WeaveExchangeManager, however,
1212+ // given its current usage, it could be replaced by a compile time const.
1213+ // Should we make that change, I would recommend making the timeDelta a u64,
1214+ // and replacing the plain 32-bit division below with the utility function.
1215+ // Note that the 32bit timeDelta overflows at around 46 days; pursuing the
1216+ // above code strategy would extend that overflow by a factor if 200 given
1217+ // the default mWRMPPTimerInterval. If and when such change is made, please
1218+ // update the comment around line 1426.
12091219 uint32_t timeDelta = static_cast <uint32_t >(newTime - oldTime);
12101220
12111221 return (timeDelta / mWRMPTimerInterval );
@@ -1334,7 +1344,7 @@ void WeaveExchangeManager::WRMPExpireTicks(void)
13341344{
13351345 uint64_t now = 0 ;
13361346 ExchangeContext* ec = NULL ;
1337- uint16_t deltaTicks;
1347+ uint32_t deltaTicks;
13381348
13391349 // Process Ack Tables for all ExchangeContexts
13401350 ec = (ExchangeContext *)ContextPool;
@@ -1345,8 +1355,14 @@ void WeaveExchangeManager::WRMPExpireTicks(void)
13451355 // to the previous tick. If we are between tick boundaries, the extra time since the
13461356 // last virtual tick is not accounted for here (it will be accounted for when resetting
13471357 // the WRMP timer)
1358+
13481359 deltaTicks = GetTickCounterFromTimeDelta (now, mWRMPTimeStampBase );
13491360
1361+ // Note on math involving deltaTicks: in the code below, deltaTicks, a
1362+ // 32-bit value, is being subtracted from 16-bit expiration times. In each
1363+ // case, we compare the expiration time prior to subtraction to guard
1364+ // against underflow.
1365+
13501366#if defined(WRMP_TICKLESS_DEBUG)
13511367 WeaveLogProgress (ExchangeManager, " WRMPExpireTicks at %" PRIu64 " , %" PRIu64 " , %u" , now, mWRMPTimeStampBase , deltaTicks);
13521368#endif
@@ -1408,11 +1424,15 @@ void WeaveExchangeManager::WRMPExpireTicks(void)
14081424
14091425 // Re-Adjust the base time stamp to the most recent tick boundary
14101426
1411- // Note on math: because we're really multiplying two 16-bit
1412- // unsigned numbers, we know that the result will fit in a 32-bit
1413- // unsigned without overflow. Consequently, casting operands to
1414- // 32-bit, and performing 32-bit multiplication is correct.
1415- mWRMPTimeStampBase += static_cast <uint64_t >( static_cast <uint32_t >(deltaTicks) * static_cast <uint32_t >(mWRMPTimerInterval ));
1427+ // Note on math: we cast deltaTicks to a 64bit value to ensure that that we
1428+ // produce a full 64 bit product. At the moment this is a bit of a moot
1429+ // conversion: right now, the math in GetTickCounterFromTimeDelta ensures
1430+ // that the deltaTicks * mWRMPTimerTick fits in 32bits. However, I'm
1431+ // leaving the math in this form, because I'm leaving the door open to
1432+ // refactoring the division in GetTickCounterFromTimeDelta to use our
1433+ // specialized utility function that computes U64 var/ U32 compile-time
1434+ // const ==> U32
1435+ mWRMPTimeStampBase += static_cast <uint64_t >(deltaTicks) * mWRMPTimerInterval ;
14161436#if defined(WRMP_TICKLESS_DEBUG)
14171437 WeaveLogProgress (ExchangeManager, " WRMPExpireTicks mWRMPTimeStampBase to %" PRIu64, mWRMPTimeStampBase );
14181438#endif
0 commit comments