From 4c6801ad73e296fb34212202f65df703e0206369 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 17 Oct 2018 04:23:30 -0700 Subject: [PATCH] [mac] invoke HandleTransmitDone from tasklet in case OT_ERROR_ABORT (#3173) This commit re-uses the `mOperationTask` tasklet (in addition to it being used for starting a scheduled MAC operation) to invoke the `HandleTransmitDone()` in case of `OT_ERROR_ABORT` failure. This ensures that frame retransmission attempt (in case of back-to-back failures) are not done through the same long call chain. --- src/core/mac/mac.cpp | 33 +++++++++++++++++++++++++++++---- src/core/mac/mac.hpp | 6 ++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index ffe8c45c6..600d2f94c 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -160,10 +160,11 @@ Mac::Mac(Instance &aInstance) , mPendingWaitingForData(false) , mRxOnWhenIdle(false) , mBeaconsEnabled(false) + , mTransmitAborted(false) #if OPENTHREAD_CONFIG_STAY_AWAKE_BETWEEN_FRAGMENTS , mDelaySleep(false) #endif - , mOperationTask(aInstance, &Mac::PerformOperation, this) + , mOperationTask(aInstance, &Mac::HandleOperationTask, this) , mMacTimer(aInstance, &Mac::HandleMacTimer, this) , mBackoffTimer(aInstance, &Mac::HandleBackoffTimer, this) , mReceiveTimer(aInstance, &Mac::HandleReceiveTimer, this) @@ -755,9 +756,29 @@ void Mac::StartOperation(Operation aOperation) } } -void Mac::PerformOperation(Tasklet &aTasklet) +void Mac::HandleOperationTask(Tasklet &aTasklet) { - aTasklet.GetOwner().PerformOperation(); + aTasklet.GetOwner().HandleOperationTask(); +} + +void Mac::HandleOperationTask(void) +{ + // `mOperationTask` tasklet is used for two separate purposes: + // + // 1) To invoke `HandleTransmitDone()` from a tasklet with + // `OT_ERROR_ABORT` error. + // + // 2) To perform a scheduled MAC operation. + + if (mTransmitAborted) + { + mTransmitAborted = false; + HandleTransmitDone(GetOperationFrame(), NULL, OT_ERROR_ABORT); + } + else + { + PerformOperation(); + } } void Mac::PerformOperation(void) @@ -1242,7 +1263,11 @@ exit: if (error != OT_ERROR_NONE) { - HandleTransmitDone(&sendFrame, NULL, OT_ERROR_ABORT); + // `HandleTrasnmitDone()` will be invoked from `mOperationTask` + // tasklet handler with error `OT_ERROR_ABORT`. + + mTransmitAborted = true; + mOperationTask.Post(); } } diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 96afe0c63..9c73a0775 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -977,6 +977,7 @@ private: void BeginTransmit(void); otError HandleMacCommand(Frame &aFrame); Frame * GetOperationFrame(void); + void PerformOperation(void); static void HandleMacTimer(Timer &aTimer); void HandleMacTimer(void); @@ -984,8 +985,8 @@ private: void HandleBackoffTimer(void); static void HandleReceiveTimer(Timer &aTimer); void HandleReceiveTimer(void); - static void PerformOperation(Tasklet &aTasklet); - void PerformOperation(void); + static void HandleOperationTask(Tasklet &aTasklet); + void HandleOperationTask(void); void StartCsmaBackoff(void); @@ -1021,6 +1022,7 @@ private: bool mPendingWaitingForData : 1; bool mRxOnWhenIdle : 1; bool mBeaconsEnabled : 1; + bool mTransmitAborted : 1; #if OPENTHREAD_CONFIG_STAY_AWAKE_BETWEEN_FRAGMENTS bool mDelaySleep : 1; #endif