From 2c612ec1dcdb2507a1e9aecd915a05980de037ad Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Fri, 8 Nov 2019 13:27:02 +0800 Subject: [PATCH] components/freertos: using the optimized task selection on esp32s2beta components/freertos: cleaned up multicore option scheduler. components/freertos: more cleanup and test optimization to present realistic results components/freertos: remove unused macros of optimized task selection when multicore is used --- .../include/freertos/FreeRTOSConfig.h | 4 --- components/freertos/tasks.c | 32 +++++++++---------- .../test/test_freertos_scheduling_time.c | 19 +++++++---- components/idf_test/include/idf_performance.h | 2 +- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 06c10b9db1..35370dd363 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -176,15 +176,11 @@ int xt_clock_freq(void) __attribute__((deprecated)); //#define configCPU_CLOCK_HZ 80000000 /* This has impact on speed of search for highest priority */ -#ifdef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifdef SMALL_TEST #define configMAX_PRIORITIES ( 7 ) #else #define configMAX_PRIORITIES ( 25 ) #endif -#else -#define configMAX_PRIORITIES ( 32 ) -#endif #ifndef CONFIG_APPTRACE_ENABLE #define configMINIMAL_STACK_SIZE 768 diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 06e681f7f2..1f89457ef5 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -368,7 +368,7 @@ PRIVILEGED_DATA static volatile BaseType_t xSwitchingContext[ portNUM_PROCESSORS \ /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ the same priority get an equal share of the processor time. */ \ - listGET_OWNER_OF_NEXT_ENTRY( xTaskGetCurrentTaskHandle(), &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[xPortGetCoreID()], &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \ } /* taskSELECT_HIGHEST_PRIORITY_TASK */ /*-----------------------------------------------------------*/ @@ -397,7 +397,7 @@ PRIVILEGED_DATA static volatile BaseType_t xSwitchingContext[ portNUM_PROCESSORS /* Find the highest priority queue that contains ready tasks. */ \ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ - listGET_OWNER_OF_NEXT_ENTRY( xTaskGetCurrentTaskHandle(), &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[xPortGetCoreID()], &( pxReadyTasksLists[ uxTopPriority ] ) ); \ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ /*-----------------------------------------------------------*/ @@ -2723,7 +2723,7 @@ void vTaskSwitchContext( void ) //Theoretically, this is only called from either the tick interrupt or the crosscore interrupt, so disabling //interrupts shouldn't be necessary anymore. Still, for safety we'll leave it in for now. int irqstate=portENTER_CRITICAL_NESTED(); - tskTCB * pxTCB; + if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context @@ -2782,16 +2782,12 @@ void vTaskSwitchContext( void ) vPortCPUAcquireMutex( &xTaskQueueMutex ); #endif +#if !CONFIG_FREERTOS_UNICORE unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead; unsigned portBASE_TYPE holdTop=pdFALSE; + tskTCB * pxTCB; -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - portBASE_TYPE uxDynamicTopReady; - portGET_HIGHEST_PRIORITY( uxDynamicTopReady, uxTopReadyPriority ); - portBASE_TYPE uxCopyOfTopReadyPrio = uxDynamicTopReady; -#else portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; -#endif /* * ToDo: This scheduler doesn't correctly implement the round-robin scheduling as done in the single-core * FreeRTOS stack when multiple tasks have the same priority and are all ready; it just keeps grabbing the @@ -2867,18 +2863,19 @@ void vTaskSwitchContext( void ) } } while ((ableToSchedule == pdFALSE) && (pxTCB != pxRefTCB)); } else { - if (!holdTop) { - #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - portRESET_READY_PRIORITY( uxCopyOfTopReadyPrio,uxTopReadyPriority ); - portGET_HIGHEST_PRIORITY( uxCopyOfTopReadyPrio,uxTopReadyPriority ); - #else - uxTopReadyPriority--; - #endif - } + if (!holdTop) uxTopReadyPriority--; } --uxDynamicTopReady; } +#else + //For Unicore targets we can keep the current FreeRTOS O(1) + //Scheduler. I hope to optimize better the scheduler for + //Multicore settings -- This will involve to create a per + //affinity ready task list which will impact hugely on + //tasks module + taskSELECT_HIGHEST_PRIORITY_TASK(); +#endif traceTASK_SWITCHED_IN(); xSwitchingContext[ xPortGetCoreID() ] = pdFALSE; @@ -2890,6 +2887,7 @@ void vTaskSwitchContext( void ) vPortCPUReleaseMutex( &xTaskQueueMutex ); #endif + #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK vPortSetStackWatchpoint(pxCurrentTCB[xPortGetCoreID()]->pxStack); #endif diff --git a/components/freertos/test/test_freertos_scheduling_time.c b/components/freertos/test/test_freertos_scheduling_time.c index 68f8468003..1670f520e7 100644 --- a/components/freertos/test/test_freertos_scheduling_time.c +++ b/components/freertos/test/test_freertos_scheduling_time.c @@ -12,16 +12,16 @@ #include "test_utils.h" typedef struct { - uint32_t noof_runs; SemaphoreHandle_t end_sema; uint32_t before_sched; uint32_t cycles_to_sched; + TaskHandle_t t1_handle; } test_context_t; static void test_task_1(void *arg) { test_context_t *context = (test_context_t *)arg; - for(context->noof_runs = 0 ;context->noof_runs < 10000; ) { + for( ;; ) { context->before_sched = portGET_RUN_TIME_COUNTER_VALUE(); vPortYield(); } @@ -31,13 +31,15 @@ static void test_task_1(void *arg) { static void test_task_2(void *arg) { test_context_t *context = (test_context_t *)arg; + uint32_t accumulator = 0; - for( ; context->noof_runs < 10000; context->noof_runs++) { - context->cycles_to_sched += (portGET_RUN_TIME_COUNTER_VALUE() - context->before_sched); + for(int i = 0; i < 10000; i++) { + accumulator += (portGET_RUN_TIME_COUNTER_VALUE() - context->before_sched); vPortYield(); } - context->cycles_to_sched /= 10000; + context->cycles_to_sched = accumulator / 10000; + vTaskDelete(context->t1_handle); xSemaphoreGive(context->end_sema); vTaskDelete(NULL); } @@ -49,8 +51,13 @@ TEST_CASE("scheduling time test", "[freertos]") context.end_sema = xSemaphoreCreateBinary(); TEST_ASSERT(context.end_sema != NULL); - xTaskCreatePinnedToCore(test_task_1, "test1" , 4096, &context, 1, NULL,1); +#if !CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(test_task_1, "test1" , 4096, &context, 1, &context.t1_handle,1); xTaskCreatePinnedToCore(test_task_2, "test2" , 4096, &context, 1, NULL,1); +#else + xTaskCreatePinnedToCore(test_task_1, "test1" , 4096, &context, 1, &context.t1_handle,0); + xTaskCreatePinnedToCore(test_task_2, "test2" , 4096, &context, 1, NULL,0); +#endif BaseType_t result = xSemaphoreTake(context.end_sema, portMAX_DELAY); TEST_ASSERT_EQUAL_HEX32(pdTRUE, result); diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index f5ddd9a145..0aea1b3506 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -77,4 +77,4 @@ #endif //CONFIG_IDF_TARGET_ESP32S2BETA //time to perform the task selection plus context switch (from task) -#define IDF_PERFORMANCE_MAX_SCHEDULING_TIME 4500 +#define IDF_PERFORMANCE_MAX_SCHEDULING_TIME 1500