-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize xTaskIncrementTick for configNUMBER_OF_CORES > 1 #1118
Conversation
tasks.c
Outdated
@@ -4699,7 +4699,7 @@ BaseType_t xTaskIncrementTick( void ) | |||
BaseType_t xSwitchRequired = pdFALSE; | |||
|
|||
#if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) | |||
BaseType_t xYieldRequiredForCore[ configNUMBER_OF_CORES ] = { pdFALSE }; | |||
BaseType_t xYieldRequiredForCore[ configNUMBER_OF_CORES ] = { [ 0 ... configNUMBER_OF_CORES ] = pdFALSE }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not C89 syntax but GNU extension which we cannot use because FreeRTOS is used with a variety of compilers. Please use a loop to initialize the array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an existing loop where this change would fit nicely.
Existing Code:
for( xCoreID = 0; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ); xCoreID++ )
{
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U )
{
xYieldRequiredForCore[ xCoreID ] = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
Proposed Code:
for( xCoreID = 0; xCoreID < ( ( BaseType_t ) configNUMBER_OF_CORES ); xCoreID++ )
{
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U )
{
xYieldRequiredForCore[ xCoreID ] = pdTRUE;
}
else
{
xYieldRequiredForCore[ xCoreID ] = pdFALSE;
}
}
EDIT: Just reviewed the configuration options and found something unexpected. The code I propose above requires that we also resolve what seems to be a small inconsistency in the way we use configUSE_TIME_SLICING
. The loop above runs only when configUSE_TIME_SLICING
is 1, but the loop later that checks the array to induce the yields runs even if configUSE_TIME_SLICING is 0. That's fine of course, but the code I propose above requires that we add the extra condition (configUSE_TIME_SLICING == 1
) on the later loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi @aggarg , @jefftenney
Thank you for your valuable suggestions. I have made the changes based on your recommendations. Kindly assist with the review.
269eda9
to
c377beb
Compare
tasks.c
Outdated
if( ( xYieldRequiredForCore[ xCoreID ] != pdFALSE ) || ( xYieldPendings[ xCoreID ] != pdFALSE ) ) | ||
#else | ||
if( xYieldPendings[ xCoreID ] != pdFALSE ) | ||
#endif /* #if ( configUSE_TIME_SLICING == 1 ) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine to me now, but can't help but wonder if we should eliminate xYieldRequiredForCore
altogether. (Sorry for not seeing this earlier.) The code above that sets xYieldRequiredForCore[ xCoreID ]
would just set xYieldPendings[ xCoreID ]
instead, leaving the original test-coverage marker in the "else" case. Would you mind investigating that possibility? Any concerns @aggarg?
73c2277
to
b7a7636
Compare
The original implementation only initializes the first variable. After executing xTaskIncrementTick, the schedule might not behave as expected. When configUSE_PREEMPTION == 1 & configUSE_TIME_SLICING == 1, replace setting xYieldRequiredForCore[ xCoreID ] with setting xYieldPendings[ xCoreID ]. And when configUSE_PREEMPTION == 1, simplify the check condition to only check xYieldPendings[ xCoreID ]. Signed-off-by: cymzier <cymb103u@cs.ccu.edu.tw>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. This PR resolves the issue of the uninitialized array, and it slightly increases performance too. The only functional difference I see is for a task with preemption disabled (via vTaskPreemptionDisable()
). For that task, a time-slicing yield is dropped before this PR and is delayed after this PR. We could see that as an improvement too.
Quality Gate passedIssues Measures |
Thanks for pointing that. It should be okay as the scheduler will not evict a task for which the preemption is disabled - https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/tasks.c#L1230. |
Description
The original implementation only initializes the first variable. After executing xTaskIncrement, the schedule might not behave as expected.
Test Steps
N/A
Checklist:
Related Issue
N/A
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.