From d4c82606fb4ba5e2c168f083a280b0176c549e34 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 6 Nov 2019 15:08:24 +0800 Subject: [PATCH] components/freertos: added and enabled the optimized task selection FreeRTOS have an platform dependent configuration to enable selection task in a optimized way. Provided the platform dependent functions in order to allow the scheduler to use the optimized algorithms by telling to the port layer where to found bitscan instruction i.e. NSAU. This closes IDF-1116 components/freertos: added option to disable the optimized scheduler --- components/freertos/Kconfig | 8 ++++++ .../include/freertos/FreeRTOSConfig.h | 8 ++++++ .../freertos/include/freertos/portmacro.h | 26 +++++++++++++++++++ components/freertos/tasks.c | 17 ++++++++++-- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 198722331b..06f84e70b2 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -39,6 +39,14 @@ menu "FreeRTOS" endchoice + config FREERTOS_OPTIMIZED_SCHEDULER + bool "Enable FreeRTOS pĺatform optimized scheduler" + default y + help + On most platforms there are instructions can speedup the ready task + searching. Enabling this option the FreeRTOS with this instructions + support will be built + config FREERTOS_HZ int "Tick rate (Hz)" range 1 1000 diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index af4bf29b18..06c10b9db1 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -72,6 +72,10 @@ #include "sdkconfig.h" +/* enable use of optimized task selection by the scheduler */ +#ifdef CONFIG_FREERTOS_OPTIMIZED_SCHEDULER +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif /* ESP31 and ESP32 are dualcore processors. */ #ifndef CONFIG_FREERTOS_UNICORE @@ -172,11 +176,15 @@ 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/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index 010f60f250..eaa2d6603d 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -469,6 +469,32 @@ void vApplicationSleep( TickType_t xExpectedIdleTime ); #define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime ) +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + +/* Check the configuration. */ +#if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. +#endif + +/* Store/clear the ready priorities in a bit map. */ +#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) +#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + +/*-----------------------------------------------------------*/ + +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + // porttrace #if configUSE_TRACE_FACILITY_2 #include "porttrace.h" diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 564b4aa4b2..06e681f7f2 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -2783,9 +2783,15 @@ void vTaskSwitchContext( void ) #endif unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead; - portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; unsigned portBASE_TYPE holdTop=pdFALSE; +#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 @@ -2861,7 +2867,14 @@ void vTaskSwitchContext( void ) } } while ((ableToSchedule == pdFALSE) && (pxTCB != pxRefTCB)); } else { - if (!holdTop) --uxTopReadyPriority; + if (!holdTop) { + #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + portRESET_READY_PRIORITY( uxCopyOfTopReadyPrio,uxTopReadyPriority ); + portGET_HIGHEST_PRIORITY( uxCopyOfTopReadyPrio,uxTopReadyPriority ); + #else + uxTopReadyPriority--; + #endif + } } --uxDynamicTopReady; }