diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt index c7fbf1e90..1da07d067 100644 --- a/.github/.cSpellWords.txt +++ b/.github/.cSpellWords.txt @@ -5012,6 +5012,7 @@ VRRSTEN VRRSTS VSDB VSYNC +VTASKLIST VTIR VTOFFR VTOR @@ -5340,6 +5341,7 @@ coremqtt cortexa coverity covfs +covg cpas cpbs cpcdis @@ -5402,6 +5404,7 @@ enetrg epage epdisc eqcfg +equalto equidistribution eret ethernetif @@ -5581,6 +5584,7 @@ lpstart lpthread lptr lsls +lteq ltorg ltry lums @@ -6049,10 +6053,14 @@ utilising utrhf utrhfgdghfg ux +uxdeletedtaskwaiting uxindex +uxpriority uxsource uxtab +uxtasknumber uxtb +uxtopreadypriority vactive vblank vcmp @@ -6120,6 +6128,7 @@ xfindobjectwithlabelandclass xfscompat xgetslotlist xheader +xidx xinitializepkcs xlarge xlength diff --git a/FreeRTOS/Source b/FreeRTOS/Source index 4ada1d7d5..5281427a9 160000 --- a/FreeRTOS/Source +++ b/FreeRTOS/Source @@ -1 +1 @@ -Subproject commit 4ada1d7d5e853f0f9415dc99cafae72eaf571b59 +Subproject commit 5281427a9942bf12d35240d388fcfe60fa7dd682 diff --git a/FreeRTOS/Test/CMock/Makefile b/FreeRTOS/Test/CMock/Makefile index 4aa947e1a..47b8433c2 100644 --- a/FreeRTOS/Test/CMock/Makefile +++ b/FreeRTOS/Test/CMock/Makefile @@ -14,6 +14,7 @@ UNITS += queue UNITS += stream_buffer UNITS += message_buffer UNITS += event_groups +UNITS += smp .PHONY: makefile.in diff --git a/FreeRTOS/Test/CMock/config/fake_infiniteloop.h b/FreeRTOS/Test/CMock/config/fake_infiniteloop.h new file mode 100644 index 000000000..ec4ce558d --- /dev/null +++ b/FreeRTOS/Test/CMock/config/fake_infiniteloop.h @@ -0,0 +1,32 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FAKE_INFINITE_LOOP_H +#define FAKE_INFINITE_LOOP_H + +int vFakeInfiniteLoop( void ); + +#endif /* FAKE_INFINITE_LOOP_H */ diff --git a/FreeRTOS/Test/CMock/config/fake_port.h b/FreeRTOS/Test/CMock/config/fake_port.h index 23fe5653b..d86d181ff 100644 --- a/FreeRTOS/Test/CMock/config/fake_port.h +++ b/FreeRTOS/Test/CMock/config/fake_port.h @@ -31,7 +31,8 @@ void vFakePortYield( void ); void vFakePortYieldFromISR( void ); void vFakePortYieldWithinAPI( void ); -void vFakePortDisableInterrupts( void ); +void vFakePortRestoreInterrupts( UBaseType_t ); +uint32_t vFakePortDisableInterrupts( void ); void vFakePortEnableInterrupts( void ); void vFakePortClearInterruptMaskFromISR( UBaseType_t uxNewMaskValue ); void vFakePortClearInterruptMask( UBaseType_t uxNewMaskValue ); @@ -44,7 +45,25 @@ void vFakePortEnterCriticalSection( void ); void vFakePortExitCriticalSection( void ); void vPortCurrentTaskDying( void * pxTaskToDelete, volatile BaseType_t * pxPendYield ); + +void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + void portSetupTCB_CB( void * tcb ); + +void vFakePortGetISRLock( void ); +void vFakePortReleaseISRLock( void ); +void vFakePortGetTaskLock( void ); +void vFakePortReleaseTaskLock( void ); + void vFakePortAssertIfISR(); +BaseType_t vFakePortCheckIfInISR( void ); + +unsigned int vFakePortGetCoreID( void ); +void vFakePortYieldCore( int ); + +portBASE_TYPE vFakePortEnterCriticalFromISR( void ); +void vFakePortExitCriticalFromISR( portBASE_TYPE uxSavedInterruptState ); + +void vFakePortAllocateSecureContext( BaseType_t stackSize ); #endif /* FAKE_PORT_H */ diff --git a/FreeRTOS/Test/CMock/config/portmacro.h b/FreeRTOS/Test/CMock/config/portmacro.h index bf028ab48..8c2e4abdb 100644 --- a/FreeRTOS/Test/CMock/config/portmacro.h +++ b/FreeRTOS/Test/CMock/config/portmacro.h @@ -81,6 +81,7 @@ typedef portSTACK_TYPE StackType_t; typedef long BaseType_t; typedef unsigned long UBaseType_t; + #if ( configUSE_16_BIT_TICKS == 1 ) typedef uint16_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffff @@ -93,6 +94,7 @@ typedef unsigned long UBaseType_t; /* Requires definition of UBaseType_t */ #include "fake_port.h" +#include /* Hardware specifics. */ #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) @@ -123,46 +125,70 @@ typedef unsigned long UBaseType_t; /*-----------------------------------------------------------*/ #define portSAVE_CONTEXT() -#define portYIELD() vFakePortYield() -#define portYIELD_WITHIN_API() vFakePortYieldWithinAPI() -#define portYIELD_FROM_ISR() vFakePortYieldFromISR() +#define portYIELD() vFakePortYield() +#define portYIELD_WITHIN_API() vFakePortYieldWithinAPI() +#define portYIELD_FROM_ISR() vFakePortYieldFromISR() /* Critical section handling. */ -#define portDISABLE_INTERRUPTS() vFakePortDisableInterrupts() -#define portENABLE_INTERRUPTS() vFakePortEnableInterrupts() +#define portDISABLE_INTERRUPTS() vFakePortDisableInterrupts() +#define portENABLE_INTERRUPTS() vFakePortEnableInterrupts() #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) \ vFakePortClearInterruptMaskFromISR( x ) #define portSET_INTERRUPT_MASK_FROM_ISR() \ ulFakePortSetInterruptMaskFromISR() -#define portSET_INTERRUPT_MASK() ulFakePortSetInterruptMask() -#define portCLEAR_INTERRUPT_MASK( x ) vFakePortClearInterruptMask( x ) +#define portSET_INTERRUPT_MASK() ulFakePortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK( x ) vFakePortClearInterruptMask( x ) #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() \ vFakePortAssertIfInterruptPriorityInvalid() -#define portENTER_CRITICAL() vFakePortEnterCriticalSection() -#define portEXIT_CRITICAL() vFakePortExitCriticalSection() +#define portENTER_CRITICAL() vFakePortEnterCriticalSection() +#define portEXIT_CRITICAL() vFakePortExitCriticalSection() +#define portGET_ISR_LOCK() vFakePortGetISRLock() +#define portRELEASE_ISR_LOCK() vFakePortReleaseISRLock() +#define portGET_TASK_LOCK() vFakePortGetTaskLock() +#define portRELEASE_TASK_LOCK() vFakePortReleaseTaskLock() +#define portCHECK_IF_IN_ISR() vFakePortCheckIfInISR() +#define portRESTORE_INTERRUPTS( x ) vFakePortRestoreInterrupts( x ) #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) \ vPortCurrentTaskDying( ( pvTaskToDelete ), ( pxPendYield ) ) -#define portSETUP_TCB( pxTCB ) portSetupTCB_CB( pxTCB ); -#define portASSERT_IF_IN_ISR() vFakePortAssertIfISR(); +#define portSETUP_TCB( pxTCB ) portSetupTCB_CB( pxTCB ); +#define portASSERT_IF_IN_ISR() vFakePortAssertIfISR(); -#define ucPortCountLeadingZeros( ulBitmap ) ( ( uint8_t ) __builtin_clz( ulBitmap ) ) +#define portGET_CORE_ID() vFakePortGetCoreID() +#define portYIELD_CORE( x ) vFakePortYieldCore( x ) -#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ +#define portENTER_CRITICAL_FROM_ISR vFakePortEnterCriticalFromISR +#define portEXIT_CRITICAL_FROM_ISR vFakePortExitCriticalFromISR + +#if ( configNUMBER_OF_CORES > 1 ) + #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) + #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#else + #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) \ + volatile int fool_static = 0; \ + void vFunction( void * ( pvParameters ) ) + + #define portTASK_FUNCTION( vFunction, pvParameters ) \ + volatile int fool_static2 = 0; \ + void vFunction( void * ( pvParameters ) ) +#endif + +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + static uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; + + ucReturn = __builtin_clz( ulBitmap ); + return ucReturn; + } + + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) -#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) -#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) - -/* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) \ - volatile int fool_static = 0; \ - void vFunction( void * ( pvParameters ) ) - -#define portTASK_FUNCTION( vFunction, pvParameters ) \ - volatile int fool_static2 = 0; \ - void vFunction( void * ( pvParameters ) ) +#endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) */ /* We need to define it here because CMock does not recognize the * #if ( portUSING_MPU_WRAPPERS == 1 ) guard around xTaskGetMPUSettings diff --git a/FreeRTOS/Test/CMock/makefile.in b/FreeRTOS/Test/CMock/makefile.in index d01539556..67b54e803 100644 --- a/FreeRTOS/Test/CMock/makefile.in +++ b/FreeRTOS/Test/CMock/makefile.in @@ -13,7 +13,7 @@ GENERATED_DIR := $(BUILD_DIR)/generated LIB_DIR := $(BUILD_DIR)/lib TOOLS_DIR := $(UT_ROOT_DIR)/tools -FREERTOS_DIR := $(abspath $(UT_ROOT_DIR)../../../FreeRTOS) +FREERTOS_DIR := $(abspath $(UT_ROOT_DIR)/../../../FreeRTOS) KERNEL_DIR := $(abspath $(UT_ROOT_DIR)/../../../FreeRTOS/Source) CMOCK_DIR := $(UT_ROOT_DIR)/CMock diff --git a/FreeRTOS/Test/CMock/message_buffer/message_buffer/message_buffer_utest.c b/FreeRTOS/Test/CMock/message_buffer/message_buffer/message_buffer_utest.c index 9af967d10..c87ffa1e9 100644 --- a/FreeRTOS/Test/CMock/message_buffer/message_buffer/message_buffer_utest.c +++ b/FreeRTOS/Test/CMock/message_buffer/message_buffer/message_buffer_utest.c @@ -255,6 +255,7 @@ static BaseType_t receiverTaskNotificationCallback( TaskHandle_t xTaskToNotify, /******************************************************************************* * Unity fixtures ******************************************************************************/ +/*! called before each test case */ void setUp( void ) { assertionFailed = 0; @@ -276,7 +277,7 @@ void setUp( void ) UnityMalloc_StartTest(); } -/*! called before each test case */ +/*! called after each test case */ void tearDown( void ) { TEST_ASSERT_EQUAL_MESSAGE( 0, assertionFailed, "Assertion check failed in code." ); diff --git a/FreeRTOS/Test/CMock/queue/generic/queue_receive_blocking_utest.c b/FreeRTOS/Test/CMock/queue/generic/queue_receive_blocking_utest.c index bd4c9719f..44ea6e1a1 100644 --- a/FreeRTOS/Test/CMock/queue/generic/queue_receive_blocking_utest.c +++ b/FreeRTOS/Test/CMock/queue/generic/queue_receive_blocking_utest.c @@ -70,6 +70,18 @@ int suiteTearDown( int numFailures ) /* ========================== Helper functions =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Test Cases ============================== */ /** @@ -108,6 +120,7 @@ void test_xQueueReceive_blocking_success_locked_no_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueReceive_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &td_task_xTaskResumeAllStub ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -140,6 +153,7 @@ void test_xQueuePeek_blocking_success_locked_no_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueReceive_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &td_task_xTaskResumeAllStub ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -196,6 +210,7 @@ void test_xQueueReceive_blocking_timeout_locked_high_prio_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueReceive_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &xQueueReceive_xTaskResumeAllCallback ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); @@ -236,6 +251,7 @@ void test_xQueuePeek_blocking_timeout_locked_high_prio_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueReceive_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &xQueueReceive_xTaskResumeAllCallback ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); @@ -276,6 +292,7 @@ void test_xQueueReceive_blocking_success_locked_low_prio_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueReceive_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &xQueueReceive_xTaskResumeAllCallback ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 ); @@ -312,6 +329,7 @@ void test_xQueuePeek_blocking_success_locked_low_prio_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueReceive_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &xQueueReceive_xTaskResumeAllCallback ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 ); @@ -345,6 +363,7 @@ void test_xQueuePeek_blocking_suspended_assert( void ) td_task_setSchedulerState( taskSCHEDULER_SUSPENDED ); vTaskSuspendAll_Stub( td_task_vTaskSuspendAllStubNoCheck ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -398,6 +417,7 @@ void test_xQueuePeek_blocking_success( void ) xQueueHandleStatic = xQueue; xTaskCheckForTimeOut_Stub( &blocking_success_xTaskCheckForTimeOut_cb ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -446,6 +466,7 @@ void test_xQueuePeek_blocking_success_last_chance( void ) xQueueHandleStatic = xQueue; xTaskCheckForTimeOut_Stub( &blocking_success_last_chance_xTaskCheckForTimeOut_cb ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -472,6 +493,8 @@ void test_xQueuePeek_blocking_timeout( void ) uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( pdFALSE, xQueuePeek( xQueue, &checkVal, TICKS_TO_WAIT ) ); TEST_ASSERT_EQUAL( 0, uxQueueMessagesWaiting( xQueue ) ); @@ -496,6 +519,7 @@ void test_xQueueReceive_blocking_suspended_assert( void ) uint32_t checkVal = INVALID_UINT32; fakeAssertExpectFail(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setSchedulerState( taskSCHEDULER_SUSPENDED ); @@ -528,6 +552,7 @@ void test_xQueueReceive_blocking_success( void ) xQueueHandleStatic = xQueue; xTaskCheckForTimeOut_Stub( &blocking_success_xTaskCheckForTimeOut_cb ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -558,6 +583,7 @@ void test_xQueueReceive_blocking_success_last_chance( void ) xQueueHandleStatic = xQueue; xTaskCheckForTimeOut_Stub( &blocking_success_last_chance_xTaskCheckForTimeOut_cb ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); uint32_t checkVal = INVALID_UINT32; @@ -584,6 +610,8 @@ void test_xQueueReceive_blocking_timeout( void ) uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( pdFALSE, xQueueReceive( xQueue, &checkVal, TICKS_TO_WAIT ) ); TEST_ASSERT_EQUAL( 0, uxQueueMessagesWaiting( xQueue ) ); @@ -612,6 +640,8 @@ void test_xQueueReceive_blocking_locked( void ) uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Run xQueueReceive in blocking mode with the queue locked */ TEST_ASSERT_EQUAL( pdFALSE, xQueueReceive( xQueue, &checkVal, TICKS_TO_WAIT ) ); @@ -636,6 +666,8 @@ void test_xQueueReceive_blocking_locked( void ) */ void test_xQueuePeek_blocking_locked( void ) { + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Create a new binary Queue */ QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); diff --git a/FreeRTOS/Test/CMock/queue/generic/queue_receive_nonblocking_utest.c b/FreeRTOS/Test/CMock/queue/generic/queue_receive_nonblocking_utest.c index 39982c6c2..e15d8495b 100644 --- a/FreeRTOS/Test/CMock/queue/generic/queue_receive_nonblocking_utest.c +++ b/FreeRTOS/Test/CMock/queue/generic/queue_receive_nonblocking_utest.c @@ -74,6 +74,18 @@ int suiteTearDown( int numFailures ) /* ========================== Helper functions =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Test Cases ============================== */ /** @@ -287,6 +299,8 @@ void test_xQueuePeek_noop_waiting_higher_priority( void ) /* peek from the queue */ uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) ); TEST_ASSERT_EQUAL( pdTRUE, xQueuePeek( xQueue, &checkVal, 0 ) ); @@ -325,6 +339,7 @@ void test_xQueuePeek_xQueuePeek_waiting_higher_priority( void ) td_task_addFakeTaskWaitingToReceiveFromQueue( xQueue ); vFakePortYieldWithinAPI_Stub( &vPortYieldWithinAPI_xQueuePeek_Stub ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); xStubExpectedReturnValue = pdTRUE; @@ -369,6 +384,7 @@ void test_xQueuePeek_xQueueReceive_waiting_higher_priority( void ) td_task_addFakeTaskWaitingToReceiveFromQueue( xQueue ); vFakePortYieldWithinAPI_Stub( &vPortYieldWithinAPI_xQueueReceive_Stub ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); xStubExpectedReturnValue = pdTRUE; @@ -805,6 +821,8 @@ void test_xQueueReceive_noop_waiting_higher_priority( void ) uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xQueue ) ); /* receive from the queue */ diff --git a/FreeRTOS/Test/CMock/queue/generic/queue_reset_utest.c b/FreeRTOS/Test/CMock/queue/generic/queue_reset_utest.c index 30a3f0e5c..7d6dc5380 100644 --- a/FreeRTOS/Test/CMock/queue/generic/queue_reset_utest.c +++ b/FreeRTOS/Test/CMock/queue/generic/queue_reset_utest.c @@ -67,6 +67,18 @@ int suiteTearDown( int numFailures ) /* ========================== Helper functions =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ========================== Test Cases =========================== */ /** @@ -164,6 +176,8 @@ void test_macro_xQueueReset_tasks_waiting_higher_priority( void ) td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); td_task_addFakeTaskWaitingToSendToQueue( xQueue ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( pdTRUE, xQueueReset( xQueue ) ); TEST_ASSERT_EQUAL( 1, td_task_getYieldCount() ); diff --git a/FreeRTOS/Test/CMock/queue/generic/queue_send_blocking_utest.c b/FreeRTOS/Test/CMock/queue/generic/queue_send_blocking_utest.c index 422a16ac8..1c5b700b2 100644 --- a/FreeRTOS/Test/CMock/queue/generic/queue_send_blocking_utest.c +++ b/FreeRTOS/Test/CMock/queue/generic/queue_send_blocking_utest.c @@ -45,6 +45,18 @@ static QueueHandle_t xQueueHandleStatic; /* ========================== CALLBACK FUNCTIONS =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Unity Fixtures ============================= */ void setUp( void ) @@ -82,6 +94,8 @@ static BaseType_t xQueueSend_locked_xTaskCheckForTimeOutCB( TimeOut_t * const px { BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT ) { uint32_t checkVal = INVALID_UINT32; @@ -138,6 +152,8 @@ static BaseType_t xQueueSend_xTaskResumeAllCallback( int cmock_num_calls ) { BaseType_t xReturnValue = td_task_xTaskResumeAllStub( cmock_num_calls ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* If td_task_xTaskResumeAllStub returns pdTRUE, a higher priority task is pending * Send from an ISR to block */ if( pdTRUE == xReturnValue ) @@ -171,6 +187,7 @@ void test_macro_xQueueSend_blocking_fail_locked_high_prio_pending( void ) xTaskCheckForTimeOut_Stub( &xQueueSend_locked_xTaskCheckForTimeOutCB ); xTaskResumeAll_Stub( &xQueueSend_xTaskResumeAllCallback ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* this task is lower priority than the pending task */ td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); @@ -256,6 +273,7 @@ void test_macro_xQueueSend_blocking_suspended_assert( void ) uint32_t testVal = getNextMonotonicTestValue(); fakeAssertExpectFail(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setSchedulerState( taskSCHEDULER_SUSPENDED ); @@ -282,6 +300,8 @@ void test_macro_xQueueSend_blocking_timeout( void ) uint32_t testVal = getNextMonotonicTestValue(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Fill up the queue */ TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 0 ) ); @@ -314,6 +334,8 @@ void test_macro_xQueueSend_blocking_locked( void ) uint32_t testVal1 = getNextMonotonicTestValue(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Fill the queue */ TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal1, TICKS_TO_WAIT ) ); diff --git a/FreeRTOS/Test/CMock/queue/generic/queue_send_nonblocking_utest.c b/FreeRTOS/Test/CMock/queue/generic/queue_send_nonblocking_utest.c index e52002ed4..7f3ab4c0d 100644 --- a/FreeRTOS/Test/CMock/queue/generic/queue_send_nonblocking_utest.c +++ b/FreeRTOS/Test/CMock/queue/generic/queue_send_nonblocking_utest.c @@ -44,6 +44,18 @@ /* ========================== CALLBACK FUNCTIONS =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Unity Fixtures ============================= */ void setUp( void ) @@ -246,6 +258,8 @@ void test_macro_xQueueSend_task_waiting_higher_priority_success( void ) { QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Insert an item into the event list */ td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); td_task_addFakeTaskWaitingToReceiveFromQueue( xQueue ); diff --git a/FreeRTOS/Test/CMock/queue/semaphore/binary_semaphore_utest.c b/FreeRTOS/Test/CMock/queue/semaphore/binary_semaphore_utest.c index 26975c6e7..385396020 100644 --- a/FreeRTOS/Test/CMock/queue/semaphore/binary_semaphore_utest.c +++ b/FreeRTOS/Test/CMock/queue/semaphore/binary_semaphore_utest.c @@ -42,6 +42,18 @@ static SemaphoreHandle_t xSemaphoreHandleStatic; /* ========================== CALLBACK FUNCTIONS =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Unity Fixtures ============================= */ void setUp( void ) @@ -501,6 +513,8 @@ void test_xSemaphoreTake_tasks_waiting_higher_priority( void ) ( void ) xSemaphoreGive( xSemaphore ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Insert an item into the event list */ td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); td_task_addFakeTaskWaitingToSendToQueue( xSemaphore ); @@ -582,6 +596,7 @@ void test_xSemaphoreTake_blocking_suspended_assert( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(); fakeAssertExpectFail(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); vTaskSuspendAll_Stub( td_task_vTaskSuspendAllStubNoCheck ); @@ -649,6 +664,7 @@ void test_xSemaphoreTake_blocking_success( void ) xSemaphoreHandleStatic = xSemaphore; vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); xTaskCheckForTimeOut_Stub( &blocking_success_xTaskCheckForTimeOut_cb ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); @@ -696,6 +712,7 @@ void test_xSemaphoreTake_blocking_success_last_chance( void ) xSemaphoreHandleStatic = xSemaphore; vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); xTaskCheckForTimeOut_Stub( &blocking_last_chance_xTaskCheckForTimeOut_cb ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); @@ -718,6 +735,8 @@ void test_xSemaphoreTake_blocking_timeout( void ) { SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) ); TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() ); @@ -738,6 +757,8 @@ void test_xSemaphoreTake_blocking_locked( void ) /* Create a new binary semaphore */ SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Set private lock counters */ vSetQueueRxLock( xSemaphore, queueLOCKED_UNMODIFIED ); vSetQueueTxLock( xSemaphore, queueLOCKED_UNMODIFIED ); @@ -787,6 +808,7 @@ void test_xSemaphoreTake_blocking_success_locked_no_pending( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(); vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Export for callbacks */ xSemaphoreHandleStatic = xSemaphore; @@ -840,6 +862,7 @@ void test_xSemaphoreTake_blocking_timeout_locked_high_prio_pending( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(); vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Export for callbacks */ xSemaphoreHandleStatic = xSemaphore; @@ -878,6 +901,7 @@ void test_xSemaphoreTake_blocking_success_locked_low_prio_pending( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(); vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Export for callbacks */ xSemaphoreHandleStatic = xSemaphore; diff --git a/FreeRTOS/Test/CMock/queue/semaphore/counting_semaphore_utest.c b/FreeRTOS/Test/CMock/queue/semaphore/counting_semaphore_utest.c index bdba72d7c..7284b41ae 100644 --- a/FreeRTOS/Test/CMock/queue/semaphore/counting_semaphore_utest.c +++ b/FreeRTOS/Test/CMock/queue/semaphore/counting_semaphore_utest.c @@ -40,6 +40,18 @@ static SemaphoreHandle_t xSemaphoreHandleStatic; /* ========================== CALLBACK FUNCTIONS =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Unity Fixtures ============================= */ void setUp( void ) @@ -349,6 +361,7 @@ void test_xSemaphoreTake_blocking_suspended_assert( void ) fakeAssertExpectFail(); vTaskSuspendAll_Stub( td_task_vTaskSuspendAllStubNoCheck ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); td_task_setSchedulerState( taskSCHEDULER_SUSPENDED ); @@ -417,6 +430,7 @@ void test_xSemaphoreTake_blocking_success( void ) xSemaphoreHandleStatic = xSemaphore; vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); xTaskCheckForTimeOut_Stub( &blocking_xTaskCheckForTimeOut_cb ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); @@ -467,6 +481,7 @@ void test_xSemaphoreTake_blocking_success_last_chance( void ) xSemaphoreHandleStatic = xSemaphore; vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); xTaskCheckForTimeOut_Stub( &blocking_last_chance_xTaskCheckForTimeOut_cb ); uxTaskGetNumberOfTasks_IgnoreAndReturn( 1 ); @@ -492,6 +507,8 @@ void test_xSemaphoreTake_blocking_timeout( void ) { SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting( 2, 0 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) ); TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() ); @@ -512,6 +529,8 @@ void test_xSemaphoreTake_blocking_locked( void ) /* Create a new binary semaphore */ SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting( 2, 0 ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + /* Set private lock counters */ vSetQueueRxLock( xSemaphore, queueLOCKED_UNMODIFIED ); vSetQueueTxLock( xSemaphore, queueLOCKED_UNMODIFIED ); @@ -560,6 +579,7 @@ void test_xSemaphoreTake_blocking_success_locked_no_pending( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting( 2, 0 ); vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Export for callbacks */ xSemaphoreHandleStatic = xSemaphore; @@ -613,6 +633,7 @@ void test_xSemaphoreTake_blocking_timeout_locked_high_prio_pending( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting( 2, 0 ); vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Export for callbacks */ xSemaphoreHandleStatic = xSemaphore; @@ -651,6 +672,7 @@ void test_xSemaphoreTake_blocking_success_locked_low_prio_pending( void ) SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting( 2, 0 ); vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Export for callbacks */ xSemaphoreHandleStatic = xSemaphore; diff --git a/FreeRTOS/Test/CMock/queue/semaphore/mutex_utest.c b/FreeRTOS/Test/CMock/queue/semaphore/mutex_utest.c index d8d05b7db..89a9b02d2 100644 --- a/FreeRTOS/Test/CMock/queue/semaphore/mutex_utest.c +++ b/FreeRTOS/Test/CMock/queue/semaphore/mutex_utest.c @@ -38,6 +38,18 @@ static SemaphoreHandle_t xSemaphoreHandleStatic = NULL; /* ========================== CALLBACK FUNCTIONS =========================== */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= Unity Fixtures ============================= */ void setUp( void ) @@ -468,6 +480,7 @@ void test_macro_xSemaphoreTake_blocking_mutex_inherit_timeout( void ) /* Return a test value from the call to pvTaskIncrementMutexHeldCount */ pvTaskIncrementMutexHeldCount_ExpectAndReturn( ( void * ) xFakeMutexHolder ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Take the mutex */ TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) ); @@ -553,6 +566,8 @@ void test_macro_xSemaphoreTake_blocking_mutex_inherit_disinherit( void ) { xTaskPriorityDisinherit_ExpectAndReturn( NULL, pdFALSE ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + SemaphoreHandle_t xSemaphore = xSemaphoreCreateMutex(); xSemaphoreHandleStatic = xSemaphore; diff --git a/FreeRTOS/Test/CMock/queue/sets/queue_in_set_utest.c b/FreeRTOS/Test/CMock/queue/sets/queue_in_set_utest.c index cb8241643..14a83ad31 100644 --- a/FreeRTOS/Test/CMock/queue/sets/queue_in_set_utest.c +++ b/FreeRTOS/Test/CMock/queue/sets/queue_in_set_utest.c @@ -72,6 +72,18 @@ int suiteTearDown( int numFailures ) /* =========================== Helper functions ============================ */ +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================== Test Cases =============================== */ @@ -429,6 +441,7 @@ void test_macro_xQueueSendFromISR_in_set_locked_and_low_priority_pending( void ) xQueueAddToSet( xQueue, xQueueSet ); vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* Insert an item into the event list. */ td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 ); @@ -556,6 +569,8 @@ void test_macro_xQueueSend_in_set_high_priority_pending( void ) td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 ); td_task_addFakeTaskWaitingToReceiveFromQueue( xQueueSet ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + uint32_t testVal = getNextMonotonicTestValue(); /* Add item to queue*/ @@ -795,6 +810,8 @@ void test_macro_xQueueSend_in_set_blocking_success_locked_no_pending( void ) uint32_t testVal = getNextMonotonicTestValue(); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + TEST_ASSERT_EQUAL( pdTRUE, xQueueSend( xQueue, &testVal, 0 ) ); xTaskCheckForTimeOut_Stub( &xQueueSend_locked_xTaskCheckForTimeOutCB ); @@ -848,6 +865,8 @@ void test_macro_xQueueSend_in_set_blocking_fail_locked_high_prio_pending( void ) QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + xQueueAddToSet( xQueue, xQueueSet ); /* Export for callbacks */ @@ -896,6 +915,8 @@ void test_macro_xQueueSend_in_set_blocking_success_locked_low_prio_pending( void QueueHandle_t xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + xQueueAddToSet( xQueue, xQueueSet ); /* Export for callbacks */ @@ -968,6 +989,8 @@ void test_xQueueReceive_in_set_blocking_success_locked_no_pending( void ) uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + QueueHandle_t xQueueFromSet = xQueueSelectFromSet( xQueueSet, TICKS_TO_WAIT ); TEST_ASSERT_NOT_NULL( xQueueFromSet ); @@ -1035,6 +1058,8 @@ void test_xQueueReceive_in_set_blocking_fail_locked_high_prio_pending( void ) td_task_addFakeTaskWaitingToReceiveFromQueue( xQueueSet ); + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + QueueHandle_t xQueueFromSet = xQueueSelectFromSet( xQueueSet, TICKS_TO_WAIT ); TEST_ASSERT_EQUAL( NULL, xQueueFromSet ); @@ -1080,6 +1105,8 @@ void test_xQueueReceive_in_set_blocking_success_locked_low_prio_pending( void ) uint32_t checkVal = INVALID_UINT32; + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); + QueueHandle_t xQueueFromSet = xQueueSelectFromSet( xQueueSet, NUM_CALLS_TO_INTERCEPT ); TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() ); diff --git a/FreeRTOS/Test/CMock/smp/Makefile b/FreeRTOS/Test/CMock/smp/Makefile new file mode 100644 index 000000000..948942e36 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/Makefile @@ -0,0 +1,23 @@ +# Indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +include ../makefile.in + +# SUITES lists the suites contained in subdirectories of this directory +SUITES += single_priority_no_timeslice +SUITES += single_priority_timeslice +SUITES += multiple_priorities_no_timeslice +SUITES += multiple_priorities_timeslice + +# SUITS mock dependency source for coverage test +SUITES += multiple_priorities_no_timeslice_mock + +# SUITS for configASSERT +SUITES += config_assert + +# PROJECT and SUITE variables are determined based on path like so: +# $(UT_ROOT_DIR)/$(PROJECT)/$(SUITE) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH))))) + +include ../subdir.mk diff --git a/FreeRTOS/Test/CMock/smp/README.md b/FreeRTOS/Test/CMock/smp/README.md new file mode 100644 index 000000000..a54dbf11b --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/README.md @@ -0,0 +1,170 @@ +# FreeRTOS Kernel SMP Unit Test + +FreeRTOS Kernel SMP unit test verifies the SMP scheduler logic in tasks.c which +is enclosed by `configNUMBER_OF_CORES > 1`. The common scheduler logic for single +core and SMP is still verified in FreeRTOS/FreeRTOS/Test/CMock/tasks. + +## Folder structure and test group naming +FreeRTOS SMP unit test has the following folder structure: +``` +./FreeRTOS/FreeRTOS/Test/CMock/smp +├── Makefile +├── config_assert +│ └── config_assert_utest.c +├── multiple_priorities_no_timeslice_mock +│ └── covg_multiple_priorities_no_timeslice_mock_utest.c +├── multiple_priorities_no_timeslice +│ ├── covg_multiple_priorities_no_timeslice_utest.c +│ └── multiple_priorities_no_timeslice_utest.c +├── multiple_priorities_timeslice +│ ├── covg_multiple_priorities_timeslice_utest.c +│ └── multiple_priorities_timeslice_utest.c +├── single_priority_no_timeslice +│ ├── covg_single_priority_no_timeslice_utest.c +│ └── single_priority_no_timeslice_utest.c +├── single_priority_timeslice +│ ├── covg_single_priority_timeslice_utest.c +│ └── single_priority_timeslice_utest.c +├── global_vars.h +├── smp_utest_common.c +└── smp_utest_common.h +``` + +FreeRTOS SMP unit test cases are divided into groups and each folder represents +a test group. Test cases with same configurations in FreeRTOSConfig.h are grouped +together in a test group. + +The following test groups are created for the combinations of `configRUN_MULTIPLE_PRIORITIES` +and `configUSE_TIME_SLICING`: +* single_priority_timeslice +* single_priority_no_timeslice +* multiple_priorities_timeslice +* multiple_priorities_no_timeslice + +In order to increase the test coverage rate, test group **multiple_priorities_no_timeslice_mock** +is created to mock the APIs in list.h. The configuration is similar to **multiple_priorities_no_timeslice**. + * multiple_priorities_no_timeslice_mock + +config_assert test group is created to cover `configASSERT` in FreeRTOS SMP scheduler logic. +* config_assert + +## Functional tests and coverage tests +Each test group has two types of test cases, the functional test cases and coverage +test cases. To distinguish these test cases, the source code file has the following +naming convention: +* Coverage test : covg_\_utest.c +* Functional test : \_utest.c + +### Functional tests +Functional test cases verify that the SMP scheduler logic performs as described +by functional requirements. The test case specifies the functional requirement to +be verified, the test steps and expected result in the comment. + +The following is an example of the functional test: +```c +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-1 + * The purpose of this test is to verify when multiple CPU cores are available and + * the FreeRTOS kernel is configured as (configRUN_MULTIPLE_PRIORITIES = 0) that tasks + * of equal priority will execute simultaneously. The kernel will be configured as follows: + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority –1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_verification_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} +``` + +### Coverage tests +Coverage test cases verify a specific path of SMP scheduler logic. +The test case specifies the lines of code to be covered in the test case. +To minimize dependencies, mock functions are used wherever possible. + + +The following is an example of the coverage test: +```c +/** + * @brief xTaskResumeFromISR - resume higher priority suspended task + * + * A higher priority task from ISR is resumed in the test case when scheduler + * suspended. The return value of xTaskResumeFromISR indicates yield required + * for the core calling this API. + * + * Coverage + * @code{c} + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) + * { + * xYieldRequired = pdTRUE; + * } + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) is true. + */ +void test_coverage_xTaskResumeFromISR_resume_higher_priority_suspended_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1U ] = { NULL }; + uint32_t i; + BaseType_t xReturn; + + /* Setup the variables and structure. */ + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xPendingReadyList ); + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = 1; + xTaskTCBs[ i ].xTaskRunState = i; + xYieldPendings[ i ] = pdFALSE; + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + /* A suspended task is created to be resumed from ISR. The task has higher priority + * than uxTopReadyPriority and the scheduler is suspended. The task will be added + * to xPendingReadyList after resumed from ISR. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority = 2; + listINSERT_END( &xSuspendedTaskList, &xTaskTCBs[ i ].xStateListItem ); + uxTopReadyPriority = 1; + uxSchedulerSuspended = pdTRUE; + + /* Expections. */ + vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + + /* API calls. */ + xReturn = xTaskResumeFromISR( &xTaskTCBs[ i ] ); + + /* Validateions. In single priority test, the calling core is requested to yield + * since a higher priority task is resumed. */ + TEST_ASSERT( xReturn == pdTRUE ); +} +``` diff --git a/FreeRTOS/Test/CMock/smp/config_assert/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/smp/config_assert/FreeRTOSConfig.h new file mode 100644 index 000000000..90b2593ee --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/config_assert/FreeRTOSConfig.h @@ -0,0 +1,156 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* https://www.FreeRTOS.org/a00110.html +*----------------------------------------------------------*/ + +/* SMP test specific configuration */ +#define configRUN_MULTIPLE_PRIORITIES 0 +#define configNUMBER_OF_CORES 16 +#define configUSE_CORE_AFFINITY 1 +#define configUSE_TIME_SLICING 0 +#define configUSE_TASK_PREEMPTION_DISABLE 0 +#define configTICK_CORE 0 +#define configUSE_TICKLESS_IDLE 1 + +/* OS Configuration */ +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 +#define portREMOVE_STATIC_QUALIFIER 1 +#define portCRITICAL_NESTING_IN_TCB 1 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_PASSIVE_IDLE_HOOK 0 +#define configKERNEL_PROVIDED_STATIC_MEMORY 1 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configENABLE_MPU 0 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +#define configASSERT( x ) \ + do \ + { \ + if( x ) \ + { \ + vFakeAssert( true, __FILE__, __LINE__ ); \ + } \ + else \ + { \ + vFakeAssert( false, __FILE__, __LINE__ ); \ + } \ + } while( 0 ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) + extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); + #define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer ) +#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/config_assert/Makefile b/FreeRTOS/Test/CMock/smp/config_assert/Makefile new file mode 100644 index 000000000..f3fd2611b --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/config_assert/Makefile @@ -0,0 +1,54 @@ +# indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) + +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC := tasks.c + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +#PROJECT_DEPS_SRC := + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS := FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := config_assert_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +#SUITE_SUPPORT_SRC := + + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_FP += $(KERNEL_DIR)/include/list.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/smp/config_assert/list_macros.h +MOCK_FILES_FP += $(KERNEL_DIR)/include/queue.h +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_port.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/portmacro.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/smp/config_assert/local_portable.h + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS += -include list_macros.h + +# List any addiitonal flags needed by the compiler +CFLAGS += + +# Try not to edit beyond this line unless necessary. + +# Project is determined based on path: $(UT_ROOT_DIR)/$(PROJECT) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +# Make variables available to included makefile +export + +include ../../testdir.mk + + diff --git a/FreeRTOS/Test/CMock/smp/config_assert/config_assert_utest.c b/FreeRTOS/Test/CMock/smp/config_assert/config_assert_utest.c new file mode 100644 index 000000000..53421af20 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/config_assert/config_assert_utest.c @@ -0,0 +1,671 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file config_assert_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include +#include + +/* Tasks includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "../global_vars.h" +#include "task.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "CException.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_list.h" +#include "mock_list_macros.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" +#include "mock_local_portable.h" + + +/* ================================= MACROS =============================== */ + +/** + * @brief CException code for when a configASSERT should be intercepted. + */ +#define configASSERT_E 0xAA101 + +/** + * @brief simulate up to 10 tasks: add more if needed + * */ +#define TCB_ARRAY 10 + +/** + * @brief Expect a configASSERT from the function called. + * Break out of the called function when this occurs. + * @details Use this macro when the call passed in as a parameter is expected + * to cause invalid memory access. + */ +#define EXPECT_ASSERT_BREAK( call ) \ + do \ + { \ + shouldAbortOnAssertion = true; \ + CEXCEPTION_T e = CEXCEPTION_NONE; \ + Try \ + { \ + call; \ + TEST_FAIL(); \ + } \ + Catch( e ) \ + { \ + TEST_ASSERT_EQUAL( configASSERT_E, e ); \ + } \ + } while( 0 ) + + +/* ============================ GLOBAL VARIABLES =========================== */ + +/** + * @brief Global counter for the number of assertions in code. + */ +static int assertionFailed = 0; + +/** + * @brief Flag which denotes if test need to abort on assertion. + */ +static BaseType_t shouldAbortOnAssertion; + + +/* =========================== EXTERN VARIABLES =========================== */ +extern void vTaskEnterCritical( void ); +extern void vTaskExitCritical( void ); +extern void vTaskExitCriticalFromISR( UBaseType_t xSavedInterruptStatus ); +extern void prvCheckForRunStateChange( void ); + +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile BaseType_t xSchedulerRunning; +extern volatile UBaseType_t uxSchedulerSuspended; +extern TCB_t * volatile pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; +extern volatile UBaseType_t uxTopReadyPriority; +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; +extern volatile TickType_t xTickCount; +extern volatile TickType_t xNextTaskUnblockTime; + +/* ========================== STATIC FUNCTIONS ========================== */ +static void vFakeAssertStub( bool x, + char * file, + int line, + int cmock_num_calls ) +{ + if( !x ) + { + assertionFailed++; + + if( shouldAbortOnAssertion == pdTRUE ) + { + Throw( configASSERT_E ); + } + } +} + +static void validate_and_clear_assertions( void ) +{ + TEST_ASSERT_EQUAL( 1, assertionFailed ); + assertionFailed = 0; +} + +void * pvPortMalloc( size_t xSize ) +{ + return unity_malloc( xSize ); +} + +void vPortFree( void * pv ) +{ + return unity_free( pv ); +} +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + vFakeAssert_StubWithCallback( vFakeAssertStub ); +} + +/*! called after each testcase */ +void tearDown( void ) +{ +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* =============================== Callbacks ============================== */ +void port_release_task_lock_cb( int num_calls ) +{ + pxCurrentTCBs[ 0 ]->xTaskRunState = -1; /* taskTASK_YIELDING */ +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief This test ensures that the code asserts when the TCB's critical + * nesting count is less than or equal to zero + * + * Coverage + * @code{c} + * prvYieldForTask( pxTCB ); + * + * configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U ); + * @endcode + * + * configUSE_PREEMPTION == 1 + * configNUMBER_OF_CORES > 1 + * configUSE_CORE_AFFINITY == 1 + */ +void test_prvYieldForTask_assert_critical_nesting_lteq_zero( void ) +{ + UBaseType_t uxCoreAffinityMask; + TCB_t currentTCB; + + memset( ¤tTCB, 0x00, sizeof( TCB_t ) ); + + pxCurrentTCBs[ 0 ] = ¤tTCB; + pxCurrentTCBs[ 0 ]->uxCoreAffinityMask = 1; + pxCurrentTCBs[ 0 ]->uxCriticalNesting = 0; + pxCurrentTCBs[ 0 ]->xTaskRunState = -1; /* taskTASK_NOT_RUNNING */ + xSchedulerRunning = pdTRUE; + + /* Set the new mask to the last core. */ + uxCoreAffinityMask = ( 1 << ( configNUMBER_OF_CORES - 1 ) ); + + vFakePortEnterCriticalSection_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + + EXPECT_ASSERT_BREAK( vTaskCoreAffinitySet( pxCurrentTCBs[ 0 ], + uxCoreAffinityMask ) ); + + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts when xYieldPending of the + * current core is false and the task is runing + * + * Coverage + * @code{c} + * prvYieldForTask( pxTCB ); + * + * configASSERT( ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) || + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ portGET_CORE_ID() ] ) == pdFALSE ) ); + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configRUN_MULTIPLE_PRIORITIES = 0 + * configUSE_TASK_PREEMPTION_DISABLE + */ +void test_prvYieldForTask_assert_yieldpending_core_is_false( void ) +{ + TCB_t unblockedTCB[ configNUMBER_OF_CORES ] = { 0 }; + + ListItem_t xEventListItem; + TickType_t xItemValue = 0; + + for( int i = 0; i < configNUMBER_OF_CORES; ++i ) + { + pxCurrentTCBs[ i ] = &unblockedTCB[ i ]; + unblockedTCB[ i ].xTaskRunState = -1; /* taskTASK_YIELDING */ + } + + unblockedTCB[ 0 ].uxCriticalNesting = 1; + unblockedTCB[ 0 ].xTaskRunState = 0; + unblockedTCB[ 0 ].uxTaskAttributes = 2; + unblockedTCB[ 0 ].uxPriority = 1; + + unblockedTCB[ 1 ].uxTaskAttributes = 2; + unblockedTCB[ 1 ].uxPriority = 0; + unblockedTCB[ 1 ].xTaskRunState = 1; + + unblockedTCB[ 2 ].xTaskRunState = -1; + + unblockedTCB[ 3 ].xTaskRunState = configNUMBER_OF_CORES + 2; + + uxSchedulerSuspended = 3; + + xYieldPendings[ 1 ] = pdFALSE; + + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + listGET_LIST_ITEM_OWNER_ExpectAnyArgsAndReturn( &unblockedTCB[ 0 ] ); + listREMOVE_ITEM_ExpectAnyArgs(); + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdTRUE ); + listREMOVE_ITEM_ExpectAnyArgs(); + /* in prvAddTaskToReadyList */ + listINSERT_END_ExpectAnyArgs(); + /* back */ + /* taskENTER_CRITICAL */ + vFakePortEnterCriticalSection_Expect(); + /* back */ + /* prvYieldForTask */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 1 ); + vFakePortGetCoreID_ExpectAndReturn( 1 ); + vFakePortGetCoreID_ExpectAndReturn( 1 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + + EXPECT_ASSERT_BREAK( vTaskRemoveFromUnorderedEventList( &xEventListItem, + xItemValue ) ); + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts when we are trying to select + * the highest priority task on a specific core while the scheuler is not + * running + * + * Coverage + * @code{c} + * prvSelectHighestPriorityTask( xCoreID ); + * + * configASSERT( xSchedulerRunning == pdTRUE ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_prvSelectHighestPriorityTask_assert_scheduler_running_false( void ) +{ + TCB_t unblockedTCB[ configNUMBER_OF_CORES ] = { 0 }; + + unblockedTCB[ 0 ].uxCriticalNesting = 0; + + pxCurrentTCBs[ 0 ] = &unblockedTCB[ 0 ]; + + xSchedulerRunning = pdFALSE; /* causes the assert */ + uxSchedulerSuspended = pdFALSE; + + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + + EXPECT_ASSERT_BREAK( vTaskSwitchContext( 1 ) ); + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts when the coreID is not equal + * to the runstate of the task + * + * Coverage + * @code{c} + * prvSelectHighestPriorityTask( xCoreID ); + * + * configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_YIELDING ) ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_prvSelectHighestPriorityTask_assert_coreid_ne_runstate( void ) +{ + TCB_t unblockedTCB[ configNUMBER_OF_CORES ] = { 0 }; + + unblockedTCB[ 0 ].uxCriticalNesting = 0; + unblockedTCB[ 0 ].xTaskRunState = 2; /* causes the assert coreID != runstate */ + + pxCurrentTCBs[ 0 ] = &unblockedTCB[ 0 ]; + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + + listIS_CONTAINED_WITHIN_ExpectAnyArgsAndReturn( pdFALSE ); + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdFALSE ); + listGET_LIST_ITEM_OWNER_ExpectAnyArgsAndReturn( &unblockedTCB[ 0 ] ); + + EXPECT_ASSERT_BREAK( vTaskSwitchContext( 0 ) ); + + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts if the scheduler is not + * suspended + * + * Coverage + * @code{c} + * vTaskDelete( xTaskToDelete ); + * + * configASSERT( uxSchedulerSuspended == 0 ); + * @endcode + * + * configNUMBER_OF_CORES > 1 + * INCLUDE_vTaskDelete + */ +void test_vTaskDelete_assert_scheduler_suspended_eq_1( void ) +{ + TaskHandle_t xTaskToDelete = NULL; + TCB_t * pxTCB = malloc( sizeof( TCB_t ) ); + + pxTCB->pxStack = malloc( 200 ); + pxTCB->xTaskRunState = 1; /* task running on core 1 */ + xTaskToDelete = ( TaskHandle_t ) pxTCB; + + uxSchedulerSuspended = 1; /* asserts the code */ + xSchedulerRunning = pdTRUE; + + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + vListInsertEnd_ExpectAnyArgs(); + vPortCurrentTaskDying_ExpectAnyArgs(); + vFakePortGetCoreID_ExpectAndReturn( 1 ); + + EXPECT_ASSERT_BREAK( vTaskDelete( xTaskToDelete ) ); + + validate_and_clear_assertions(); + + free( pxTCB->pxStack ); + free( pxTCB ); +} + +/** + * @brief This test ensures that the code asserts when a task is suspended while + * the scheduler is suspended + * + * Coverage + * @code{c} + * vTaskDelete( xTaskToDelete ); + * + * configASSERT( uxSchedulerSuspended == 0 ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * INCLUDE_vTaskSuspend + */ +void test_vTaskSuspend_assert_schedulersuspended_ne_zero( void ) +{ + TaskHandle_t xTaskToSuspend; + TCB_t * pxTCB = malloc( sizeof( TCB_t ) ); + + xTaskToSuspend = ( TaskHandle_t ) pxTCB; + xSchedulerRunning = pdTRUE; + pxTCB->xTaskRunState = 1; + uxSchedulerSuspended = 1; /* asserts the code */ + + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + vListInsertEnd_ExpectAnyArgs(); + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdTRUE ); + vFakePortGetCoreID_ExpectAndReturn( 1 ); + + EXPECT_ASSERT_BREAK( vTaskSuspend( xTaskToSuspend ) ); + + validate_and_clear_assertions(); + + free( pxTCB ); +} + +/** + * @brief This test ensures that the code asserts when we try to switch + * context with a current task that is holding a + * critical section + * + * Coverage + * @code{c} + * vTaskSwitchContext( xCoreID ); + * + * configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_vTaskSwitchContext_assert_nexting_count_ne_zero( void ) +{ + TCB_t currentTCB = { 0 }; + + currentTCB.uxCriticalNesting = 1; /* causes the assert */ + + pxCurrentTCBs[ 1 ] = ¤tTCB; + + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 1 ); + + EXPECT_ASSERT_BREAK( vTaskSwitchContext( 1 ) ); + + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts when we try to exit a critical + * section while the current tasks critical count is zero + * + * Coverage + * @code{c} + * vTaskExitCritical(); + * + * configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_vTaskExitCritical_assert_critical_nesting_eq_zero( void ) +{ + TCB_t currentTCB = { 0 }; + + xSchedulerRunning = pdTRUE; + currentTCB.uxCriticalNesting = 0; /* causes the assert */ + pxCurrentTCBs[ 1 ] = ¤tTCB; + + vFakePortGetCoreID_ExpectAndReturn( 1 ); + + EXPECT_ASSERT_BREAK( vTaskExitCritical() ); + + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts when we try to exit a critical + * section while the current tasks critical count is zero + * + * Coverage + * @code{c} + * vTaskExitCriticalFromISR(); + * + * configASSERT( portGET_CRITICAL_NESTING_COUNT() > 0U ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_vTaskExitCriticalFromISR_assertcritical_nesting_eq_zero( void ) +{ + TCB_t currentTCB = { 0 }; + + xSchedulerRunning = pdTRUE; + currentTCB.uxCriticalNesting = 0; /* causes the assert */ + pxCurrentTCBs[ 1 ] = ¤tTCB; + + vFakePortGetCoreID_ExpectAndReturn( 1 ); + + EXPECT_ASSERT_BREAK( vTaskExitCriticalFromISR( 1 ) ); + + validate_and_clear_assertions(); +} + +/** + * @brief This test ensures that the code asserts when the next unblock time is + * less than the xTickCount + * + * Coverage + * @code{c} + * prvIdleTask(); + * + * configASSERT( xNextTaskUnblockTime >= xTickCount ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configUSE_TICKLESS_IDLE != 0 + */ +void test_prvGetExpectedIdleTime_assert_nextUnblock_lt_xTickCount( void ) +{ + TCB_t xTCB = { 0 }; + + xTickCount = 250; + xNextTaskUnblockTime = 240; /* expectedidletime = xNextTaskUnblockTime - xTickCount */ + pxCurrentTCBs[ 0 ] = &xTCB; + xTCB.uxPriority = tskIDLE_PRIORITY; + + /* Test Setup */ + uxDeletedTasksWaitingCleanUp = 0; + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Test Expectations */ + vFakePortYield_Expect(); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); + + /* vTaskSuspendAll */ + vFakePortAssertIfISR_Expect(); + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortReleaseISRLock_Expect(); + vFakePortClearInterruptMask_Expect( 0 ); + + /* API Call */ + portTASK_FUNCTION( prvIdleTask, args ); + EXPECT_ASSERT_BREAK( prvIdleTask( NULL ) ); + + /* Test Verifications */ + validate_and_clear_assertions(); +} + +/** + * @brief vTaskStepTick - assert if scheduler suspended. + * + * Coverage + * @code{c} + * configASSERT( uxSchedulerSuspended ); + * @endcode + */ +void test_vTaskStepTick_assert_scheduler_not_suspended( void ) +{ + TickType_t xTicksToJump; + + xTickCount = 230; + xTicksToJump = 10; + xNextTaskUnblockTime = 240; + uxSchedulerSuspended = pdFALSE; + + /* API Call */ + EXPECT_ASSERT_BREAK( vTaskStepTick( xTicksToJump ) ); + + /* Test Verifications */ + validate_and_clear_assertions(); +} + +/** + * @brief prvCheckForRunStateChange - task state not changed. + * + * When the task is able to run after calling portENABLE_INTERRUPTS. The task state + * is supposed to be changed to run state. This test cover the assertion of this scenario. + * + * Coverage + * @code{c} + * configASSERT( pxThisTCB->xTaskRunState != taskTASK_YIELDING ); + * @endcode + */ +void test_prvCheckForRunStateChange_assert_task_state_not_changed( void ) +{ + TCB_t xTaskTCB = { NULL }; + + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.uxCriticalNesting = 0; + xTaskTCB.xTaskRunState = taskTASK_YIELDING; + uxSchedulerSuspended = 1; + + /* Expection. */ + vFakePortAssertIfISR_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortReleaseTaskLock_Expect(); + vFakePortEnableInterrupts_Expect(); + + /* API Call. */ + EXPECT_ASSERT_BREAK( prvCheckForRunStateChange() ); + + /* Test Verifications */ + validate_and_clear_assertions(); +} + +/** + * @brief vTaskStepTick - assert if scheduler suspended. + * + * Coverage + * @code{c} + * configASSERT( xTicksToJump != ( TickType_t ) 0 ); + * @endcode + */ +void test_vTaskStepTick_assert_tick_to_jump_eq_0( void ) +{ + TickType_t xTicksToJump; + + xTickCount = 240; + xTicksToJump = 0; + xNextTaskUnblockTime = 240; + uxSchedulerSuspended = pdTRUE; + + /* API Call */ + EXPECT_ASSERT_BREAK( vTaskStepTick( xTicksToJump ) ); + + /* Test Verifications */ + validate_and_clear_assertions(); +} diff --git a/FreeRTOS/Test/CMock/smp/config_assert/list_macros.h b/FreeRTOS/Test/CMock/smp/config_assert/list_macros.h new file mode 100644 index 000000000..67061cc86 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/config_assert/list_macros.h @@ -0,0 +1,73 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef LIST_MACRO_H +#define LIST_MACRO_H + +#include +#include +#include +#include + +struct tskTaskControlBlock; + +#undef listLIST_IS_EMPTY +BaseType_t listLIST_IS_EMPTY( const List_t * pxList ); + +#undef listGET_OWNER_OF_HEAD_ENTRY +struct tskTaskControlBlock * listGET_OWNER_OF_HEAD_ENTRY( const List_t * pxList ); + +#undef listIS_CONTAINED_WITHIN +BaseType_t listIS_CONTAINED_WITHIN( List_t * list, + const ListItem_t * listItem ); + +#undef listGET_LIST_ITEM_VALUE +TickType_t listGET_LIST_ITEM_VALUE( ListItem_t * listItem ); + +#undef listSET_LIST_ITEM_VALUE +void listSET_LIST_ITEM_VALUE( ListItem_t * listItem, + TickType_t itemValue ); + +#undef listLIST_ITEM_CONTAINER +List_t * listLIST_ITEM_CONTAINER( const ListItem_t * listItem ); + +#undef listCURRENT_LIST_LENGTH +UBaseType_t listCURRENT_LIST_LENGTH( List_t * list ); + +#undef listGET_ITEM_VALUE_OF_HEAD_ENTRY +TickType_t listGET_ITEM_VALUE_OF_HEAD_ENTRY( List_t * list ); + +#undef listGET_LIST_ITEM_OWNER +struct tskTaskControlBlock * listGET_LIST_ITEM_OWNER( ListItem_t * listItem ); + +#undef listINSERT_END +void listINSERT_END( List_t * pxList, + ListItem_t * listItem ); + +#undef listREMOVE_ITEM +void listREMOVE_ITEM( ListItem_t * listItem ); + +#endif /* ifndef LIST_MACRO_H */ diff --git a/FreeRTOS/Test/CMock/smp/config_assert/local_portable.h b/FreeRTOS/Test/CMock/smp/config_assert/local_portable.h new file mode 100644 index 000000000..a26015931 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/config_assert/local_portable.h @@ -0,0 +1,40 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +#ifndef LOCAL_PORTABLE_H +#define LOCAL_PORTABLE_H + +BaseType_t xPortStartScheduler( void ); + +void vPortEndScheduler( void ); + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ); + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ); +#endif /* ifndef LOCAL_PORTABLE_H */ diff --git a/FreeRTOS/Test/CMock/smp/global_vars.h b/FreeRTOS/Test/CMock/smp/global_vars.h new file mode 100644 index 000000000..377cc274f --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/global_vars.h @@ -0,0 +1,148 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +#ifndef GLOBAL_VARS_H +#define GLOBAL_VARS_H + +#include "task.h" + +#include + +/* Indicates that the task is an Idle task. */ +#define taskATTRIBUTE_IS_IDLE ( UBaseType_t ) ( 1UL << 0UL ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskRUNNING_CHAR ( 'X' ) +#define tskBLOCKED_CHAR ( 'B' ) +#define tskREADY_CHAR ( 'R' ) +#define tskDELETED_CHAR ( 'D' ) +#define tskSUSPENDED_CHAR ( 'S' ) + +/* Values that can be assigned to the ucNotifyState member of the TCB. */ +#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */ +#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) +#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) + +/* Indicates that the task is not actively running on any core. */ +#define taskTASK_NOT_RUNNING ( TaskRunning_t ) ( -1 ) + +/* Indicates that the task is actively running but scheduled to yield. */ +#define taskTASK_YIELDING ( TaskRunning_t ) ( -2 ) + +#if ( configUSE_16_BIT_TICKS == 1 ) + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U +#else + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL +#endif + +typedef BaseType_t TaskRunning_t; + +typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */ +{ + volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + #endif + + #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) + UBaseType_t uxCoreAffinityMask; /*< Used to link the task to certain cores. UBaseType_t must have greater than or equal to the number of bits as confNUM_CORES. */ + #endif + + ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ + UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ + StackType_t * pxStack; /*< Points to the start of the stack. */ + #if ( configNUMBER_OF_CORES > 1 ) + volatile TaskRunning_t xTaskRunState; /*< Used to identify the core the task is running on, if the task is running. Otherwise, identifies the task's state - not running or yielding. */ + UBaseType_t uxTaskAttributes; /*< Task's attributes - currently used to identify the idle tasks. */ + #endif + char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + + #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + BaseType_t xPreemptionDisable; /*< Used to prevent the task from being preempted. */ + #endif + + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) + StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxMutexesHeld; + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t pxTaskTag; + #endif + + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + #endif + + #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) ) + configTLS_BLOCK_TYPE xTLSBlock; /*< Memory block used as Thread Local Storage (TLS) Block for the task. */ + #endif + + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + #endif + + /* See the comments in FreeRTOS.h with the definition of + * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ + #endif + + #if ( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDelayAborted; + #endif + + #if ( configUSE_POSIX_ERRNO == 1 ) + int iTaskErrno; + #endif +} tskTCB; + +/* The old tskTCB name is maintained above then typedefed to the new TCB_t name + * below to enable the use of older kernel aware debuggers. */ +typedef tskTCB TCB_t; + +#endif /* ifndef GLOBAL_VARS_H */ diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/FreeRTOSConfig.h new file mode 100644 index 000000000..2835008df --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/FreeRTOSConfig.h @@ -0,0 +1,158 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* https://www.FreeRTOS.org/a00110.html +*----------------------------------------------------------*/ + +/* SMP test specific configuration */ +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configNUMBER_OF_CORES 16 +#define configUSE_CORE_AFFINITY 1 +#define configUSE_TIME_SLICING 0 +#define configUSE_TASK_PREEMPTION_DISABLE 1 +#define configTICK_CORE 0 + +/* OS Configuration */ +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 +#define portREMOVE_STATIC_QUALIFIER 1 +#define portCRITICAL_NESTING_IN_TCB 1 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_MINIMAL_IDLE_HOOK 0 /* Keep this for backward compatibility. */ +#define configUSE_PASSIVE_IDLE_HOOK 0 + +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 4 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configENABLE_MPU 0 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +#define configASSERT( x ) \ + do \ + { \ + if( x ) \ + { \ + vFakeAssert( true, __FILE__, __LINE__ ); \ + } \ + else \ + { \ + vFakeAssert( false, __FILE__, __LINE__ ); \ + } \ + } while( 0 ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) + extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); + #define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer ) +#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/Makefile b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/Makefile new file mode 100644 index 000000000..daf2c0aeb --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/Makefile @@ -0,0 +1,47 @@ +# indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC := tasks.c + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +PROJECT_DEPS_SRC := list.c queue.c + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS := FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := multiple_priorities_no_timeslice_utest.c covg_multiple_priorities_no_timeslice_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +SUITE_SUPPORT_SRC := smp_utest_common.c + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_port.h + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS += + +# List any addiitonal flags needed by the compiler +CFLAGS += + +# Try not to edit beyond this line unless necessary. + +# Project is determined based on path: $(UT_ROOT_DIR)/$(PROJECT) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +# Make variables available to included makefile +export + +include ../../testdir.mk + + diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c new file mode 100644 index 000000000..c09082268 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c @@ -0,0 +1,4627 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file single_priority_no_timeslice_covg_utest */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 ) +#define tskSTACK_FILL_BYTE ( 0xa5U ) +#define TEST_VTASKLIST_BUFFER_SIZE ( 800 ) /* Size for task list. */ + +/* =========================== EXTERN VARIABLES =========================== */ +extern volatile UBaseType_t uxCurrentNumberOfTasks; +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile UBaseType_t uxSchedulerSuspended; +extern volatile TCB_t * pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern volatile BaseType_t xSchedulerRunning; +extern volatile TickType_t xTickCount; +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; +extern volatile UBaseType_t uxTopReadyPriority; +extern volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; +extern List_t xTasksWaitingTermination; +extern List_t xSuspendedTaskList; +extern List_t xPendingReadyList; +extern BaseType_t xPendedTicks; +extern List_t xDelayedTaskList1; +extern List_t xDelayedTaskList2; +extern List_t * pxDelayedTaskList; +extern List_t * pxOverflowDelayedTaskList; + +/* =========================== EXTERN FUNCTIONS =========================== */ +extern void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ); +extern void prvYieldForTask( TCB_t * pxTCB ); +extern void prvSelectHighestPriorityTask( BaseType_t xCoreID ); +extern void vTaskEnterCritical( void ); +extern UBaseType_t vTaskEnterCriticalFromISR( void ); +extern void vTaskExitCritical( void ); +extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); +extern void prvCheckTasksWaitingTermination( void ); +extern void prvDeleteTCB( TCB_t * pxTCB ); +extern TCB_t * prvSearchForNameWithinSingleList( List_t * pxList, + const char pcNameToQuery[] ); + +/* ============================== Global VARIABLES ============================== */ +TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + UBaseType_t uxPriority; + + commonSetUp(); + + for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xPendingReadyList ); + vListInitialise( &xDelayedTaskList1 ); + vListInitialise( &xDelayedTaskList2 ); + vListInitialise( &xTasksWaitingTermination ); + + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; + + /* Count memory allocate count. */ + UnityMalloc_StartTest(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); + + /* Verify memory allocate count. */ + UnityMalloc_EndTest(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================== Helper functions for Test Cases ============================== */ +static void prvPortEnterCriticalSectionCb( int cmock_num_calls ) +{ + ( void ) cmock_num_calls; + + /* This simulate the multiple idle tasks tries to clean the deleted TCB. */ + uxDeletedTasksWaitingCleanUp = 0; +} + +static void prvInitialiseTestStack( TCB_t * pxTCB, + const uint32_t ulStackDepth ) +{ + StackType_t * pxTopOfStack; + + pxTopOfStack = NULL; + + pxTCB->pxStack = ( StackType_t * ) pvPortMallocStack( + ( ( ( size_t ) ulStackDepth ) * sizeof( StackType_t ) ) ); + ( void ) memset( pxTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, + ( size_t ) ulStackDepth * sizeof( StackType_t ) ); + + #if ( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = &( pxTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & + ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); + + #if ( configRECORD_STACK_HIGH_ADDRESS == 1 ) + { + pxTCB->pxEndOfStack = pxTopOfStack; + } + #endif /* configRECORD_STACK_HIGH_ADDRESS */ + } + #else /* portSTACK_GROWTH */ + { + pxTopOfStack = pxTCB->pxStack; + pxTCB->pxEndOfStack = pxTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); + } + #endif /* portSTACK_GROWTH */ + + ( void ) pxTopOfStack; +} + +/* ============================ FreeRTOS static allocate function ============================ */ + +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize, + BaseType_t xCoreId ) +{ + static StaticTask_t xIdleTaskTCBs[ configNUMBER_OF_CORES ]; + static StackType_t uxIdleTaskStacks[ configNUMBER_OF_CORES ][ configMINIMAL_STACK_SIZE ]; + + *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBs[ xCoreId ] ); + *ppxIdleTaskStackBuffer = &( uxIdleTaskStacks[ xCoreId ][ 0 ] ); + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief vTaskPreemptionEnable - Enable preemption of a task when scheduler is not running. + * + * The xPreemptionDisable of the task will be set to pdFALSE. + * + * Coverage + * @code{c} + * if( xSchedulerRunning != pdFALSE ) + * { + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; + * prvYieldCore( xCoreID ); + * } + * } + * @endcode + * ( xSchedulerRunning != pdFALSE ) is false. + */ +void test_coverage_vTaskPreemptionEnable_scheduler_not_running( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup variables. */ + xTaskTCB.xPreemptionDisable = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskPreemptionEnable( &xTaskTCB ); + + /* Validation. */ + TEST_ASSERT( xTaskTCB.xPreemptionDisable == pdFALSE ); +} + +/** + * @brief vTaskPreemptionEnable - Enable preemption of a task when scheduler is running. + * + * The xPreemptionDisable of the task will be set to pdFALSE. + * + * Coverage + * @code{c} + * if( xSchedulerRunning != pdFALSE ) + * { + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; + * prvYieldCore( xCoreID ); + * } + * } + * @endcode + * ( xSchedulerRunning != pdFALSE ) is true. + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + */ +void test_coverage_vTaskPreemptionEnable_scheduler_running( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup variable. */ + xTaskTCB.xPreemptionDisable = pdTRUE; + xTaskTCB.xTaskRunState = -1; /* taskTASK_NOT_RUNNING. */ + + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskPreemptionEnable( &xTaskTCB ); + + /* Validation. */ + TEST_ASSERT( xTaskTCB.xPreemptionDisable == pdFALSE ); +} + +/** + * @brief vTaskPreemptionEnable - Enable preemption of a task with NULL handle. + * + * The xPreemptionDisable of the task on core 0 will be set to pdFALSE. + * + * Coverage + * @code{c} + * pxTCB = prvGetTCBFromHandle( xTask ); + * @endcode + * prvGetTCBFromHandle( xTask ) parameter xTask is NULL. + */ +void test_coverage_vTaskPreemptionEnable_null_handle( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxInterruptMask = 0x12345678; + + xTaskTCB.xPreemptionDisable = pdTRUE; + xTaskTCB.xTaskRunState = -1; /* taskTASK_NOT_RUNNING. */ + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + ulFakePortSetInterruptMask_StopIgnore(); + vFakePortClearInterruptMask_StubWithCallback( NULL ); + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + ulFakePortSetInterruptMask_ExpectAndReturn( uxInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( uxInterruptMask ); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskPreemptionEnable( NULL ); + + /* Expection. */ + TEST_ASSERT( pxCurrentTCBs[ 0 ]->xPreemptionDisable == pdFALSE ); +} + +/** + * @brief vTaskPreemptionEnable - Enable preemption of a task which is not running. + * + * The xPreemptionDisable of the task will be set to pdFALSE. The xTaskRunState is + * set to greater than ( configNUMBER_OF_CORES - 1 ). + * + * Coverage + * @code{c} + * if( xSchedulerRunning != pdFALSE ) + * { + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; + * prvYieldCore( xCoreID ); + * } + * } + * @endcode + * ( xSchedulerRunning != pdFALSE ) is true. + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + */ +void test_coverage_vTaskPreemptionEnable_task_not_running_gt_cores( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup variables. */ + xTaskTCB.xPreemptionDisable = pdTRUE; + xTaskTCB.xTaskRunState = configNUMBER_OF_CORES; + + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskPreemptionEnable( &xTaskTCB ); + + /* Validation. */ + TEST_ASSERT( xTaskTCB.xPreemptionDisable == pdFALSE ); +} + +/** + * @brief vTaskPreemptionEnable - Enable preemption of a task which is running. + * + * The xPreemptionDisable of the task will be set to pdFALSE. + * + * Coverage + * @code{c} + * if( xSchedulerRunning != pdFALSE ) + * { + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * xCoreID = ( BaseType_t ) pxTCB->xTaskRunState; + * prvYieldCore( xCoreID ); + * } + * } + * @endcode + * ( xSchedulerRunning != pdFALSE ) is true. + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is true. + */ +void test_coverage_vTaskPreemptionEnable_task_running( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup variables. */ + xTaskTCB.xPreemptionDisable = pdTRUE; + xTaskTCB.xTaskRunState = 0; + + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortCheckIfInISR_StopIgnore(); + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Expection in prvYieldCore. */ + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskPreemptionEnable( &xTaskTCB ); + + /* Validation. */ + TEST_ASSERT( xTaskTCB.xPreemptionDisable == pdFALSE ); +} + +/** + * @brief vTaskCoreAffinityGet - Get the affinity mask of a task. + * + * Verify the affinity mask returned with a task handle. + * + * Coverage + * @code{c} + * taskENTER_CRITICAL(); + * { + * pxTCB = prvGetTCBFromHandle( xTask ); + * uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; + * } + * taskEXIT_CRITICAL(); + * @endcode + * prvGetTCBFromHandle( xTask ) xTask is not NULL. + */ +void test_coverage_vTaskCoreAffinityGet( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxCoreAffinityMask; + + /* Setup variables. */ + xTaskTCB.uxCoreAffinityMask = 0x5555; /* The value to be verified later. */ + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + uxCoreAffinityMask = vTaskCoreAffinityGet( &xTaskTCB ); + + /* Validation. */ + TEST_ASSERT( uxCoreAffinityMask == 0x5555 ); +} + +/** + * @brief vTaskCoreAffinityGet - Get the affinity mask of current task. + * + * Verify the affinity mask returned with NULL task handle. Current task affinity + * mask should be returned. + * + * Coverage + * @code{c} + * taskENTER_CRITICAL(); + * { + * pxTCB = prvGetTCBFromHandle( xTask ); + * uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; + * } + * taskEXIT_CRITICAL(); + * @endcode + * prvGetTCBFromHandle( xTask ) xTask is NULL. + */ +void test_coverage_vTaskCoreAffinityGet_null_handle( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxCoreAffinityMask; + + /* Setup variables. */ + xTaskTCB.uxCoreAffinityMask = 0x5555; /* The value to be verified later. */ + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + uxCoreAffinityMask = vTaskCoreAffinityGet( NULL ); + + /* Validation. */ + TEST_ASSERT( uxCoreAffinityMask == 0x5555 ); +} + +/** + * @brief uxTaskGetTaskNumber - get the task number of a task handle. + * + * Verify the task number returned by uxTaskGetTaskNumber. + * + * Coverage + * @code{c} + * if( xTask != NULL ) + * { + * pxTCB = xTask; + * uxReturn = pxTCB->uxTaskNumber; + * } + * else + * { + * uxReturn = 0U; + * } + * @endcode + * ( xTask != NULL ) is true. + */ +void test_coverage_uxTaskGetTaskNumber_task_handle( void ) +{ + TCB_t xTaskTCB = { 0 }; + UBaseType_t uxTaskNumber = 0U; + + /* Setup the variables and structure. */ + xTaskTCB.uxTaskNumber = 0x5a5a; /* Value to be verified later. */ + + /* API call. */ + uxTaskNumber = uxTaskGetTaskNumber( &xTaskTCB ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0x5a5a, uxTaskNumber ); +} + +/** + * @brief uxTaskGetTaskNumber - get the task number of a NULL task handle. + * + * Verify the task number returned by uxTaskGetTaskNumber. + * + * Coverage + * @code{c} + * if( xTask != NULL ) + * { + * pxTCB = xTask; + * uxReturn = pxTCB->uxTaskNumber; + * } + * else + * { + * uxReturn = 0U; + * } + * @endcode + * ( xTask != NULL ) is false. + */ +void test_coverage_uxTaskGetTaskNumber_null_task_handle( void ) +{ + UBaseType_t uxTaskNumber = 0x5a5a; + + /* API call. */ + uxTaskNumber = uxTaskGetTaskNumber( NULL ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0U, uxTaskNumber ); +} + +/** + * @brief vTaskSetTaskNumber - set the task number of a task handle. + * + * Verify the task number set by vTaskSetTaskNumber. + * + * Coverage + * @code{c} + * if( xTask != NULL ) + * { + * pxTCB = xTask; + * pxTCB->uxTaskNumber = uxHandle; + * } + * @endcode + * ( xTask != NULL ) is true. + */ +void test_coverage_vTaskSetTaskNumber_task_handle( void ) +{ + TCB_t xTaskTCB = { 0 }; + + /* Setup the variables and structure. */ + xTaskTCB.uxTaskNumber = 0; + + /* API call. */ + vTaskSetTaskNumber( &xTaskTCB, 0x5a5a ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0x5a5a, xTaskTCB.uxTaskNumber ); +} + +/** + * @brief vTaskSetTaskNumber - set the task number of a task handle. + * + * The test show its result in the coverage report. + * + * Coverage + * @code{c} + * if( xTask != NULL ) + * { + * pxTCB = xTask; + * pxTCB->uxTaskNumber = uxHandle; + * } + * @endcode + * ( xTask != NULL ) is false. + */ +void test_coverage_vTaskSetTaskNumber_null_task_handle( void ) +{ + /* API call. */ + vTaskSetTaskNumber( NULL, 0x5a5a ); + + /* Validation. */ + /* Nothing will be changed. This test shows its result in the coverage report. */ +} + +/** + * @brief uxTaskGetStackHighWaterMark - return high water mark of a task. + * + * Verify the high water mark returned. + * + * Coverage + * @code{c} + * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + * { + * ... + * } + * @endcode + * xTask is not NULL. + */ +void test_coverage_uxTaskGetStackHighWaterMark( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxReturn; + + /* Setup the variables and structure. */ + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + + /* API call. */ + uxReturn = uxTaskGetStackHighWaterMark( &xTaskTCB ); + + /* Validations. */ + /* The stack is not used in this test. Verify the high water mark index. */ + TEST_ASSERT_EQUAL( configMINIMAL_STACK_SIZE - 1, uxReturn ); + + /* Clean the allocated memory in the test. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Verify memory allocate count in tearDown function. */ +} + +/** + * @brief uxTaskGetStackHighWaterMark - return high water mark of NULL task handle. + * + * Verify the high water mark returned. + * + * Coverage + * @code{c} + * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + * { + * ... + * } + * @endcode + * xTask is NULL. + */ +void test_coverage_uxTaskGetStackHighWaterMark_null_task_handle( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxReturn; + + /* Setup the variables and structure. */ + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* API call. */ + uxReturn = uxTaskGetStackHighWaterMark( NULL ); + + /* Validations. */ + /* The stack is not used in this test. Verify the high water mark index. */ + TEST_ASSERT_EQUAL( configMINIMAL_STACK_SIZE - 1, uxReturn ); + + /* Clean the allocated memory in the test. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Verify memory allocate count in tearDown function. */ +} + +/** + * @brief xTaskGetCurrentTaskHandleForCore - get current task handle with valid core ID. + * + * This test verifiesthe task handle returned with a valid core ID. + * + * Coverage + * @code{c} + * TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) + * { + * TaskHandle_t xReturn = NULL; + * + * if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) + * { + * xReturn = pxCurrentTCBs[ xCoreID ]; + * } + * + * return xReturn; + * } + * @endcode + * ( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) is true. + */ +void test_coverage_xTaskGetCurrentTaskHandleForCore_valid_core_id( void ) +{ + TCB_t xTaskTCB = { 0 }; + TaskHandle_t xTaskHandle; + + /* Setup the variables and structure. */ + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* API calls. */ + xTaskHandle = xTaskGetCurrentTaskHandleForCore( 0 ); + + /* Validation. */ + TEST_ASSERT( xTaskHandle == &xTaskTCB ); +} + +/** + * @brief xTaskGetCurrentTaskHandleForCore - get current task handle with invalid core ID. + * + * This test verifiesthe task handle returned with an invalid core ID. + * + * Coverage + * @code{c} + * TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) + * { + * TaskHandle_t xReturn = NULL; + * + * if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) + * { + * xReturn = pxCurrentTCBs[ xCoreID ]; + * } + * + * return xReturn; + * } + * @endcode + * ( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) is false. + * xCoreID is greater than or equal to configNUMBER_OF_CORES. + */ +void test_coverage_xTaskGetCurrentTaskHandleForCore_invalid_core_id_ge( void ) +{ + TCB_t xTaskTCB = { 0 }; + TaskHandle_t xTaskHandle; + + /* Setup the variables and structure. */ + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* API calls. */ + xTaskHandle = xTaskGetCurrentTaskHandleForCore( configNUMBER_OF_CORES ); + + /* Validation. */ + TEST_ASSERT( xTaskHandle == NULL ); +} + +/** + * @brief xTaskGetCurrentTaskHandleForCore - get current task handle with invalid core ID. + * + * This test verifiesthe task handle returned with an invalid core ID. + * + * Coverage + * @code{c} + * TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) + * { + * TaskHandle_t xReturn = NULL; + * + * if( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) + * { + * xReturn = pxCurrentTCBs[ xCoreID ]; + * } + * + * return xReturn; + * } + * @endcode + * ( taskVALID_CORE_ID( xCoreID ) != pdFALSE ) is false. + * xCoreID is less than 0. + */ +void test_coverage_xTaskGetCurrentTaskHandleForCore_invalid_core_id_lt( void ) +{ + TCB_t xTaskTCB = { 0 }; + TaskHandle_t xTaskHandle; + + /* Setup the variables and structure. */ + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* API calls. */ + xTaskHandle = xTaskGetCurrentTaskHandleForCore( -1 ); + + /* Validation. */ + TEST_ASSERT( xTaskHandle == NULL ); +} + +/** + * @brief vTaskList - No task is created. + * + * This API is called before any task is created. + * + * Coverage + * @code{c} + * if( pxTaskStatusArray != NULL ) + * { + * ... + * } + * @endcode + * ( pxTaskStatusArray != NULL ) is false. + */ +void test_coverage_vTaskList_no_task_created( void ) +{ + char pcWriteBuffer[ TEST_VTASKLIST_BUFFER_SIZE ] = "Test"; /* Validate the string is overwritten in the API call. */ + + /* Setup the variables and structure. */ + uxCurrentNumberOfTasks = 0; /* No task is created. */ + + /* API calls. */ + vTaskList( pcWriteBuffer ); + + /* Validation. */ + /* Verify memory allocate count in tearDown function. */ + /* No task is created. A string with zero legnth is returned. */ + TEST_ASSERT_EQUAL( 0x00, pcWriteBuffer[ 0 ] ); +} + +/** + * @brief vTaskList - Task with state eRunning. + * + * Coverage + * @code{c} + * switch( pxTaskStatusArray[ x ].eCurrentState ) + * { + * ... + * case eRunning: + * cStatus = tskRUNNING_CHAR; + * break; + * ... + * } + * @endcode + * ( pxTaskStatusArray[ x ].eCurrentState ) is eRunning. + */ +void test_coverage_vTaskList_task_eRunning( void ) +{ + TCB_t xTaskTCB = { NULL }; + char pcExpectedResult[ TEST_VTASKLIST_BUFFER_SIZE ] = { 0 }; + char pcWriteBuffer[ TEST_VTASKLIST_BUFFER_SIZE ] = "Test"; /* Validate the string is overwritten in the API call. */ + int xStringCompareResult; + char pcGeneratedTaskName[ configMAX_TASK_NAME_LEN ]; + uint32_t i; + + /* Setup the variables and structure. */ + xSchedulerRunning = pdTRUE; + + /* Create one task with state eDeleted. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.pcTaskName[ 0 ] = '\0'; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.uxTaskAttributes = -1; + xTaskTCB.xTaskRunState = 0; + xTaskTCB.uxTaskNumber = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCB.xStateListItem ); + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* API calls. */ + vTaskList( pcWriteBuffer ); + + /* Clean up malloc for stack. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Validation. */ + /* Verify memory allocate count in tearDown function. */ + + /* Verify the returned string. */ + for( i = 0; i < ( configMAX_TASK_NAME_LEN - 1 ); i++ ) + { + pcGeneratedTaskName[ i ] = ' '; + } + + pcGeneratedTaskName[ i ] = '\0'; + + sprintf( pcExpectedResult, "%s\t%c\t%u\t%u\t%u\t0x%x\r\n", pcGeneratedTaskName, tskRUNNING_CHAR, + ( unsigned int ) xTaskTCB.uxPriority, ( unsigned int ) ( configMINIMAL_STACK_SIZE - 1U ), + ( unsigned int ) xTaskTCB.uxTaskNumber, ( unsigned int ) ( ( 1U << configNUMBER_OF_CORES ) - 1U ) ); + xStringCompareResult = strcmp( pcExpectedResult, pcWriteBuffer ); + TEST_ASSERT_EQUAL( 0, xStringCompareResult ); +} + +/** + * @brief vTaskList - Task with state eReady. + * + * Coverage + * @code{c} + * switch( pxTaskStatusArray[ x ].eCurrentState ) + * { + * ... + * case eReady: + * cStatus = tskREADY_CHAR; + * break; + * ... + * } + * @endcode + * ( pxTaskStatusArray[ x ].eCurrentState ) is eReady. + */ +void test_coverage_vTaskList_task_eReady( void ) +{ + TCB_t xTaskTCB = { NULL }; + char pcExpectedResult[ TEST_VTASKLIST_BUFFER_SIZE ] = { 0 }; + char pcWriteBuffer[ TEST_VTASKLIST_BUFFER_SIZE ] = "Test"; /* Validate the string is overwritten in the API call. */ + int xStringCompareResult; + char pcGeneratedTaskName[ configMAX_TASK_NAME_LEN ]; + uint32_t i; + + /* Setup the variables and structure. */ + xSchedulerRunning = pdTRUE; + + /* Create one task with state eDeleted. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.pcTaskName[ 0 ] = '\0'; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.uxTaskAttributes = -1; + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxTaskNumber = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCB.xStateListItem ); + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* API calls. */ + vTaskList( pcWriteBuffer ); + + /* Clean up malloc for stack. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Validation. */ + /* Verify memory allocate count in tearDown function. */ + + /* Verify the returned string. */ + for( i = 0; i < ( configMAX_TASK_NAME_LEN - 1 ); i++ ) + { + pcGeneratedTaskName[ i ] = ' '; + } + + pcGeneratedTaskName[ i ] = '\0'; + + sprintf( pcExpectedResult, "%s\t%c\t%u\t%u\t%u\t0x%x\r\n", pcGeneratedTaskName, tskREADY_CHAR, + ( unsigned int ) xTaskTCB.uxPriority, ( unsigned int ) ( configMINIMAL_STACK_SIZE - 1U ), + ( unsigned int ) xTaskTCB.uxTaskNumber, ( unsigned int ) ( ( 1U << configNUMBER_OF_CORES ) - 1U ) ); + xStringCompareResult = strcmp( pcExpectedResult, pcWriteBuffer ); + TEST_ASSERT_EQUAL( 0, xStringCompareResult ); +} + +/** + * @brief vTaskList - Task with state eBlocked. + * + * Coverage + * @code{c} + * switch( pxTaskStatusArray[ x ].eCurrentState ) + * { + * ... + * case eBlocked: + * cStatus = tskBLOCKED_CHAR; + * break; + * ... + * } + * @endcode + * ( pxTaskStatusArray[ x ].eCurrentState ) is eBlocked. + */ +void test_coverage_vTaskList_task_eBlocked( void ) +{ + TCB_t xTaskTCB = { NULL }; + char pcExpectedResult[ TEST_VTASKLIST_BUFFER_SIZE ] = { 0 }; + char pcWriteBuffer[ TEST_VTASKLIST_BUFFER_SIZE ] = "Test"; /* Validate the string is overwritten in the API call. */ + int xStringCompareResult; + char pcGeneratedTaskName[ configMAX_TASK_NAME_LEN ]; + uint32_t i; + + /* Setup the variables and structure. */ + xSchedulerRunning = pdTRUE; + + /* Create one task with state eDeleted. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.pcTaskName[ 0 ] = '\0'; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.uxTaskAttributes = -1; + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxTaskNumber = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xStateListItem.pxContainer = pxDelayedTaskList; + listINSERT_END( pxDelayedTaskList, &xTaskTCB.xStateListItem ); + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* API calls. */ + vTaskList( pcWriteBuffer ); + + /* Clean up malloc for stack. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Validation. */ + /* Verify memory allocate count in tearDown function. */ + + /* Verify the returned string. */ + for( i = 0; i < ( configMAX_TASK_NAME_LEN - 1 ); i++ ) + { + pcGeneratedTaskName[ i ] = ' '; + } + + pcGeneratedTaskName[ i ] = '\0'; + + sprintf( pcExpectedResult, "%s\t%c\t%u\t%u\t%u\t0x%x\r\n", pcGeneratedTaskName, tskBLOCKED_CHAR, + ( unsigned int ) xTaskTCB.uxPriority, ( unsigned int ) ( configMINIMAL_STACK_SIZE - 1U ), + ( unsigned int ) xTaskTCB.uxTaskNumber, ( unsigned int ) ( ( 1U << configNUMBER_OF_CORES ) - 1U ) ); + xStringCompareResult = strcmp( pcExpectedResult, pcWriteBuffer ); + TEST_ASSERT_EQUAL( 0, xStringCompareResult ); +} + +/** + * @brief vTaskList - Task with state eSuspended. + * + * Coverage + * @code{c} + * switch( pxTaskStatusArray[ x ].eCurrentState ) + * { + * ... + * case eSuspended: + * cStatus = tskSUSPENDED_CHAR; + * break; + * ... + * } + * @endcode + * ( pxTaskStatusArray[ x ].eCurrentState ) is eSuspended. + */ +void test_coverage_vTaskList_task_eSuspended( void ) +{ + TCB_t xTaskTCB = { NULL }; + char pcExpectedResult[ TEST_VTASKLIST_BUFFER_SIZE ] = { 0 }; + char pcWriteBuffer[ TEST_VTASKLIST_BUFFER_SIZE ] = "Test"; /* Validate the string is overwritten in the API call. */ + int xStringCompareResult; + char pcGeneratedTaskName[ configMAX_TASK_NAME_LEN ]; + uint32_t i; + + /* Setup the variables and structure. */ + xSchedulerRunning = pdTRUE; + + /* Create one task with state eDeleted. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.pcTaskName[ 0 ] = '\0'; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.uxTaskAttributes = -1; + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxTaskNumber = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* API calls. */ + vTaskList( pcWriteBuffer ); + + /* Clean up malloc for stack. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Validation. */ + /* Verify memory allocate count in tearDown function. */ + + /* Verify the returned string. */ + for( i = 0; i < ( configMAX_TASK_NAME_LEN - 1 ); i++ ) + { + pcGeneratedTaskName[ i ] = ' '; + } + + pcGeneratedTaskName[ i ] = '\0'; + + sprintf( pcExpectedResult, "%s\t%c\t%u\t%u\t%u\t0x%x\r\n", pcGeneratedTaskName, tskSUSPENDED_CHAR, + ( unsigned int ) xTaskTCB.uxPriority, ( unsigned int ) ( configMINIMAL_STACK_SIZE - 1U ), + ( unsigned int ) xTaskTCB.uxTaskNumber, ( unsigned int ) ( ( 1U << configNUMBER_OF_CORES ) - 1U ) ); + xStringCompareResult = strcmp( pcExpectedResult, pcWriteBuffer ); + TEST_ASSERT_EQUAL( 0, xStringCompareResult ); +} + +/** + * @brief vTaskList - Task with state eDeleted. + * + * Coverage + * @code{c} + * switch( pxTaskStatusArray[ x ].eCurrentState ) + * { + * ... + * case eDeleted: + * cStatus = tskDELETED_CHAR; + * break; + * ... + * } + * @endcode + * ( pxTaskStatusArray[ x ].eCurrentState ) is eDeleted. + */ +void test_coverage_vTaskList_task_eDeleted( void ) +{ + TCB_t xTaskTCB = { NULL }; + char pcExpectedResult[ TEST_VTASKLIST_BUFFER_SIZE ] = { 0 }; + char pcWriteBuffer[ TEST_VTASKLIST_BUFFER_SIZE ] = "Test"; /* Validate the string is overwritten in the API call. */ + int xStringCompareResult; + char pcGeneratedTaskName[ configMAX_TASK_NAME_LEN ]; + uint32_t i; + + /* Setup the variables and structure. */ + xSchedulerRunning = pdTRUE; + + /* Create one task with state eDeleted. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.pcTaskName[ 0 ] = '\0'; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.uxTaskAttributes = -1; + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxTaskNumber = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xStateListItem.pxContainer = &xTasksWaitingTermination; + listINSERT_END( &xTasksWaitingTermination, &xTaskTCB.xStateListItem ); + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* API calls. */ + vTaskList( pcWriteBuffer ); + + /* Clean up malloc for stack. */ + vPortFreeStack( xTaskTCB.pxStack ); + + /* Validation. */ + /* Verify memory allocate count in tearDown function. */ + + /* Verify the returned string. */ + for( i = 0; i < ( configMAX_TASK_NAME_LEN - 1 ); i++ ) + { + pcGeneratedTaskName[ i ] = ' '; + } + + pcGeneratedTaskName[ i ] = '\0'; + + sprintf( pcExpectedResult, "%s\t%c\t%u\t%u\t%u\t0x%x\r\n", pcGeneratedTaskName, tskDELETED_CHAR, + ( unsigned int ) xTaskTCB.uxPriority, ( unsigned int ) ( configMINIMAL_STACK_SIZE - 1U ), + ( unsigned int ) xTaskTCB.uxTaskNumber, ( unsigned int ) ( ( 1U << configNUMBER_OF_CORES ) - 1U ) ); + xStringCompareResult = strcmp( pcExpectedResult, pcWriteBuffer ); + TEST_ASSERT_EQUAL( 0, xStringCompareResult ); +} + +/** + * @brief xTaskDelayUntil - current task should delay. + * + * The task delay itself until 5 ticks later. Verify that the return value should + * indicate the task is actually delayed. Cover the path that vTaskYieldWithinAPI + * is called for a task calls xTaskDelayUntil if xTaskResumeAll returns pdFALSE. + * + * Coverage + * @code{c} + * if( xAlreadyYielded == pdFALSE ) + * { + * #if ( configNUMBER_OF_CORES == 1 ) + * portYIELD_WITHIN_API(); + * #else + * vTaskYieldWithinAPI(); + * #endif + * } + * @endcode + * ( xAlreadyYielded == pdFALSE ) is true. + */ +void test_coverage_xTaskDelayUntil_current_task_should_delay( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TickType_t xPreviousWakeTime = 10; + BaseType_t xShouldDelay; + + /* Setup the variables and structure. */ + + /* ( xPreviousWakeTime + 10 ) is greater than xTickCount. The return value should + * indicate that the task is actual delayed. */ + xTickCount = 15; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCBs[ i ].uxTaskAttributes = -1; + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Expectations. */ + vFakePortYield_StubWithCallback( NULL ); + vFakePortYield_Expect(); + + /* API call. */ + xShouldDelay = xTaskDelayUntil( &xPreviousWakeTime, 10 ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 1, xShouldDelay ); +} + +/** + * @brief prvAddNewTaskToReadyList - add a new idle task to the list of ready tasks + * + * This test covers the prvAddNewTaskToReadyList for SMP, which is surrounded by + * ( configNUMBER_OF_CORES > 1 ). More tasks than cores are created to test the for + * loop condition when the scheduler is not running. + * + * Coverage + * @code{c} + * for( xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ ) + * @endcode + * for loop condition ( xCoreID < configNUMBER_OF_CORES ) is false. + */ +void test_coverage_prvAddNewTaskToReadyList_create_more_idle_tasks_than_cores( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + uxTopReadyPriority = tskIDLE_PRIORITY; + uxCurrentNumberOfTasks = 0; + xSchedulerRunning = pdFALSE; + + /* Create idle tasks and add it into the ready list. Create one more idle priority level + * in the loop. */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1U ); i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCBs[ i ].uxTaskAttributes = -1; + + if( i < configNUMBER_OF_CORES ) + { + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + else + { + /* Create one more idle task to be added to ready list. */ + xTaskTCBs[ i ].xTaskRunState = taskTASK_NOT_RUNNING; + } + } + + /* API calls. */ + prvAddNewTaskToReadyList( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validations. The run state of this task is still taskTASK_NOT_RUNNING. */ + configASSERT( xTaskTCBs[ configNUMBER_OF_CORES + 1U ].xTaskRunState == taskTASK_NOT_RUNNING ); +} + +/** + * @brief vTaskCoreAffinitySet - Set core mask with NULL task handle. + * + * Core mask of current task will be set if the parameter xTask is NULL. The task + * is not able to run on current runnning core. Verify that the mask is set correctly + * and yield pending is set. + * + * Coverage + * @code{c} + * pxTCB = prvGetTCBFromHandle( xTask ); + * + * uxPrevCoreAffinityMask = pxTCB->uxCoreAffinityMask; + * pxTCB->uxCoreAffinityMask = uxCoreAffinityMask; + * + * if( xSchedulerRunning != pdFALSE ) + * { + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * ... + * if( ( uxCoreAffinityMask & ( 1 << xCoreID ) ) == 0 ) + * { + * prvYieldCore( xCoreID ); + * } + * } + * } + * @endcode + * prvGetTCBFromHandle( xTask ) xTask is NULL. + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is true. + * ( ( uxCoreAffinityMask & ( 1 << xCoreID ) ) == 0 ) is true. + */ +void test_coverage_vTaskCoreAffinitySet_null_task_handle( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxCoreAffinityMask; + UBaseType_t uxNewCoreAffinityMask; + + /* Setup the variables and structure. */ + uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + vCreateStaticTestTaskAffinity( &xTaskTCB, + uxCoreAffinityMask, + tskIDLE_PRIORITY, + 0, + pdFALSE ); + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Expectations. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + vFakePortCheckIfInISR_StopIgnore(); + + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + /* Task is not able to run on current core. This core will be requested to yield. */ + uxNewCoreAffinityMask = uxCoreAffinityMask & ( ~( 1 << 0 ) ); + vTaskCoreAffinitySet( NULL, uxNewCoreAffinityMask ); + + /* Validations. */ + TEST_ASSERT_EQUAL( uxNewCoreAffinityMask, xTaskTCB.uxCoreAffinityMask ); + TEST_ASSERT_EQUAL( pdTRUE, xYieldPendings[ 0 ] ); +} + +/** + * @brief vTaskCoreAffinitySet - no new core for task which is not running. + * + * Set core mask for a not running task. The new core mask doesn't enable the task + * to run on any new core. Verify the core mask set is correct. + * + * Coverage + * @code{c} + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * ... + * } + * else + * { + * if( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) != 0U ) + * { + * prvYieldForTask( pxTCB ); + * } + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + * ( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) != 0U ) is false. + */ +void test_coverage_vTaskCoreAffinitySet_task_not_running_no_new_core( void ) +{ + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxCoreAffinityMask; + UBaseType_t uxNewCoreAffinityMask; + + /* Setup the variables and structure. */ + /* This task is allowed to run on core 0 and core 1 only. */ + uxCoreAffinityMask = ( 1U << 0 ) | ( 1U << 1 ); + vCreateStaticTestTaskAffinity( &xTaskTCB, + uxCoreAffinityMask, + tskIDLE_PRIORITY, + configNUMBER_OF_CORES, + pdFALSE ); + xSchedulerRunning = pdTRUE; + + /* Expectations. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + vFakePortCheckIfInISR_StopIgnore(); + + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + /* No new core is enabled for this task. */ + uxNewCoreAffinityMask = ( 1U << 0 ); + vTaskCoreAffinitySet( &xTaskTCB, uxNewCoreAffinityMask ); + + /* Validations. */ + TEST_ASSERT_EQUAL( uxNewCoreAffinityMask, xTaskTCB.uxCoreAffinityMask ); +} + +/** + * @brief prvYieldForTask - running task with xTaskRunState equals to configNUMBER_OF_CORES. + * + * Yield for a task of equal priority. No other task should be requested to yield. + * + * Coverage + * @code{c} + * if( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) && ( xYieldPendings[ xCoreID ] == pdFALSE ) ) + * { + * if( xCurrentCoreTaskPriority <= xLowestPriorityToPreempt ) + * { + * @endcode + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) is false. + */ +void test_coverage_prvYieldForTask_task_is_running_eq( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1U ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = 1; + xTaskTCBs[ i ].xTaskRunState = i; + xYieldPendings[ i ] = pdFALSE; + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Set one of the running xTaskRunState equals to configNUMBER_OF_CORES. */ + xTaskTCBs[ 0 ].xTaskRunState = configNUMBER_OF_CORES; + + /* Create one more task with equal priority. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority = 1; + + /* API call. */ + prvYieldForTask( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* Core 0 will not be requested to yield. */ + TEST_ASSERT( xTaskTCBs[ 0 ].xTaskRunState != taskTASK_YIELDING ); + + /* No core will be requested to yield. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT( xYieldPendings[ i ] != pdTRUE ); + } +} + +/** + * @brief prvYieldForTask - running task with xTaskRunState is taskTASK_YIELDING. + * + * Yield for a task of equal priority. No other task should be requested to yield. + * + * Coverage + * @code{c} + * if( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) && ( xYieldPendings[ xCoreID ] == pdFALSE ) ) + * { + * if( xCurrentCoreTaskPriority <= xLowestPriorityToPreempt ) + * { + * @endcode + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) is false. + */ +void test_coverage_prvYieldForTask_task_yielding( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1U ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = 1; + xTaskTCBs[ i ].xTaskRunState = i; + xYieldPendings[ i ] = pdFALSE; + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Set xTaskRunState of the running task to taskTASK_YIELDING. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_YIELDING; + + /* Create one more task with equal priority. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority = 1; + + /* API call. */ + prvYieldForTask( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* Core 0 remains of state taskTASK_YIELDING. */ + TEST_ASSERT( xTaskTCBs[ 0 ].xTaskRunState == taskTASK_YIELDING ); + + /* No core will be requested to yield. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT( xYieldPendings[ i ] != pdTRUE ); + } +} + +/** + * @brief prvYieldForTask - running task with yield pending. + * + * Yield for a task of equal priority. No other task should be requested to yield. + * + * Coverage + * @code{c} + * if( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) != pdFALSE ) && ( xYieldPendings[ xCoreID ] == pdFALSE ) ) + * { + * if( xCurrentCoreTaskPriority <= xLowestPriorityToPreempt ) + * { + * @endcode + * ( xYieldPendings[ xCoreID ] == pdFALSE ) is false. + */ +void test_coverage_prvYieldForTask_task_yield_pending( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1U ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = 1; + xTaskTCBs[ i ].xTaskRunState = i; + xYieldPendings[ i ] = pdFALSE; + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Set one of the running core with yield pending. */ + xYieldPendings[ 0 ] = pdTRUE; + + /* Create one more task with equal priority. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority = 1; + + /* API call. */ + prvYieldForTask( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* Core 0 remains yield pending. */ + TEST_ASSERT( xYieldPendings[ 0 ] == pdTRUE ); + + /* Other core will not be requested to yield. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT( xYieldPendings[ i ] != pdTRUE ); + } +} + +/* @brief prvSelectHighestPriorityTask - task with preemption disabled. + * + * prvSelectHighestPriorityTask selects a task to run on specified core. The scheduler + * also selects another core to yield for previous task if the condition is satisfied. + * This test verifies the coverage of preemption disabled condition. + * + * Coverage + * @code{c} + * if( ( xTaskPriority < xLowestPriority ) && + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) && + * ( xYieldPendings[ uxCore ] == pdFALSE ) ) + * { + * #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + * if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) + * #endif + * { + * xLowestPriority = xTaskPriority; + * xLowestPriorityCore = uxCore; + * } + * } + * @endcode + * ( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) is false. + */ +void test_coverage_prvSelectHighestPriorityTask_affinity_preemption_disabled( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 2 ] = { 0 }; + uint32_t i = 0; + + /* Setup the variables and structure. */ + + /* Initialize the idle priority ready list and set top ready priority to higher + * priority than idle. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxCurrentNumberOfTasks = 0; + + /* Create core numbers running idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + i, + pdTRUE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create two higher priority normal task. */ + for( i = configNUMBER_OF_CORES; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY + 1, + taskTASK_NOT_RUNNING, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Core 0 runs task TN. The original core 0 idle task now is not running. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ configNUMBER_OF_CORES ]; + xTaskTCBs[ configNUMBER_OF_CORES ].xTaskRunState = 0; + + /* Task 1 has preemption disabled. */ + xTaskTCBs[ 1 ].xPreemptionDisable = pdTRUE; + + /* Setup the affinity mask for TN and TN+1. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxCoreAffinityMask = ( 1 << 0 ) | ( 1 << 1 ); + xTaskTCBs[ configNUMBER_OF_CORES + 1 ].uxCoreAffinityMask = ( 1 << 0 ); + + /* The ready list has the following status. + * Ready list [ 0 ] : T0, T1(preemption disabled), T2(2), ..., TN-1(N-1). + * Ready list [ 1 ] : TN(0), TN+1. */ + + /* API calls. Select task for core 0. Task TN+1 will be selected. Scheduler + * tries to find another core to yield for TN. The affinity mask limited the + * core for TN to run on core 1 only ( core 0 is running TN+1 ). Idle task 1 has + * preemption disabled. Therefore, no core will yield for TN. */ + prvSelectHighestPriorityTask( 0 ); + + /* Validations.*/ + + /* T0 won't be selected to run after calling prvSelectHighestPriorityTask since + * it can only runs on core 0 and core 1. Task on core 1 is yielding. */ + TEST_ASSERT_NOT_EQUAL( &xTaskTCBs[ 0 ], pxCurrentTCBs[ 0 ] ); + /* T1 is still running on core 1 since it has preemption disabled. */ + TEST_ASSERT_EQUAL( &xTaskTCBs[ 1 ], pxCurrentTCBs[ 1 ] ); + /* TN+1 is selected to run on core 0. */ + TEST_ASSERT_EQUAL( 0, xTaskTCBs[ configNUMBER_OF_CORES + 1 ].xTaskRunState ); +} + +/** + * @brief prvSelectHighestPriorityTask - task with preemption enabled. + * + * prvSelectHighestPriorityTask selects a task to run on specified core. The scheduler + * also selects another core to yield for previous task if the condition is satisfied. + * This test verifies the coverage of preemption enabled condition. + * + * Coverage + * @code{c} + * if( ( xTaskPriority < xLowestPriority ) && + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) && + * ( xYieldPendings[ uxCore ] == pdFALSE ) ) + * { + * #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + * if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) + * #endif + * { + * xLowestPriority = xTaskPriority; + * xLowestPriorityCore = uxCore; + * } + * } + * @endcode + * ( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) is true. + */ +void test_coverage_prvSelectHighestPriorityTask_affinity_preemption_enabled( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 2 ] = { 0 }; + uint32_t i = 0; + + /* Setup the variables and structure. */ + + /* Initialize the idle priority ready list and set top ready priority to higher + * priority than idle. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxCurrentNumberOfTasks = 0; + + /* Create core numbers running idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + i, + pdTRUE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create two higher priority normal task. */ + for( i = configNUMBER_OF_CORES; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY + 1, + taskTASK_NOT_RUNNING, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Core 0 runs task TN. The original core 0 idle task now is not running. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ configNUMBER_OF_CORES ]; + xTaskTCBs[ configNUMBER_OF_CORES ].xTaskRunState = 0; + + /* Task 1 has preemption disabled. */ + xTaskTCBs[ 1 ].xPreemptionDisable = pdFALSE; + + /* Setup the affinity mask for TN and TN+1. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxCoreAffinityMask = ( 1 << 0 ) | ( 1 << 1 ); + xTaskTCBs[ configNUMBER_OF_CORES + 1 ].uxCoreAffinityMask = ( 1 << 0 ); + + /* The ready list has the following status. + * Ready list [ 0 ] : T0, T1(preemption enabled), T2(2), ..., TN-1(N-1). + * Ready list [ 1 ] : TN(0), TN+1. */ + + vFakePortYieldCore_StubWithCallback( NULL ); + vFakePortYieldCore_Expect( 1 ); + + /* API calls. Select task for core 0. Task TN+1 will be selected. Scheduler + * tries to find another core to yield for TN. The affinity mask limited the + * core for TN to run on core 1 only ( core 0 is running TN+1 ). Idle task 1 has + * preemption enabled. Therefore, core 1 will yield for TN. Task 1 will be of + * yielding state. */ + prvSelectHighestPriorityTask( 0 ); + + /* Validations.*/ + + /* T0 won't be selected to run after calling prvSelectHighestPriorityTask since + * it can only runs on core 0 and core 1. Task on core 1 is yielding. */ + TEST_ASSERT_NOT_EQUAL( &xTaskTCBs[ 0 ], pxCurrentTCBs[ 0 ] ); + /* T1 will be requested to yield. */ + TEST_ASSERT_EQUAL( taskTASK_YIELDING, xTaskTCBs[ 1 ].xTaskRunState ); +} + +/** + * @brief xTaskRemoveFromEventList - Remove a equal priority task from event list. + * + * The task is removed from event list. Verified this task is put back to ready list + * and removed from event list. Current core is not requested to yield. + * + * Coverage + * @code{c} + * #else + * { + * xReturn = pdFALSE; + * + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxUnblockedTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) + * { + * xReturn = pdTRUE; + * } + * } + * #endif + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) is false. + */ +void test_coverage_xTaskRemoveFromEventList_remove_eq_priority_task( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + List_t xEventList = { 0 }; + uint32_t i; + BaseType_t xReturn; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Expectations. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get portGET_CRITICAL_NESTING_COUNT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get prvYieldCore. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get portGET_CRITICAL_NESTING_COUNT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get xYieldPendings. */ + + /* API call. */ + xReturn = xTaskRemoveFromEventList( &xEventList ); + + /* Validations. */ + /* Yield not required for current core due to equal priority. */ + TEST_ASSERT_EQUAL( pdFALSE, xReturn ); + /* Task is removed from event list. */ + TEST_ASSERT_EQUAL( NULL, xTaskTCB.xEventListItem.pvContainer ); + /* Task is added to ready list. */ + TEST_ASSERT_EQUAL( &pxReadyTasksLists[ xTaskTCB.uxPriority ], xTaskTCB.xStateListItem.pvContainer ); +} + +/** + * @brief xTaskRemoveFromEventList - Remove a higher priority task from event list. + * + * The task is removed from event list. Verified this task is put back to ready list + * and removed from event list. Current core is requested to yield. + * + * Coverage + * @code{c} + * #else + * { + * xReturn = pdFALSE; + * + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxUnblockedTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) + * { + * xReturn = pdTRUE; + * } + * } + * #endif + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) is true. + */ +void test_coverage_xTaskRemoveFromEventList_remove_higher_priority_task( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + List_t xEventList = { 0 }; + uint32_t i; + BaseType_t xReturn; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY + 1U; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1U ] ) ); + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i == 0 ) + { + /* Core 0 is running an idle task in order to be requested to yield. */ + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + /* Others are running a normal task. */ + xTaskTCBs[ i ].uxTaskAttributes = 0; + } + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY + 1U; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Expectations. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get portGET_CRITICAL_NESTING_COUNT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get prvYieldCore. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get xYieldPendings. */ + + /* API call. */ + xReturn = xTaskRemoveFromEventList( &xEventList ); + + /* Validations. */ + /* Yield is required for current core due to higher priority. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + /* Task is removed from event list. */ + TEST_ASSERT_EQUAL( NULL, xTaskTCB.xEventListItem.pvContainer ); + /* Task is added to ready list. */ + TEST_ASSERT_EQUAL( &pxReadyTasksLists[ xTaskTCB.uxPriority ], xTaskTCB.xStateListItem.pvContainer ); +} + + +/** + * @brief vTaskRemoveFromUnorderedEventList - Remove a higher priority task from event list. + * + * The task is removed from event list. Verified this task is put back to ready list + * and removed from event list. Current core is requested to yield. The item value + * is set correctly. + * + * Coverage + * @code{c} + * #else + * { + * #if ( configUSE_PREEMPTION == 1 ) + * { + * taskENTER_CRITICAL(); + * { + * prvYieldForTask( pxUnblockedTCB ); + * } + * taskEXIT_CRITICAL(); + * } + * #endif + * } + * #endif + * @endcode + */ +void test_coverage_vTaskRemoveFromUnorderedEventList_remove_higher_priority_task( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY + 1U; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1U ] ) ); + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i == 0 ) + { + /* Core 0 is running an idle task in order to be requested to yield. */ + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + /* Others are running a normal task. */ + xTaskTCBs[ i ].uxTaskAttributes = 0; + } + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY + 1U; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Expectations. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get portGET_CRITICAL_NESTING_COUNT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get prvYieldCore. */ + + /* API call. */ + vTaskRemoveFromUnorderedEventList( &xTaskTCB.xEventListItem, 500 | 0x80000000UL ); + + /* Validations. */ + /* Task is removed from event list. */ + TEST_ASSERT_EQUAL( NULL, xTaskTCB.xEventListItem.pvContainer ); + /* Task is added to ready list. */ + TEST_ASSERT_EQUAL( &pxReadyTasksLists[ xTaskTCB.uxPriority ], xTaskTCB.xStateListItem.pvContainer ); + /* The event list item value is set. */ + TEST_ASSERT_EQUAL( 500 | 0x80000000UL, xTaskTCB.xEventListItem.xItemValue ); + /* The xYieldPendings is set. */ + TEST_ASSERT_EQUAL( pdTRUE, xYieldPendings[ 0 ] ); +} + +/** + * @brief vTaskEnterCritical - task is already in the critical section. + * + * Task is already in the critical section. The critical nesting count will be increased. + * + * Coverage + * @code{c} + * if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + * { + * portGET_TASK_LOCK(); + * portGET_ISR_LOCK(); + * } + * @endcode + * ( portGET_CRITICAL_NESTING_COUNT() == 0U ) is false. + */ +void test_coverage_vTaskEnterCritical_task_in_critical_already( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCB.uxCriticalNesting = 1; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortDisableInterrupts_StopIgnore(); + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortDisableInterrupts_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get both locks. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Increment the critical nesting count. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check first time enter critical section. */ + + /* API call. */ + vTaskEnterCritical(); + + /* Validation. */ + TEST_ASSERT_EQUAL( 2, xTaskTCB.uxCriticalNesting ); +} + +/** + * @brief vTaskEnterCriticalFromISR - ISR is already in critical section. + * + * ISR is already in the critical section. The critical nesting count will be increased. + * + * Coverage + * @code{c} + * if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + * { + * portGET_ISR_LOCK(); + * } + * @endcode + * ( portGET_CRITICAL_NESTING_COUNT() == 0U ) is false. + */ +void test_coverage_vTaskEnterCriticalFromISR_isr_in_critical_already( void ) +{ + TCB_t xTaskTCB = { NULL }; + portBASE_TYPE xSavedInterruptStatus; + + /* Setup the variables and structure. */ + xTaskTCB.uxCriticalNesting = 1; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + ulFakePortSetInterruptMaskFromISR_StopIgnore(); + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + ulFakePortSetInterruptMaskFromISR_ExpectAndReturn( 0x5a5a ); /* The value to be verified. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get ISR locks. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Increment the critical nesting count. */ + + /* API call. */ + xSavedInterruptStatus = vTaskEnterCriticalFromISR(); + + /* Validation. */ + TEST_ASSERT_EQUAL( 2, xTaskTCB.uxCriticalNesting ); + TEST_ASSERT_EQUAL( 0X5a5a, xSavedInterruptStatus ); +} + +/** + * @brief vTaskExitCritical - Task enters the critical section for more than 1 time. + * + * Verify the critical nesting count will be decreased in this API. + * + * Coverage + * @code{c} + * if( pxCurrentTCB->uxCriticalNesting == 0U ) + * { + * portENABLE_INTERRUPTS(); + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( pxCurrentTCB->uxCriticalNesting == 0U ) is false. + */ +void test_coverage_vTaskExitCritical_task_enter_critical_mt_1( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCB.uxCriticalNesting = 2; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* configASSERT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check critical nesting count. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Decrease the critical nesting count. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check exit critical section. */ + + /* API call. */ + vTaskExitCritical(); + + /* Validation. */ + TEST_ASSERT_EQUAL( 1, xTaskTCB.uxCriticalNesting ); +} + +/** + * @brief vTaskExitCritical - Task is not in the critical section. + * + * Cover the situation that task is not in the critical section when vTaskExitCritical + * is called. Critical nesting count won't be updated. + * + * Coverage + * @code{c} + * if( pxCurrentTCB->uxCriticalNesting > 0U ) + * { + * ( pxCurrentTCB->uxCriticalNesting )--; + * ... + * } + * @endcode + * ( pxCurrentTCB->uxCriticalNesting > 0U ) is false. + */ +void test_coverage_vTaskExitCritical_task_not_in_critical( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCB.uxCriticalNesting = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* configASSERT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check critical nesting count. */ + + /* API call. */ + vTaskExitCritical(); + + /* Validation. */ + + /* Critical section count won't be updated. This test shows it's result in the + * coverage report. */ +} + +/** + * @brief vTaskExitCriticalFromISR - ISR enters critical section more than 1 time. + * + * Cover the situation that ISR enters critical section more that 1 time when vTaskExitCriticalFromISR + * is called. Critical nesting count will be decreased. + * + * Coverage + * @code{c} + * if( portGET_CRITICAL_NESTING_COUNT() > 0U ) + * { + * portDECREMENT_CRITICAL_NESTING_COUNT(); + * + * if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + * { + * xYieldCurrentTask = xYieldPendings[ portGET_CORE_ID() ]; + * + * portRELEASE_ISR_LOCK(); + * portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + * + * if( xYieldCurrentTask != pdFALSE ) + * { + * portYIELD(); + * } + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * } + * @endcode + * ( portGET_CRITICAL_NESTING_COUNT() > 0U ) is true. + * ( portGET_CRITICAL_NESTING_COUNT() == 0U ) is false. + */ +void test_coverage_vTaskExitCriticalFromISR_isr_enter_critical_mt_1( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCB.uxCriticalNesting = 2; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* configASSERT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check critical nesting count. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Decrement critical nesting count. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check critical nesting count. */ + + /* API call. */ + /* The mask value has not effect since ISR enters critical section more than 1 time. */ + vTaskExitCriticalFromISR( 0x5a5a ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 1, xTaskTCB.uxCriticalNesting ); +} + +/** + * @brief vTaskExitCriticalFromISR - ISR is not in the critical section. + * + * Cover the situation that ISR is not in the critical section when vTaskExitCriticalFromISR + * is called. Critical nesting count won't be updated. + * + * Coverage + * @code{c} + * if( portGET_CRITICAL_NESTING_COUNT() > 0U ) + * { + * portDECREMENT_CRITICAL_NESTING_COUNT(); + * + * ... + * } + * @endcode + * ( portGET_CRITICAL_NESTING_COUNT() > 0U ) is false. + */ +void test_coverage_vTaskExitCriticalFromISR_isr_not_in_critical( void ) +{ + TCB_t xTaskTCB = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCB.uxCriticalNesting = 0; + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xSchedulerRunning = pdTRUE; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* configASSERT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Check critical nesting count. */ + + /* API call. */ + /* The mask value has not effect since ISR is not in critical section. */ + vTaskExitCriticalFromISR( 0x5a5a ); + + /* Validation. */ + + /* Critical section count won't be changed. This test shows it's result in the + * coverage report. */ +} + +/** + * @brief pvTaskGetThreadLocalStoragePointer - xIndex is zero. + * + * Cover the situation that xIndex is zero and less than configNUM_THREAD_LOCAL_STORAGE_POINTERS when pvTaskGetThreadLocalStoragePointer + * is called. + * + * Coverage + * @code{c} + * if( ( xIndex >= 0 ) && + * ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) + * { + * pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + * pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + * } + * @endcode + * ( ( xIndex >= 0 ) && ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) is true. + */ +void test_coverage_pvTaskGetThreadLocalStoragePointer_xIndex_is_zero( void ) +{ + uint32_t i = 454545; + void * pValue = &i; + void * ret_pValue; + TCB_t tcb; + TaskHandle_t task_handle = &tcb; + + /* Setup */ + /* API Call */ + vTaskSetThreadLocalStoragePointer( task_handle, + 0, + pValue ); + ret_pValue = pvTaskGetThreadLocalStoragePointer( task_handle, 0 ); + /* Validations */ + TEST_ASSERT_EQUAL_PTR( pValue, ret_pValue ); +} + +/** + * @brief pvTaskGetThreadLocalStoragePointer - taskhandle is NULL. + * + * Cover the situation that xIndex is zero and handle is NULL when pvTaskGetThreadLocalStoragePointer + * is called. + * + * Coverage + * @code{c} + * if( ( xIndex >= 0 ) && + * ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) + * { + * pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + * pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + * } + * @endcode + * ( ( xIndex >= 0 ) && ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) is true. + */ +void test_coverage_pvTaskGetThreadLocalStoragePointer_null_handle( void ) +{ + TCB_t xTaskTCB = { NULL }; + uint32_t i = 454545; + void * pValue = &i; + void * ret_pValue; + + /* Setup */ + /* Create a task as current running task on core 0. */ + pxCurrentTCBs[ 0 ] = &xTaskTCB; + + /* API Call */ + vTaskSetThreadLocalStoragePointer( NULL, + 0, + pValue ); + ret_pValue = pvTaskGetThreadLocalStoragePointer( NULL, 0 ); + + /* Validations */ + TEST_ASSERT_EQUAL_PTR( pValue, ret_pValue ); +} + +/** + * @brief pvTaskGetThreadLocalStoragePointer - xIndex is greater than configNUM_THREAD_LOCAL_STORAGE_POINTERS . + * + * Cover the situation that xIndex is greater than configNUM_THREAD_LOCAL_STORAGE_POINTERS when pvTaskGetThreadLocalStoragePointer + * is called. + * + * Coverage + * @code{c} + * if( ( xIndex >= 0 ) && + * ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) + * { + * pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + * pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + * } + * else + * { + * pvReturn = NULL; + * } + * @endcode + * ( ( xIndex >= 0 ) && ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) ) is false. + */ +void test_coverage_pvTaskGetThreadLocalStoragePointer_fail( void ) +{ + void * ret_pValue; + + ret_pValue = pvTaskGetThreadLocalStoragePointer( NULL, + configNUM_THREAD_LOCAL_STORAGE_POINTERS + 2 ); + TEST_ASSERT_NULL( ret_pValue ); +} + +/** + * @brief xTaskGenericNotifyFromISR - Notify a equal or lower priority task. + * + * Notify a equal or lower priority task from ISR. Higher priority task is not woken. + * + * Coverage + * @code{c} + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + * { + * if( pxHigherPriorityTaskWoken != NULL ) + * { + * *pxHigherPriorityTaskWoken = pdTRUE; + * } + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) is false. + */ +void test_coverage_xTaskGenericNotifyFromISR_priority_le( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + UBaseType_t uxIndexToNotify = 0; /* Use index 0 in this test. */ + uint32_t ulPreviousNotificationValue; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xReturn; + BaseType_t xSavedInterruptMask = 0x1234; /* Interrupt mask to be verified. */ + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCBs[ i ].uxTaskAttributes = 0; + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] = 0x5a5a; /* Value to be verified in this test. */ + xTaskTCB.ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortEnterCriticalFromISR_StubWithCallback( NULL ); + vFakePortExitCriticalFromISR_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vFakePortEnterCriticalFromISR_ExpectAndReturn( xSavedInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get portGET_CRITICAL_NESTING_COUNT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get prvYieldCore. */ + vFakePortExitCriticalFromISR_Expect( xSavedInterruptMask ); + + /* API call. */ + xReturn = xTaskGenericNotifyFromISR( &xTaskTCB, + uxIndexToNotify, + 0, /* Value is not used with eNoAction. */ + eNoAction, + &ulPreviousNotificationValue, + &xHigherPriorityTaskWoken ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + TEST_ASSERT_EQUAL( 0x5a5a, ulPreviousNotificationValue ); + TEST_ASSERT_NOT_EQUAL( pdTRUE, xHigherPriorityTaskWoken ); +} + +/** + * @brief xTaskGenericNotifyFromISR - Notify a higher priority task. + * + * Notify a higher priority task from ISR. Higher priority task is woken. + * + * Coverage + * @code{c} + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + * { + * if( pxHigherPriorityTaskWoken != NULL ) + * { + * *pxHigherPriorityTaskWoken = pdTRUE; + * } + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) is true. + * ( pxHigherPriorityTaskWoken != NULL ) is true. + */ +void test_coverage_xTaskGenericNotifyFromISR_priority_gt( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + UBaseType_t uxIndexToNotify = 0; /* Use index 0 in this test. */ + uint32_t ulPreviousNotificationValue; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xReturn; + BaseType_t xSavedInterruptMask = 0x1234; /* Interrupt mask to be verified. */ + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i == 0 ) + { + /* Core 0 is running an idle task in order to be requested to yield. */ + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + /* Others are running a normal task. */ + xTaskTCBs[ i ].uxTaskAttributes = 0; + } + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] = 0x5a5a; /* Value to be verified in this test. */ + xTaskTCB.ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortEnterCriticalFromISR_StubWithCallback( NULL ); + vFakePortExitCriticalFromISR_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vFakePortEnterCriticalFromISR_ExpectAndReturn( xSavedInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortExitCriticalFromISR_Expect( xSavedInterruptMask ); + + /* API call. */ + xReturn = xTaskGenericNotifyFromISR( &xTaskTCB, + uxIndexToNotify, + 0, /* Value is not used with eNoAction. */ + eNoAction, + &ulPreviousNotificationValue, + &xHigherPriorityTaskWoken ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + TEST_ASSERT_EQUAL( 0x5a5a, ulPreviousNotificationValue ); + TEST_ASSERT_EQUAL( pdTRUE, xHigherPriorityTaskWoken ); +} + +/** + * @brief xTaskGenericNotifyFromISR - Notify a higher priority task with NULL param. + * + * Notify a higher priority task from ISR. Higher priority task is woken. Input param + * pxHigherPriorityTaskWoken is NULL. + * + * Coverage + * @code{c} + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + * { + * if( pxHigherPriorityTaskWoken != NULL ) + * { + * *pxHigherPriorityTaskWoken = pdTRUE; + * } + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) is true. + * ( pxHigherPriorityTaskWoken != NULL ) is false. + */ +void test_coverage_xTaskGenericNotifyFromISR_priority_gt_null_param( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + UBaseType_t uxIndexToNotify = 0; /* Use index 0 in this test. */ + uint32_t ulPreviousNotificationValue; + BaseType_t xReturn; + BaseType_t xSavedInterruptMask = 0x1234; /* Interrupt mask to be verified. */ + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i == 0 ) + { + /* Core 0 is running an idle task in order to be requested to yield. */ + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + /* Others are running a normal task. */ + xTaskTCBs[ i ].uxTaskAttributes = 0; + } + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] = 0x5a5a; /* Value to be verified in this test. */ + xTaskTCB.ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortEnterCriticalFromISR_StubWithCallback( NULL ); + vFakePortExitCriticalFromISR_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vFakePortEnterCriticalFromISR_ExpectAndReturn( xSavedInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortExitCriticalFromISR_Expect( xSavedInterruptMask ); + + /* API call. */ + xReturn = xTaskGenericNotifyFromISR( &xTaskTCB, + uxIndexToNotify, + 0, /* Value is not used with eNoAction. */ + eNoAction, + &ulPreviousNotificationValue, + NULL ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + TEST_ASSERT_EQUAL( 0x5a5a, ulPreviousNotificationValue ); + TEST_ASSERT_EQUAL( pdTRUE, xYieldPendings[ 0 ] ); +} + +/** + * @brief vTaskGenericNotifyGiveFromISR - Notify a equal or lower priority task. + * + * Notify a equal or lower priority task from ISR. Higher priority task is not woken. + * + * Coverage + * @code{c} + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + * { + * if( pxHigherPriorityTaskWoken != NULL ) + * { + * *pxHigherPriorityTaskWoken = pdTRUE; + * } + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) is false. + */ +void test_coverage_vTaskGenericNotifyGiveFromISR_priority_le( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + UBaseType_t uxIndexToNotify = 0; /* Use index 0 in this test. */ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xSavedInterruptMask = 0x1234; /* Interrupt mask to be verified. */ + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCBs[ i ].uxTaskAttributes = 0; + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] = 0x5a5a; /* Value to be verified in this test. */ + xTaskTCB.ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortEnterCriticalFromISR_StubWithCallback( NULL ); + vFakePortExitCriticalFromISR_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vFakePortEnterCriticalFromISR_ExpectAndReturn( xSavedInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get portGET_CRITICAL_NESTING_COUNT. */ + vFakePortGetCoreID_ExpectAndReturn( 0 ); /* Get prvYieldCore. */ + vFakePortExitCriticalFromISR_Expect( xSavedInterruptMask ); + + /* API call. */ + vTaskGenericNotifyGiveFromISR( &xTaskTCB, + uxIndexToNotify, + &xHigherPriorityTaskWoken ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0x5a5a + 1U, xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] ); + TEST_ASSERT_NOT_EQUAL( pdTRUE, xHigherPriorityTaskWoken ); +} + +/** + * @brief vTaskGenericNotifyGiveFromISR - Notify a higher priority task. + * + * Notify a higher priority task from ISR. Higher priority task is woken. + * + * Coverage + * @code{c} + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + * { + * if( pxHigherPriorityTaskWoken != NULL ) + * { + * *pxHigherPriorityTaskWoken = pdTRUE; + * } + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) is true. + * ( pxHigherPriorityTaskWoken != NULL ) is true. + */ +void test_coverage_vTaskGenericNotifyGiveFromISR_priority_gt( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + UBaseType_t uxIndexToNotify = 0; /* Use index 0 in this test. */ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xSavedInterruptMask = 0x1234; /* Interrupt mask to be verified. */ + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i == 0 ) + { + /* Core 0 is running an idle task in order to be requested to yield. */ + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + /* Others are running a normal task. */ + xTaskTCBs[ i ].uxTaskAttributes = 0; + } + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] = 0x5a5a; /* Value to be verified in this test. */ + xTaskTCB.ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortEnterCriticalFromISR_StubWithCallback( NULL ); + vFakePortExitCriticalFromISR_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vFakePortEnterCriticalFromISR_ExpectAndReturn( xSavedInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortExitCriticalFromISR_Expect( xSavedInterruptMask ); + + /* API call. */ + vTaskGenericNotifyGiveFromISR( &xTaskTCB, + uxIndexToNotify, + &xHigherPriorityTaskWoken ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0x5a5a + 1U, xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] ); + TEST_ASSERT_EQUAL( pdTRUE, xHigherPriorityTaskWoken ); +} + +/** + * @brief vTaskGenericNotifyGiveFromISR - Notify a higher priority task with NULL param. + * + * Notify a higher priority task from ISR. Higher priority task is woken. Input param + * pxHigherPriorityTaskWoken is NULL. + * + * Coverage + * @code{c} + * #if ( configUSE_PREEMPTION == 1 ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) + * { + * if( pxHigherPriorityTaskWoken != NULL ) + * { + * *pxHigherPriorityTaskWoken = pdTRUE; + * } + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] == pdTRUE ) is true. + * ( pxHigherPriorityTaskWoken != NULL ) is false. + */ +void test_coverage_vTaskGenericNotifyGiveFromISR_priority_gt_null_param( void ) +{ + TCB_t xTaskTCB = { NULL }; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + UBaseType_t uxIndexToNotify = 0; /* Use index 0 in this test. */ + BaseType_t xSavedInterruptMask = 0x1234; /* Interrupt mask to be verified. */ + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + uxSchedulerSuspended = pdFALSE; + uxTopReadyPriority = tskIDLE_PRIORITY; + vListInitialise( &xEventList ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &xSuspendedTaskList ); + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i == 0 ) + { + /* Core 0 is running an idle task in order to be requested to yield. */ + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + /* Others are running a normal task. */ + xTaskTCBs[ i ].uxTaskAttributes = 0; + } + + /* Create idle tasks with equal number of cores. */ + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + } + + /* Create one more task to be removed from event list. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pxContainer = &xSuspendedTaskList; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xSuspendedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pxContainer = &xEventList; + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + xTaskTCB.xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] = 0x5a5a; /* Value to be verified in this test. */ + xTaskTCB.ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Clear callback in commonSetUp. */ + vFakePortGetCoreID_StubWithCallback( NULL ); + vFakePortEnterCriticalFromISR_StubWithCallback( NULL ); + vFakePortExitCriticalFromISR_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Expect(); + vFakePortEnterCriticalFromISR_ExpectAndReturn( xSavedInterruptMask ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortExitCriticalFromISR_Expect( xSavedInterruptMask ); + + /* API call. */ + vTaskGenericNotifyGiveFromISR( &xTaskTCB, + uxIndexToNotify, + NULL ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0x5a5a + 1U, xTaskTCB.ulNotifiedValue[ uxIndexToNotify ] ); + TEST_ASSERT_EQUAL( pdTRUE, xYieldPendings[ 0 ] ); +} + +/** + * @brief prvCheckTasksWaitingTermination - multiple idle tasks clean the deleted task. + * + * This test case cover the branch that the waiting termination tasks are already been + * deleted by other idle tasks. + * + * Coverage + * @code{c} + * taskENTER_CRITICAL(); + * { + * ... + * if( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + * { + * pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + * @endcode + * ( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) is false. + */ +void test_coverage_prvCheckTasksWaitingTermination_multiple_idle_tasks( void ) +{ + /* Setup the variables and structure. */ + uxDeletedTasksWaitingCleanUp = 1; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_StubWithCallback( prvPortEnterCriticalSectionCb ); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + prvCheckTasksWaitingTermination(); + + /* Validation. */ + + /* No task is waiting to be cleaned up. Nothing will be updated in this API. This + * test case shows its result in the coverage report. */ +} + +/** + * @brief prvCheckTasksWaitingTermination - delete not running task. + * + * A not running task is deleted. The number of tasks and number of tasks waiting to + * be deleted are verified in this test case. + * + * Coverage + * @code{c} + * if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) + * { + * ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + * --uxCurrentNumberOfTasks; + * --uxDeletedTasksWaitingCleanUp; + * } + * else + * { + * ... + * taskEXIT_CRITICAL(); + * break; + * } + * @endcode + * ( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) is true. + */ +void test_coverage_prvCheckTasksWaitingTermination_delete_not_running_task( void ) +{ + TCB_t * pxTaskTCB = NULL; + + /* Setup the variables and structure. */ + uxDeletedTasksWaitingCleanUp = 1; + uxCurrentNumberOfTasks = 1; + + pxTaskTCB = pvPortMalloc( sizeof( TCB_t ) ); + pxTaskTCB->pxStack = pvPortMalloc( configMINIMAL_STACK_SIZE ); + pxTaskTCB->xTaskRunState = taskTASK_NOT_RUNNING; + pxTaskTCB->xStateListItem.pvOwner = pxTaskTCB; + pxTaskTCB->xStateListItem.pxContainer = &xTasksWaitingTermination; + listINSERT_END( &xTasksWaitingTermination, &pxTaskTCB->xStateListItem ); + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + prvCheckTasksWaitingTermination(); + + /* Validation. */ + TEST_ASSERT_EQUAL( uxCurrentNumberOfTasks, 0 ); + TEST_ASSERT_EQUAL( uxDeletedTasksWaitingCleanUp, 0 ); + /* Verify memory allocate count in tearDown function. */ +} + +/** + * @brief prvCheckTasksWaitingTermination - delete running task. + * + * A task to be deleted is still running. Nothing will be updated in this test case. + * The test shows it's result in the coverage report. + * + * Coverage + * @code{c} + * if( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) + * { + * ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + * --uxCurrentNumberOfTasks; + * --uxDeletedTasksWaitingCleanUp; + * } + * else + * { + * ... + * taskEXIT_CRITICAL(); + * break; + * } + * @endcode + * ( pxTCB->xTaskRunState == taskTASK_NOT_RUNNING ) is false. + */ +void test_coverage_prvCheckTasksWaitingTermination_delete_running_task( void ) +{ + TCB_t * pxTaskTCB = NULL; + + /* Setup the variables and structure. */ + uxDeletedTasksWaitingCleanUp = 1; + uxCurrentNumberOfTasks = 1; + + pxTaskTCB = pvPortMalloc( sizeof( TCB_t ) ); + pxTaskTCB->pxStack = pvPortMalloc( configMINIMAL_STACK_SIZE ); + pxTaskTCB->xTaskRunState = 0; + pxTaskTCB->xStateListItem.pvOwner = pxTaskTCB; + pxTaskTCB->xStateListItem.pxContainer = &xTasksWaitingTermination; + listINSERT_END( &xTasksWaitingTermination, &pxTaskTCB->xStateListItem ); + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + prvCheckTasksWaitingTermination(); + + /* Validation. */ + + /* If the task is not of taskTASK_NOT_RUNNING state, nothing will be updated. + * This test shows it's result in coverage report. Verify that the number of + * deleted task is not changed. */ + TEST_ASSERT_EQUAL( uxDeletedTasksWaitingCleanUp, 1 ); + TEST_ASSERT_EQUAL( uxCurrentNumberOfTasks, 1 ); + + /* Free the resource allocated in this test. Since running task can't be deleted, + * there won't have double free assertion. */ + vPortFree( pxTaskTCB ); + vPortFree( pxTaskTCB->pxStack ); + /* Verify memory allocate count in tearDown function. */ +} + +/** + * @brief prvDeleteTCB - clean up the memory utilised by a TCB and its stack. + * + * Coverage + * @code{c} + * else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + * { + * ... + * vPortFree( pxTCB ) + * @endcode + * + * Cover the case where the stack allocation is static. + */ +void test_coverage_prvDeleteTCB_static_stack_only( void ) +{ + TCB_t * pxTaskTCB; + + pxTaskTCB = pvPortMalloc( sizeof( TCB_t ) ); + + pxTaskTCB->uxPriority = 1; + pxTaskTCB->xTaskRunState = 0; + pxTaskTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; + /* Default core is 0. This can be updated with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = pxTaskTCB; + + prvDeleteTCB( pxTaskTCB ); + + /* Validate the memory allocate count to ensure that allocated stack is freed + * in tearDown function. */ +} + +/** @brief xTaskResumeFromISR - resume task from within ISR context + * + * Coverage + * @code{c} + * if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) + * { + * traceTASK_RESUME_FROM_ISR( pxTCB ); + * ... + * if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + * { + * ... + * prvAddTaskToReadyList( pxTCB ); + * @endcode + * + * Cover the case where the scheduler is not suspended, and the + * task being resumed is suspended. + * + */ +void test_coverage_xTaskResumeFromISR_task_suspended_uxpriority_greater( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xAlreadyYielded; + UBaseType_t uxCore; + List_t xList; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 2; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &xSuspendedTaskList, &xTaskTCBs[ 1 ].xStateListItem ); + vListInitialise( &xList ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + + /* API call. */ + xAlreadyYielded = xTaskResumeFromISR( &xTaskTCBs[ 1 ] ); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdFALSE, xAlreadyYielded ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** @brief xTaskResumeFromISR - resume task from within ISR context + * + * Coverage + * @code{c} + * if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) + * { + * traceTASK_RESUME_FROM_ISR( pxTCB ); + * ... + * if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + * { + * ... + * prvAddTaskToReadyList( pxTCB ); + * @endcode + * + * Cover the case where the scheduler is not suspended, and the + * task being resumed is suspended. + * + */ +void test_coverage_xTaskResumeFromISR_task_suspended_uxpriority_lesser( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xAlreadyYielded; + UBaseType_t uxCore; + List_t xList; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 0; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &xSuspendedTaskList, &xTaskTCBs[ 1 ].xStateListItem ); + vListInitialise( &xList ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* Expectations. */ + vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + + /* API call. */ + xAlreadyYielded = xTaskResumeFromISR( &xTaskTCBs[ 1 ] ); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdFALSE, xAlreadyYielded ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + + + +/** @brief xTaskResumeAll - resume all suspended tasks + * + * Coverage + * @code{c} + * while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) + * { + * ... + * @endcode + * + * Cover the case where the scheduler is running and suspended, + * there are tasks and at least one is in the pending ready list. + * + */ +void test_coverage_xTaskResumeAll_task_in_pending_ready_list( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xAlreadyYielded; + List_t xList; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the pending ready list. */ + xTaskTCBs[ 1 ].uxPriority = 2; /* The priority is not higher than current running task. */ + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &xPendingReadyList, &xTaskTCBs[ 1 ].xStateListItem ); + vListInitialise( &xList ); + vListInitialiseItem( &( xTaskTCBs[ 1 ].xEventListItem ) ); + listSET_LIST_ITEM_VALUE( &( xTaskTCBs[ 1 ].xEventListItem ), + taskEVENT_LIST_ITEM_VALUE_IN_USE ); + listINSERT_END( &xList, &( xTaskTCBs[ 1 ].xEventListItem ) ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + uxTopReadyPriority = 1; + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdTRUE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* Clear setup in commonSetUp. */ + vFakePortReleaseTaskLock_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortReleaseTaskLock_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + xAlreadyYielded = xTaskResumeAll(); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdFALSE, xAlreadyYielded ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** @brief xTaskResumeAll - resume all suspended tasks + * + * Coverage + * @code{c} + * while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) + * { + * ... + * @endcode + * + * Cover the case where the scheduler is running and suspended, + * there are tasks and at least one is in the pending ready list + * with a priority less than uxTopReadyPriority. + * + */ +void test_coverage_xTaskResumeAll_task_in_pending_ready_list_uxpriority_lesser( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xAlreadyYielded; + List_t xList; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the pending ready list. */ + xTaskTCBs[ 1 ].uxPriority = 0; /* The priority is not higher than current running task. */ + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &xPendingReadyList, &xTaskTCBs[ 1 ].xStateListItem ); + vListInitialise( &xList ); + vListInitialiseItem( &( xTaskTCBs[ 1 ].xEventListItem ) ); + listSET_LIST_ITEM_VALUE( &( xTaskTCBs[ 1 ].xEventListItem ), + taskEVENT_LIST_ITEM_VALUE_IN_USE ); + listINSERT_END( &xList, &( xTaskTCBs[ 1 ].xEventListItem ) ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + uxTopReadyPriority = 1; + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdTRUE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* Clear setup in commonSetUp. */ + vFakePortReleaseTaskLock_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expectations. */ + vFakePortReleaseTaskLock_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + xAlreadyYielded = xTaskResumeAll(); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdFALSE, xAlreadyYielded ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief vTaskResume - resume a suspended task. + * + * Coverage + * @code{c} + * if( pxTCB != NULL ) + * { + * ... + * } + * @endcode + * ( pxTCB != NULL ) is false. + */ +void test_coverage_vTaskResume_null_task( void ) +{ + vTaskResume( NULL ); + + /* In this case no state is changed and so no assertion can be made to + * validate the operation. */ +} + +/** + * @brief xTaskGenericNotify - function to notify a task. + * + * Coverage + * @code{c} + * if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + * { + * ... + * @endcode + * + * Cover the case where the ucOriginalNotifyState is taskWAITING_NOTIFICATION. + */ +void test_coverage_xTaskGenericNotify_with_eAction_equalto_eNoAction_taskWAITING_NOTIFICATION_uxpriority_lesser( void ) +{ + TCB_t xTaskTCBs[ 2U ] = { NULL }; + UBaseType_t xidx = 0; + uint32_t prevValue; + BaseType_t xReturn; + UBaseType_t uxCoreID; + + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + listINSERT_END( &xPendingReadyList, &xTaskTCBs[ 0 ].xStateListItem ); + + /* Default core ID is 0. The can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + xTaskTCBs[ 1 ].uxPriority = 1; + xTaskTCBs[ 1 ].xTaskRunState = -1; + + for( uxCoreID = 0; uxCoreID < configNUMBER_OF_CORES; uxCoreID++ ) + { + if( pxCurrentTCBs[ uxCoreID ] == NULL ) + { + pxCurrentTCBs[ uxCoreID ] = &xTaskTCBs[ 1 ]; + } + } + + uxTopReadyPriority = 2; + uxSchedulerSuspended = pdTRUE; + xTaskTCBs[ 0 ].ucNotifyState[ xidx ] = taskWAITING_NOTIFICATION; + xTaskTCBs[ 0 ].ulNotifiedValue[ xidx ] = 0xa5a5; /* Value to be verified later. */ + + xReturn = xTaskGenericNotify( &xTaskTCBs[ 0 ], xidx, 0x0, eNoAction, &prevValue ); + + TEST_ASSERT_EQUAL_UINT32( 0xa5a5, prevValue ); + TEST_ASSERT( xReturn == pdPASS ); +} + +/** + * @brief xTaskGenericNotify - function to notify a task. + * + * Coverage + * @code{c} + * if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + * { + * ... + * @endcode + * + * Cover the case where the ucOriginalNotifyState is taskWAITING_NOTIFICATION. + */ +void test_coverage_xTaskGenericNotify_with_eAction_equalto_eNoAction_taskWAITING_NOTIFICATION_uxpriority_greater( void ) +{ + TCB_t xTaskTCBs[ 2U ] = { NULL }; + UBaseType_t xidx = 0; + uint32_t prevValue; + BaseType_t xReturn; + UBaseType_t uxCoreID; + + xTaskTCBs[ 0 ].uxPriority = 2; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + listINSERT_END( &xPendingReadyList, &xTaskTCBs[ 0 ].xStateListItem ); + + /* Default core ID is 0. The can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + xTaskTCBs[ 1 ].uxPriority = 1; + xTaskTCBs[ 1 ].xTaskRunState = -1; + + for( uxCoreID = 0; uxCoreID < configNUMBER_OF_CORES; uxCoreID++ ) + { + if( pxCurrentTCBs[ uxCoreID ] == NULL ) + { + pxCurrentTCBs[ uxCoreID ] = &xTaskTCBs[ 1 ]; + } + } + + uxTopReadyPriority = 1; + uxSchedulerSuspended = pdTRUE; + xTaskTCBs[ 0 ].ucNotifyState[ xidx ] = taskWAITING_NOTIFICATION; + xTaskTCBs[ 0 ].ulNotifiedValue[ xidx ] = 0xa5a5; /* Value to be verified later. */ + + xReturn = xTaskGenericNotify( &xTaskTCBs[ 0 ], xidx, 0x0, eNoAction, &prevValue ); + + TEST_ASSERT_EQUAL_UINT32( 0xa5a5, prevValue ); + TEST_ASSERT( xReturn == pdPASS ); +} + + +/** + * @brief vTaskGetInfo - populate TaskStatus_t and eTaskState + * + * Coverage + * @code{c} + * pxTCB = prvGetTCBFromHandle( xTask ); + * ... + * @endcode + * + * Cover the case where xTask is NULL, and the current task is implicitly + * referenced and returned by prvGetTCBFromHandle(...); + */ +void test_coverage_vTaskGetInfo_implicit_task( void ) +{ + TCB_t xTaskTCBs[ 1U ] = { NULL }; + TaskStatus_t pxTaskStatus; + BaseType_t xFreeStackSpace = pdFALSE; + eTaskState taskState = eReady; + + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].uxBasePriority = 0; + xTaskTCBs[ 0 ].xTaskRunState = 0; + xTaskTCBs[ 0 ].uxCoreAffinityMask = ( ( 1U << ( configNUMBER_OF_CORES ) ) - 1U ); + xTaskTCBs[ 0 ].uxTCBNumber = 1; + xTaskTCBs[ 0 ].pxStack = ( StackType_t * ) 0x1234; /* The value to be verified later. */ + + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + uxTopReadyPriority = 1; + uxSchedulerSuspended = pdTRUE; + + vTaskGetInfo( NULL, &pxTaskStatus, xFreeStackSpace, taskState ); + + TEST_ASSERT_EQUAL( &xTaskTCBs[ 0 ], pxTaskStatus.xHandle ); + TEST_ASSERT_EQUAL( xTaskTCBs[ 0 ].pcTaskName, pxTaskStatus.pcTaskName ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 1, pxTaskStatus.xTaskNumber ); + TEST_ASSERT_EQUAL( eRunning, pxTaskStatus.eCurrentState ); + TEST_ASSERT_EQUAL( ( BaseType_t ) 1, pxTaskStatus.uxCurrentPriority ); + TEST_ASSERT_EQUAL( ( BaseType_t ) 0, pxTaskStatus.uxBasePriority ); + TEST_ASSERT_EQUAL( ( StackType_t * ) 0x1234, pxTaskStatus.pxStackBase ); + TEST_ASSERT_EQUAL( ( ( 1U << ( configNUMBER_OF_CORES ) ) - 1U ), pxTaskStatus.uxCoreAffinityMask ); + TEST_ASSERT_EQUAL( 0, pxTaskStatus.usStackHighWaterMark ); +} + +/** + * @brief vTaskGetInfo - populate TaskStatus_t and eTaskState + * + * Coverage + * @code{c} + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * pxTaskStatus->eCurrentState = eRunning; + * } + * ... + * @endcode + * + * Cover the case in the taskTASK_IS_RUNNING() macro where the xTaskRunState + * is out of bounds. + */ +void test_coverage_vTaskGetInfo_oob_xTaskRunState( void ) +{ + TCB_t xTaskTCBs[ 1U ] = { NULL }; + TaskStatus_t pxTaskStatus; + BaseType_t xFreeStackSpace = pdFALSE; + eTaskState taskState = eSuspended; + + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = configNUMBER_OF_CORES; + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + uxTopReadyPriority = 1; + uxSchedulerSuspended = pdTRUE; + + vTaskGetInfo( &xTaskTCBs[ 0 ], &pxTaskStatus, xFreeStackSpace, taskState ); + + TEST_ASSERT_EQUAL( ( UBaseType_t ) 0, pxTaskStatus.xTaskNumber ); + TEST_ASSERT_EQUAL( eSuspended, pxTaskStatus.eCurrentState ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 1, pxTaskStatus.uxCurrentPriority ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 0, pxTaskStatus.uxBasePriority ); + TEST_ASSERT_EQUAL( 0, pxTaskStatus.usStackHighWaterMark ); +} + +/** + * @brief vTaskGetInfo - populate TaskStatus_t and eTaskState + * + * Coverage + * @code{c} + * if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + * { + * pxTaskStatus->eCurrentState = eBlocked; + * } + * ... + * @endcode + * + * Cover the case where the task is blocked. + */ +void test_coverage_vTaskGetInfo_blocked_task( void ) +{ + TCB_t xTaskTCBs[ 1U ] = { NULL }; + TaskStatus_t pxTaskStatus; + BaseType_t xFreeStackSpace = pdFALSE; + eTaskState taskState = eSuspended; + + /* Setup the variables and structure. */ + xTaskTCBs[ 0 ].uxPriority = 2; + xTaskTCBs[ 0 ].uxBasePriority = 0; + xTaskTCBs[ 0 ].xTaskRunState = -1; + xTaskTCBs[ 0 ].uxTCBNumber = 1; + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + listINSERT_END( &xSuspendedTaskList, &xTaskTCBs[ 0 ].xStateListItem ); + + uxTopReadyPriority = 2; + uxSchedulerSuspended = pdTRUE; + + xTaskTCBs[ 0 ].xEventListItem.pxContainer = ( struct xLIST * ) 1; + + vTaskGetInfo( &xTaskTCBs[ 0 ], &pxTaskStatus, xFreeStackSpace, taskState ); + + TEST_ASSERT_EQUAL( ( UBaseType_t ) 1, pxTaskStatus.xTaskNumber ); + TEST_ASSERT_EQUAL( eBlocked, pxTaskStatus.eCurrentState ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 2, pxTaskStatus.uxCurrentPriority ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 0, pxTaskStatus.uxBasePriority ); + TEST_ASSERT_EQUAL( 0, pxTaskStatus.usStackHighWaterMark ); +} + +/** + * @brief vTaskGetInfo - populate TaskStatus_t and eTaskState + * + * Coverage + * @code{c} + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * pxTaskStatus->eCurrentState = eRunning; + * } + * ... + * @endcode + * + * Cover the case where xFreeStackSpace is pdTRUE, avoiding the free + * stack space query. + */ +void test_coverage_vTaskGetInfo_get_free_stack_space( void ) +{ + TCB_t xTaskTCBs[ 1U ] = { NULL }; + TaskStatus_t pxTaskStatus; + BaseType_t xFreeStackSpace = pdTRUE; + eTaskState taskState = eReady; + + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].uxBasePriority = 0; + xTaskTCBs[ 0 ].xTaskRunState = 0; + prvInitialiseTestStack( &xTaskTCBs[ 0 ], configMINIMAL_STACK_SIZE ); + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + uxTopReadyPriority = 1; + uxSchedulerSuspended = pdTRUE; + + vTaskGetInfo( &xTaskTCBs[ 0 ], &pxTaskStatus, xFreeStackSpace, taskState ); + + vPortFreeStack( xTaskTCBs[ 0 ].pxStack ); + + TEST_ASSERT_EQUAL( ( UBaseType_t ) 0, pxTaskStatus.xTaskNumber ); + TEST_ASSERT_EQUAL( eRunning, pxTaskStatus.eCurrentState ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 1, pxTaskStatus.uxCurrentPriority ); + TEST_ASSERT_EQUAL( ( UBaseType_t ) 0, pxTaskStatus.uxBasePriority ); + /* The stack is not used in this test. The high water mark is the index of the stack. */ + TEST_ASSERT_EQUAL( ( configMINIMAL_STACK_SIZE - 1 ), pxTaskStatus.usStackHighWaterMark ); +} + +/** + * @brief xTaskPriorityInherit - inherit the priority of the mutex holder + * + * Coverage + * @code{c} + * if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE ) + * { + * ... + * prvAddTaskToReadyList( pxMutexHolderTCB ); + * @endcode + * + * Cover the case where a non-NULL task is specified, and this task has a + * priority lesser than the current task. Furthermore than the specified + * task is in the ready task list. Finally that the uxpriority of the + * specified task is less than uxtopreadypriority. + * + */ +void test_coverage_xTaskPriorityInherit_task_uxpriority_lesser( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xReturn; + UBaseType_t uxCore; + List_t xList; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 0; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ], &xTaskTCBs[ 1 ].xStateListItem ); + vListInitialise( &xList ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* API call. */ + xReturn = xTaskPriorityInherit( &xTaskTCBs[ 1 ] ); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief xTaskPriorityInherit - inherit the priority of the mutex holder + * + * Coverage + * @code{c} + * if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE ) + * { + * ... + * prvAddTaskToReadyList( pxMutexHolderTCB ); + * @endcode + * + * Cover the case where a non-NULL task is specified, and this task has a + * priority lesser than the current task. Furthermore than the specified + * task is in the ready task list. Finally that the uxpriority of the + * specified task is greater than uxtopreadypriority. + * + */ +void test_coverage_xTaskPriorityInherit_task_uxpriority_greater( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xReturn; + UBaseType_t uxCore; + List_t xList; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 3; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 2; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ], &xTaskTCBs[ 1 ].xStateListItem ); + vListInitialise( &xList ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* API call. */ + xReturn = xTaskPriorityInherit( &xTaskTCBs[ 1 ] ); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief xTaskPriorityInherit - task is already running. + * A running task inherit a high priority task. Verify that the priority is raised. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) + * { + * prvYieldForTask( pxMutexHolderTCB ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) is false. + */ +void test_coverage_xTaskPriorityInherit_task_is_running( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 1, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 1 ]; + listINSERT_END( &pxReadyTasksLists[ 1 ], &xTaskTCBs[ i ].xStateListItem ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + + /* API call. */ + xTaskPriorityInherit( &xTaskTCBs[ ( configNUMBER_OF_CORES - 1 ) ] ); + + /* Validation. */ + /* Verify the priority of the task is raised. */ + TEST_ASSERT_EQUAL( 2, xTaskTCBs[ ( configNUMBER_OF_CORES - 1 ) ].uxPriority ); +} + +/** + * @brief xTaskPriorityInherit - task is of invalid running state. + * A running task inherit a high priority task. Verify that the priority is raised. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) + * { + * prvYieldForTask( pxMutexHolderTCB ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) is true. + */ +void test_coverage_xTaskPriorityInherit_task_invalid_state( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 1, + configNUMBER_OF_CORES, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 1 ]; + listINSERT_END( &pxReadyTasksLists[ 1 ], &xTaskTCBs[ i ].xStateListItem ); + + /* API call. */ + xTaskPriorityInherit( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( 2, xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority ); +} + +/** + * @brief xTaskPriorityDisinherit - restore priority after inheriting the priority of the mutex holder + * + * Coverage + * @code{c} + * if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + * { + * ... + * prvAddTaskToReadyList( pxMutexHolderTCB ); + * @endcode + * + * Cover the case where a non-NULL task is specified, and this task has a + * priority different than its base priority. Finally the uxPriority + * is lesser than the uxTopReadyPriority. + * + */ +void test_coverage_xTaskPriorityDisinherit_task_uxpriority_lesser( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xReturn; + UBaseType_t uxCore; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 2; + xTaskTCBs[ 1 ].uxBasePriority = 1; + xTaskTCBs[ 1 ].uxMutexesHeld++; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ], &xTaskTCBs[ 1 ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 3; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* API call. */ + xReturn = xTaskPriorityDisinherit( &xTaskTCBs[ 1 ] ); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief xTaskPriorityDisinherit - restore priority after inheriting the priority of the mutex holder + * + * Coverage + * @code{c} + * if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + * { + * ... + * prvAddTaskToReadyList( pxMutexHolderTCB ); + * @endcode + * + * Cover the case where a non-NULL task is specified, and this task has a + * priority different than its base priority. Finally the uxPriority + * is lesser than the uxTopReadyPriority. + * + */ +void test_coverage_xTaskPriorityDisinherit_task_uxpriority_greater( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + BaseType_t xReturn; + UBaseType_t uxCore; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 3; + xTaskTCBs[ 1 ].uxBasePriority = 2; + xTaskTCBs[ 1 ].uxMutexesHeld++; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ], &xTaskTCBs[ 1 ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* API call. */ + xReturn = xTaskPriorityDisinherit( &xTaskTCBs[ 1 ] ); + + /* Validation. */ + /* The task priority is no higher than current running task. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief xTaskPriorityDisinherit - task is of invalid running state. + * The task disinherits a high priority task. Verify that the priority of the disinherited + * task is dropped to base priority. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * prvYieldCore( pxTCB->xTaskRunState ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + */ +void test_coverage_xTaskPriorityDisinherit_task_invalid_state( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + configNUMBER_OF_CORES, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + xTaskTCBs[ i ].uxMutexesHeld = 1; + xTaskTCBs[ i ].uxBasePriority = 1; + + /* API call. */ + xTaskPriorityDisinherit( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* The priority of the task is dropped to base priority. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ i ].uxBasePriority, xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority ); +} + +/** + * @brief xTaskPriorityDisinheritAfterTimeout - restore priority after inheriting the priority of the mutex holder + * + * Coverage + * @code{c} + * if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + * { + * ... + * prvAddTaskToReadyList( pxMutexHolderTCB ); + * @endcode + * + * Cover the case where a non-NULL task is specified, and this task has a + * priority different than its base priority. Finally the uxPriority + * is lesser than the uxTopReadyPriority. + * + */ +void test_coverage_xTaskPriorityDisinheritAfterTimeout_task_uxpriority_lesser( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + UBaseType_t uxCore; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 2; + xTaskTCBs[ 1 ].uxBasePriority = 1; + xTaskTCBs[ 1 ].uxMutexesHeld++; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ], &xTaskTCBs[ 1 ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 3; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* API call. */ + vTaskPriorityDisinheritAfterTimeout( &xTaskTCBs[ 1 ], 1 ); + + /* Validation. */ + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief xTaskPriorityDisinheritAfterTimeout - restore priority after inheriting the priority of the mutex holder + * + * Coverage + * @code{c} + * if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + * { + * ... + * prvAddTaskToReadyList( pxMutexHolderTCB ); + * @endcode + * + * Cover the case where a non-NULL task is specified, and this task has a + * priority different than its base priority. Finally the uxPriority + * is lesser than the uxTopReadyPriority. + * + */ +void test_coverage_xTaskPriorityDisinheritAfterTimeout_task_uxpriority_greater( void ) +{ + TCB_t xTaskTCBs[ 2 ] = { NULL }; + UBaseType_t uxCore; + + /* Create a task as current running task on core 0. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xTaskTCBs[ 0 ].xTaskRunState = 0; + vListInitialiseItem( &( xTaskTCBs[ 0 ].xStateListItem ) ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 0 ].uxPriority ], &xTaskTCBs[ 0 ].xStateListItem ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 0 ].xStateListItem ), &xTaskTCBs[ 0 ] ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + /* Create a task in the suspended list. */ + xTaskTCBs[ 1 ].uxPriority = 3; + xTaskTCBs[ 1 ].uxBasePriority = 2; + xTaskTCBs[ 1 ].uxMutexesHeld++; + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_NOT_RUNNING; + vListInitialiseItem( &( xTaskTCBs[ 1 ].xStateListItem ) ); + listSET_LIST_ITEM_OWNER( &( xTaskTCBs[ 1 ].xStateListItem ), &xTaskTCBs[ 1 ] ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ], &xTaskTCBs[ 1 ].xStateListItem ); + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; + + uxTopReadyPriority = 1; + + /* Default value for portGET_CORE_ID is 0. This can be changed with vSetCurrentCore. */ + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + + for( uxCore = 0U; uxCore < configNUMBER_OF_CORES; uxCore++ ) + { + if( pxCurrentTCBs[ uxCore ] == NULL ) + { + pxCurrentTCBs[ uxCore ] = &xTaskTCBs[ 0 ]; + } + } + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdFALSE; + xPendedTicks = 0; /* No pending tick in this test. */ + + /* API call. */ + vTaskPriorityDisinheritAfterTimeout( &xTaskTCBs[ 1 ], 2 ); + + /* Validation. */ + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xEventListItem.pvContainer, NULL ); + /* The task in pending ready list should be added back to ready list. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); +} + +/** + * @brief vTaskPriorityDisinheritAfterTimeout - task is of invalid running state. + * The task disinherit a high priority task due to high priority task timeout. Verify + * that the priority of the disinherited task is dropped to uxHighestPriorityWaitingTask. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * prvYieldCore( pxTCB->xTaskRunState ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + */ +void test_coverage_vTaskPriorityDisinheritAfterTimeout_task_invalid_state( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + UBaseType_t uxHighestPriorityWaitingTask = 2; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 3, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 3 ]; + listINSERT_END( &pxReadyTasksLists[ 3 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 1, + configNUMBER_OF_CORES, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 1 ]; + listINSERT_END( &pxReadyTasksLists[ 1 ], &xTaskTCBs[ i ].xStateListItem ); + xTaskTCBs[ i ].uxMutexesHeld = 1; + xTaskTCBs[ i ].uxBasePriority = 1; + + /* API call. */ + vTaskPriorityDisinheritAfterTimeout( &xTaskTCBs[ configNUMBER_OF_CORES ], uxHighestPriorityWaitingTask ); + + /* Validation. */ + /* The priority of the task is dropped to uxHighestPriorityWaitingTask. */ + TEST_ASSERT_EQUAL( uxHighestPriorityWaitingTask, xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority ); +} + +/** + * @brief uxTaskGetSystemState - array size is less than current task number. + * + * Verify that 0 task is returned. + * + * Coverage + * @code{c} + * if( uxArraySize >= uxCurrentNumberOfTasks ) + * { + * ... + * } + * @endcode + * ( uxArraySize >= uxCurrentNumberOfTasks ) is false. + */ +void test_coverage_uxTaskGetSystemState_array_size_lt_current_num_tasks( void ) +{ + TaskStatus_t pxTaskStatusArray[ 1 ]; + UBaseType_t uxTask; + + /* Setup variables. */ + uxCurrentNumberOfTasks = 2; + xSchedulerRunning = pdFALSE; + + /* API call. */ + uxTask = uxTaskGetSystemState( pxTaskStatusArray, 1, NULL ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 0, uxTask ); +} + +/** + * @brief uxTaskGetSystemState - pulTotalRunTime is not null. + * + * Cover pulTotalRunTime is null. Task status returned is also verified in this test. + * + * Coverage + * @code{c} + * if( pulTotalRunTime != NULL ) + * { + * *pulTotalRunTime = 0; + * } + * @endcode + * ( pulTotalRunTime != NULL ) is true. + */ +void test_coverage_uxTaskGetSystemState_valid_run_time_param( void ) +{ + TaskStatus_t pxTaskStatusArray[ 1 ]; + TCB_t xTaskTCB = { NULL }; + UBaseType_t uxTask; + int xTaskNameCompareResult; + configRUN_TIME_COUNTER_TYPE ulTotalRunTime; + + /* Setup variables. */ + UnityMalloc_StartTest(); + /* Create a task as current running task on core 0. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xTaskRunState = 0; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + strncpy( xTaskTCB.pcTaskName, "Test", configMAX_TASK_NAME_LEN ); + xTaskTCB.uxCoreAffinityMask = ( ( 1U << ( configNUMBER_OF_CORES ) ) - 1U ); + pxCurrentTCBs[ 0 ] = &xTaskTCB; + prvInitialiseTestStack( &xTaskTCB, configMINIMAL_STACK_SIZE ); + listINSERT_END( &pxReadyTasksLists[ xTaskTCB.uxPriority ], &xTaskTCB.xStateListItem ); + uxCurrentNumberOfTasks = 1; + xSchedulerRunning = pdFALSE; + + /* API call. */ + uxTask = uxTaskGetSystemState( pxTaskStatusArray, 1, &ulTotalRunTime ); + + /* Validation. */ + TEST_ASSERT_EQUAL( 1, uxTask ); + TEST_ASSERT_EQUAL( 0, ulTotalRunTime ); + TEST_ASSERT_EQUAL( &xTaskTCB, pxTaskStatusArray[ 0 ].xHandle ); + TEST_ASSERT_EQUAL( eRunning, pxTaskStatusArray[ 0 ].eCurrentState ); + TEST_ASSERT_EQUAL( tskIDLE_PRIORITY, pxTaskStatusArray[ 0 ].uxCurrentPriority ); + TEST_ASSERT_EQUAL( xTaskTCB.pxStack, pxTaskStatusArray[ 0 ].pxStackBase ); + TEST_ASSERT_EQUAL( ( ( 1U << ( configNUMBER_OF_CORES ) ) - 1U ), pxTaskStatusArray[ 0 ].uxCoreAffinityMask ); + xTaskNameCompareResult = strncmp( "Test", pxTaskStatusArray[ 0 ].pcTaskName, configMAX_TASK_NAME_LEN ); + TEST_ASSERT_EQUAL( 0, xTaskNameCompareResult ); + + /* Verify the malloc count. */ + vPortFreeStack( xTaskTCB.pxStack ); + UnityMalloc_EndTest(); +} + +/** + * @brief prvSearchForNameWithinSingleList - search empty list + * + * Verify NULL pointer should be returned when list is empty. + * + * Coverage + * @code{c} + * if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + * { + * ... + * } + * @endcode + * ( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) is false. + */ +void test_coverage_prvSearchForNameWithinSingleList_empty_list( void ) +{ + List_t xList; + TCB_t xTaskTCB; + TCB_t * pReturnedTCB; + + /* Setup variables. */ + memset( &xList, 0, sizeof( List_t ) ); + memset( &xTaskTCB, 0, sizeof( TCB_t ) ); + + vListInitialise( &xList ); + + /* API call. */ + pReturnedTCB = prvSearchForNameWithinSingleList( &xList, "TASK_NOT_EXIST" ); + + /* Validation. */ + TEST_ASSERT_EQUAL( NULL, pReturnedTCB ); +} + +/** + * @brief prvSearchForNameWithinSingleList - task found in the list + * + * Verify that task should be found in the list. + * + * Coverage + * @code{c} + * if( pxReturn != NULL ) + * { + * break; + * } + * @endcode + * ( pxReturn != NULL ) is true. + */ +void test_coverage_prvSearchForNameWithinSingleList_task_found( void ) +{ + List_t xList; + TCB_t xTaskTCB; + TCB_t * pReturnedTCB; + + /* Setup variables. */ + memset( &xList, 0, sizeof( List_t ) ); + memset( &xTaskTCB, 0, sizeof( TCB_t ) ); + strncpy( xTaskTCB.pcTaskName, "TASK_EXIST", configMAX_TASK_NAME_LEN ); + + vListInitialise( &xList ); + + vCreateStaticTestTask( &xTaskTCB, + 1, + -1, + pdFALSE ); + + listINSERT_END( &xList, &xTaskTCB.xStateListItem ); + + /* API call. */ + pReturnedTCB = prvSearchForNameWithinSingleList( &xList, "TASK_EXIST" ); + + /* Validation. */ + TEST_ASSERT_EQUAL( &xTaskTCB, pReturnedTCB ); +} + +/** + * @brief prvSearchForNameWithinSingleList - task not found in the list + * + * Verify that NULL pointer should be returned when task with different name in the list. + * + * Coverage + * @code{c} + * if( cNextChar != pcNameToQuery[ x ] ) + * { + * xBreakLoop = pdTRUE; + * } + * @endcode + * ( cNextChar != pcNameToQuery[ x ] ) is true. + */ +void test_coverage_prvSearchForNameWithinSingleList_task_not_found( void ) +{ + List_t xList; + TCB_t xTaskTCB; + TCB_t * pReturnedTCB; + + /* Setup variables. */ + memset( &xList, 0, sizeof( List_t ) ); + memset( &xTaskTCB, 0, sizeof( TCB_t ) ); + + vListInitialise( &xList ); + + vCreateStaticTestTask( &xTaskTCB, + 1, + -1, + pdFALSE ); + strncpy( xTaskTCB.pcTaskName, "TASK_EXIST", configMAX_TASK_NAME_LEN ); + + listINSERT_END( &xList, &xTaskTCB.xStateListItem ); + + /* API call. */ + pReturnedTCB = prvSearchForNameWithinSingleList( &xList, "TASK_NOT_EXIST" ); + + /* Validation. */ + TEST_ASSERT_EQUAL( NULL, pReturnedTCB ); +} + +/** + * @brief prvSearchForNameWithinSingleList - task name too long + * + * Verify that NULL pointer should be returned when task with name longer than configMAX_TASK_NAME_LEN. + * + * Coverage + * @code{c} + * for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + * { + * } + * @endcode + * ( x < ( UBaseType_t ) configMAX_TASK_NAME_LEN ) is false. + */ +void test_coverage_prvSearchForNameWithinSingleList_long_task_name( void ) +{ + List_t xList; + TCB_t xTaskTCB; + TCB_t * pReturnedTCB; + + /* Setup variables. */ + memset( &xList, 0, sizeof( List_t ) ); + memset( &xTaskTCB, 0, sizeof( TCB_t ) ); + memcpy( xTaskTCB.pcTaskName, "TASK_EXIST12", configMAX_TASK_NAME_LEN ); + + vListInitialise( &xList ); + + vCreateStaticTestTask( &xTaskTCB, + 1, + -1, + pdFALSE ); + + listINSERT_END( &xList, &xTaskTCB.xStateListItem ); + + /* API call. */ + pReturnedTCB = prvSearchForNameWithinSingleList( &xList, "TASK_EXIST12" ); + + /* Validation. */ + TEST_ASSERT_EQUAL( NULL, pReturnedTCB ); +} diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c new file mode 100644 index 000000000..97855a2cf --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c @@ -0,0 +1,3489 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file multiple_priorities_no_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +/* =========================== EXTERN VARIABLES =========================== */ + +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================ FreeRTOS static allocate function ============================ */ + +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize, + BaseType_t xCoreId ) +{ + static StaticTask_t xIdleTaskTCBs[ configNUMBER_OF_CORES ]; + static StackType_t uxIdleTaskStacks[ configNUMBER_OF_CORES ][ configMINIMAL_STACK_SIZE ]; + + *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBs[ xCoreId ] ); + *ppxIdleTaskStackBuffer = &( uxIdleTaskStacks[ xCoreId ][ 0 ] ); + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-33 + * The purpose of this test is to verify when multiple CPU cores are available and + * the FreeRTOS kernel is configured as (configRUN_MULTIPLE_PRIORITIES = 1) that tasks + * of equal priority will execute simultaneously. The kernel will be configured as follows: + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority –1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_verification_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-34 + * The purpose of this test is to verify when multiple CPU cores are available and + * the FreeRTOS kernel is configured as (configRUN_MULTIPLE_PRIORITIES = 1) that + * tasks of different priorities will execute simultaneously. The kernel will be + * configured as follows: + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * One high priority task will be created. N low priority tasks will be created + * per remaining CPU cores. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_verification_tasks_different_priorities( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-35 + * A task of equal priority will be created for each available CPU core. + * This test will verify that when the priority of one task is lowered the + * task remains running. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Running (Core 0) State - Running (Core N) + * + * After calling vTaskPrioritySet() and lowering the priority of task T1 + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 2 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_change_tasks_equal_priority_lower( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks of equal priority for all available CPU cores */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Lower the priority of task T0 */ + vTaskPrioritySet( xTaskHandles[ 0 ], 1 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify all tasks remain in the running state on the same CPU cores */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-36 + * A task of equal priority will be created for each available CPU core. + * This test will verify that when the priority of one task is raised all + * tasks remain running. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * After calling vTaskPrioritySet() and raising the priority of task T1 + * + * Task (T1) Task (T2) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_change_tasks_equal_priority_raise( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks of equal priority for all available CPU cores */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Raise the priority of task T0 */ + vTaskPrioritySet( xTaskHandles[ 0 ], 2 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 2, xTaskDetails.xHandle->uxPriority ); + + /* Verify T0 is the the running state */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify all tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-37 + * A task of high priority will be created for each available CPU core. An + * additional task will be created in the ready state at low priority. + * This test will verify that when the priority of the ready task is raised + * to match the running tasks it will remain in the ready state. All other + * tasks will remain in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * After calling vTaskPrioritySet() and raising the priority of task TN + 1 + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + */ +void test_priority_change_tasks_different_priority_raise_to_equal( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify each task is in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Raise the priority of the ready task */ + vTaskPrioritySet( xTaskHandles[ i ], 2 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ i ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 2, xTaskDetails.xHandle->uxPriority ); + + /* Verify the task remains in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify each task is in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-38 + * A task of high priority will be created for each available CPU core. An + * additional task will be created in the ready state at low priority. + * This test will verify that when the priority of the ready task is raised + * to greater than the running tasks it will enter the running state. All + * other tasks will remain in the running state except for one. This task will + * now be in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * After calling vTaskPrioritySet() and raising the priority of task TN + 1 + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 3 + * State - Running (Core N) State - Running (Core N) + */ +void test_priority_change_tasks_different_priority_raise_to_higher( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify each task is in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Raise the priority of the ready task */ + vTaskPrioritySet( xTaskHandles[ i ], 3 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ i ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify the task remains in the state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify each task is in the running running state */ + for( i = 0; i < configNUMBER_OF_CORES - 1; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-39 + * A task of high priority will be created for each available CPU core. An + * additional task will be created in the ready state at low priority. + * This test will verify that when the priority of a running task is lowered + * to the priority of the existing ready task it will enter the ready state. + * The previously ready task will now be running. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * After calling vTaskPrioritySet() and lowering the priority of task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 1 + * State - Ready State - Running (Core N) State - Running (Core 0) + */ +void test_priority_change_tasks_different_priority_lower_to_equal( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify each task is in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Lower the priority of a running task */ + vTaskPrioritySet( xTaskHandles[ 0 ], 1 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the task is now in the ready state */ + verifySmpTask( &xTaskHandles[ 0 ], eReady, -1 ); + + /* Verify each other task is in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-40 + * A task of high priority will be created for each available CPU core. An + * additional task will be created in the ready state at low priority. + * This test will verify that when the priority of a running task is set to + * the lowest priority it will enter the ready state. + * The previously ready task will now be running. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 + * State - Running (Core N) State - Ready + * + * After calling vTaskPrioritySet() and lowering the priority of task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 3 Priority – 2 + * State - Ready State - Running (Core N) State - Running (Core 0) + */ +void test_priority_change_tasks_different_priority_lower_to_lowest( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify each task is in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Lower the priority of a running task */ + vTaskPrioritySet( xTaskHandles[ 0 ], 1 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the is now in the ready state */ + verifySmpTask( &xTaskHandles[ 0 ], eReady, -1 ); + + /* Verify each other task is in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-110 + * A task of equal priority will be created for each available CPU core. An + * additional task will be created in the ready state at equal priority. + * This test will verify that when the priority of running task is raised all + * the other running tasks remain running. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) Task (TN+1) + * Priority – 1 Priority – 1 Priority – 1 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) Task (TN+1) + * Priority – 1 Priority – 1 Priority – 1 + * State - Running State - Running State - Ready + * + * After calling vTaskPrioritySet() and raising the priority of task T1 + * + * Task (T1) Task (TN) Task (TN+1) + * Priority – 2 Priority – 1 Priority – 1 + * State - Running State - Running State - Ready + */ +void test_priority_change_tasks_equal_priority_raise_additional_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks at equal priority. */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify each task is in the running state. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last task is in the ready state. */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Raise the priority of a running task. */ + vTaskPrioritySet( xTaskHandles[ 0 ], 2 ); + + /* Verify the priority has been changed. */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 2, xTaskDetails.xHandle->uxPriority ); + + /* Verify each task is in the running state. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-41 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * that as each low priority task is deleted the high priority task remains in + * the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Delete each low priority task + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Deleted + */ +void test_task_delete_tasks_different_priorities_delete_low( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Delete low priority task */ + vTaskDelete( xTaskHandles[ i ] ); + + /* Verify T0 remains running on core 0 */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify task T[i] is in the deleted state */ + verifySmpTask( &xTaskHandles[ i ], eDeleted, -1 ); + } + + /* Verify tasks are pending deletion */ + TEST_ASSERT_EQUAL( ( configNUMBER_OF_CORES - 1 ), uxDeletedTasksWaitingCleanUp ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-42 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will delete the high + * priority task and verify each other core remains in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Delete the high priority task + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Deleted State - Running (Core N) + */ +void test_task_delete_tasks_different_priorities_delete_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Delete task T0 */ + vTaskDelete( xTaskHandles[ 0 ] ); + + /* Verify the task has been deleted */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + verifySmpTask( &xTaskHandles[ 0 ], eDeleted, -1 ); + + /* Verify core 0 is now running an idle task */ + verifyIdleTask( 0, 0 ); + + /* Verify other cores remain in the running state */ + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-43 + * A task of high priority will be created for each available CPU core. Two + * additional tasks will be created, a low priority task and a high priority task. + * This test will verify that when a running high priority task is deleted, the + * high priority task in the ready state will move to the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 1 Priority – 2 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 1 Priority – 2 + * State - Running (Core N) State - Ready State - Ready + * + * Delete the high priority task + * + * Task (T0) Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 2 Priority – 1 Priority – 2 + * State - Deleted State - Running (Core N) State - Ready State - Running (Core 0) + */ +void test_task_delete_select_high_priority_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 2 ] = { NULL }; + uint32_t i; + + /* Create tasks at high priority for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i + 1 ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining tasks are in the ready states */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + verifySmpTask( &xTaskHandles[ i + 1 ], eReady, -1 ); + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Delete task T0 */ + vTaskDelete( xTaskHandles[ 0 ] ); + + /* Verify the task has been deleted */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + verifySmpTask( &xTaskHandles[ 0 ], eDeleted, -1 ); + + /* Verify other cores remain in the running state */ + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* High priority task is now running on core 0 */ + verifySmpTask( &xTaskHandles[ i + 1 ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-45 + * Tasks of equal priority will be created for N - 1 CPU cores. The remaining + * CPU core will be idle. Once the scheduler is started a new task of equal + * priority shall be created. The test shall verify the new task is in the + * running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task N-1 + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task N-1 + * Priority – 1 + * State - Running (Core N) + * + * Create a new task with priority 1 + * + * Task N - 1 New Task + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Running (Last available core) + * + */ +void test_task_create_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES - 1; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining CPU core is running the idle task */ + verifyIdleTask( 0, i ); + + /* Create a new task of equal priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-46 + * Tasks of equal priority will be created for N - 1 CPU cores. The remaining + * task will be idle. Once the scheduler is started a new task of lower + * priority shall be created. The test shall verify the new task is in the + * running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task N-1 + * Priority – 2 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task N-1 + * Priority – 2 + * State - Running (Core N) + * + * Create a new task with priority 2 + * + * Task N - 1 New Task + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Running + * + */ +void test_task_create_tasks_lower_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining CPU core is running the idle task */ + verifyIdleTask( 0, i ); + + /* Create a new task of lower priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-47 + * Tasks of equal priority will be created for N - 1 CPU cores. The remaining + * task will be idle. Once the scheduler is started a new task of higher + * priority shall be created. The test shall verify the new task is in the + * running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task N-1 + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task N-1 + * Priority – 1 + * State - Running (Core N) + * + * Create a new task with priority 2 + * + * Task N-1 New Task + * Priority – 1 Priority – 2 + * State - Running (Core N) State - Running + * + */ +void test_task_create_tasks_higher_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining CPU core is running the idle task */ + verifyIdleTask( 0, i ); + + /* Create a new task of higher priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + /* Verify all tasks are in the ready state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-48 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a new task of equal priority is created it will + * be in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Create a new task of equal priority + * + * Task (TN) New Task + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_task_create_all_cores_equal_priority_equal( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task of equal priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-49 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a new task of lower priority is created it will + * be in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 2 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Create a new task of lower priority + * + * Task (TN) New Task + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_task_create_all_cores_equal_priority_lower( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task of lower priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-50 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a new task of higher priority is created it will + * be in the running state and a previously running task will now be in the + * ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Create a new task of higher priority + * + * Task (TN) New Task + * Priority – 1 Priority – 2 + * State - Running (Core N) State - Running + */ +void test_task_create_all_cores_equal_priority_higher( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task of higher priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last original task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-51 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will create a new + * high priority task and verify the new task is in the running state. A low + * priority task will also have been moved to the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Create a new high priority task + * + * Task (T1) Task (TN) New Task + * Priority – 2 Priority – 1 Priority – 2 + * State - Running (Core 0) State - Ready State - Running (Last Core) + */ +void test_task_create_all_cores_different_priority_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create single high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last original task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-52 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will create a new + * low priority task and verify the new task is in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Create a new low priority task + * + * Task (T1) Task (TN) New Task + * Priority – 2 Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) State - Ready + */ +void test_task_create_all_cores_different_priority_low( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create single high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-53 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a task is suspended the CPU core will execute + * the idle task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – N + * State - Running (Core N) + * + * Suspend task (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Suspended State - Running (Core N) + * + * Resume task (T1) + * + * Task (TN) + * Priority – N + * State - Running (Core N) + */ +void test_task_suspend_all_cores_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Suspend task T0 */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the task has been suspended */ + verifySmpTask( &xTaskHandles[ 0 ], eSuspended, -1 ); + + /* Verify all other tasks are running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Resume task T0 */ + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-55 + * A task of high priority will be created for each available CPU core. Two + * additional tasks will be created, a low priority task and a high priority task. + * This test will verify that when a running high priority task is suspended, the + * high priority task in the ready state will move to the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 1 Priority – 2 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 1 Priority – 2 + * State - Running (Core N) State - Ready State - Ready + * + * Suspend the high priority task + * + * Task (T0) Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 2 Priority – 1 Priority – 2 + * State - Suspended State - Running (Core N) State - Ready State - Running (Core 0) + */ +void test_task_suspend_select_high_priority_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 2 ] = { NULL }; + uint32_t i; + + /* Create tasks at high priority for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i + 1 ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining tasks are in the ready states */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + verifySmpTask( &xTaskHandles[ i + 1 ], eReady, -1 ); + + /* Suspend task T0 */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the task has been suspended */ + verifySmpTask( &xTaskHandles[ 0 ], eSuspended, -1 ); + + /* Verify other cores remain in the running state */ + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* High priority task is now running on core 0 */ + verifySmpTask( &xTaskHandles[ i + 1 ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-57 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will verify that + * when the high priority task is suspended the low priority tasks will + * remain in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Suspend task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Suspended State - Running (Core N) + * + * Resume task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_task_suspend_all_cores_different_priority_suspend_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Suspend the high priority task */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the suspended task is not running. */ + verifySmpTask( &xTaskHandles[ 0 ], eSuspended, -1 ); + + /* Verify all other tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-54 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. This test will verify that + * as each low priority task is suspended, the high priority task shall remain + * in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Suspend tasks (TN) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Suspended + * + * Resume tasks (TN) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_task_suspend_all_cores_different_priority_suspend_low( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + } + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Suspend low priority task */ + vTaskSuspend( xTaskHandles[ i ] ); + + /* Verify T0 remains running on core 0 */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify task T[i] is in the suspended state */ + verifySmpTask( &xTaskHandles[ i ], eSuspended, -1 ); + } + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Resume low priority task */ + vTaskResume( xTaskHandles[ i ] ); + + /* Verify T0 remains running on core 0 */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify task T[i] is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - i ) ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-59 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a task is blocked the CPU core will execute + * the idle task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Block task (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Blocked State - Running (Core N) + * + * Unblock task (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running ( Core 0 ) State - Running (Core N) + */ +void test_task_blocked_all_cores_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Block task T0 */ + vTaskDelay( 10 ); + + /* Verify the task has been suspended */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + /* Verify all other tasks are running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Unblock task T0 */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-60 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will verify that + * when the high priority task is blocked the low priority tasks will + * remain in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Block task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Blocked State - Running (Core N) + * + * Unblock task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_task_blocked_all_cores_different_priority_block_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Block the high priority task */ + vTaskDelay( 10 ); + + /* Verify the blocked task is not running. */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + /* Verify all other tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Unblock task T0 */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-62 + * A single task of high priority will be created for each available CPU core. + * An additional low priority task shall be created. This test will verify that + * when a high priority task is blocked the low priority task will enter the + * running state. When the blocked task is resumed, it will move to the running + * state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 Priority – 1 + * State - Running (Core 0) State - Running (Core N) State - Ready + * + * Block tasks (T1) + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 1 + * State - Blocked State - Running (Core N) State - Running (Core 0) + * + * Unblocked tasks (T1) + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) State - Ready + */ +void test_task_block_all_cores_high_priority_block( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a task for each CPU core at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all high priority tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Block the high priority task T0 */ + vTaskDelay( 10 ); + + /* Verify the task is blocked */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + /* Verify all high priority tasks remain running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); + + /* Resume the high priority task */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify all high priority tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-63 + * A task of high priority will be created for each available CPU core. Two + * additional tasks will be created, a low priority task and a high priority task. + * This test will verify that when a running high priority task is blocked, the + * high priority task in the ready state will move to the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 1 Priority – 2 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 1 Priority – 2 + * State - Running (Core N) State - Ready State - Ready + * + * Blocked the high priority task + * + * Task (T0) Task (TN) Task (TN + 1) Task (TN + 2) + * Priority – 2 Priority – 2 Priority – 1 Priority – 2 + * State - Blocked State - Running (Core N) State - Ready State - Running (Core 0) + */ +void test_task_blocked_select_high_priority_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 2 ] = { NULL }; + uint32_t i; + + /* Create tasks at high priority for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i + 1 ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining tasks are in the ready states */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + verifySmpTask( &xTaskHandles[ i + 1 ], eReady, -1 ); + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Block the task on core 0 */ + vTaskDelay( 10 ); + + /* Verify the task has been blocked */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + /* Verify other cores remain in the running state */ + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* High priority task is now running on core 0 */ + verifySmpTask( &xTaskHandles[ i + 1 ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-64 + * A task of equal priority will be created for each available CPU core. The + * vTaskCoreAffinitySet() API will be used to assign a specific core per task. + * Once the scheduler has been started the test will verify each task is + * running on the correctly designated core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 1 + * Affinity – Last CPU Core Affinity – (configNUMBER_OF_CORES - 1) - N) + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running ((configNUMBER_OF_CORES - 1) - N)) + */ +void test_task_affinity_verification_separate_cores( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* Normally each task will run on CPU cores in assending order. Assign the lowest + * tasks to the largest CPU core numbers */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vTaskCoreAffinitySet( xTaskHandles[ i ], 1 << ( ( configNUMBER_OF_CORES - 1 ) - i ) ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state on the correct CPU Core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, ( ( configNUMBER_OF_CORES - 1 ) - i ) ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-65 + * A task of equal priority will be created for each available CPU core. The + * vTaskCoreAffinitySet() API will be used to assign the last created task to + * CPU core 0. The test will verify each task is in the running state except + * for the last task. The last task will be in the ready state and the idle + * task will be running on the last available CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN-1) Task (Last) + * Priority – 1 Priority – 1 Priority – 1 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN-1) Task (Last) + * Priority – 1 Priority – 1 Priority – 1 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Running (Core 0) State - Running (Core N) State - Ready + */ +void test_task_affinity_verification_same_cores( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* Set core affinity for the last task to CPU 0 */ + vTaskCoreAffinitySet( xTaskHandles[ i - 1 ], 1 << 0 ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES - 1; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on the last CPU Core */ + verifyIdleTask( 0, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-66 + * A task of equal priority will be created for each available CPU core. The + * vTaskCoreAffinitySet() API will be used to assign the last created task to + * CPU core 0. The test will verify each task is in the running state except + * for the last task. The task running on CPU core 0 will then be suspended. + * The previously ready task will now be running on CPU core 0. When the + * suspended task is resumed, it will run on the previously idle CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (Last) + * Priority – 1 Priority – 1 + * Affinity – None Affinity - Core 0 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN-1) Task (Last) + * Priority – 1 Priority – 1 Priority – 1 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Running (Core 0) State - Running (Core N) State - Ready + * + * Suspend Task T0 + * + * Task (T0) Task (TN-1) Task (Last) + * Priority – 1 Priority – 1 Priority – 1 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Suspended State - Running (Core N) State - Running (Core 0) + * + * Resume Task T0 + * + * Task (T0) Task (TN-1) Task (Last) + * Priority – 1 Priority – 1 Priority – 1 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Running (Last Core) State - Running (Core N) State - Running (Core 0) + */ +void test_task_affinity_suspend_same_core_affinity( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* Set the last task to have affinity for core 0 only */ + vTaskCoreAffinitySet( xTaskHandles[ i - 1 ], 1 << 0 ); + + vTaskStartScheduler(); + + /* Verify all but the last task are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES - 1; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last task is in the ready state and the last CPU + * core is idle */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + verifyIdleTask( 0, ( configNUMBER_OF_CORES - 1 ) ); + + /* Suspend task T0 */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the previously ready task is now running on core 0 */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); + + /* Resume task T0 */ + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify task T0 is now running on the previously + * idle CPU core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-67 + * A task of equal priority will be created for each available CPU core. The + * vTaskCoreAffinitySet() API will be used to assign the last created task CPU + * affinity for a core that does not exist. Once the scheduler has been started + * the test will verify the task does not enter the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * Affinity – None Affinity – Out of range + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * Affinity – None Affinity – Out of range + * State - Running (Core N) State - Ready + * + * Suspend task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 + * Affinity – None Affinity – None Affinity - Out of range + * State - Suspended State - Running (Core N) State - Ready + */ +void test_task_affinity_out_of_range( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create tasks for each CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* Create an additional task which will be in the ready state */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Set the affinity mask to a core that is out of range */ + vTaskCoreAffinitySet( xTaskHandles[ i ], 1 << configNUMBER_OF_CORES ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify last task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Suspend task T0 */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify last task remains in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-69 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. An additional high priority + * task shall be created in the suspended state and have affinity for CPU core + * 0. This test shall verify that when the suspended task is resumed it remains + * in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Ready State - Ready State - Suspended + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity - Core 0 + * State - Running (Core 0) State - Running (Core N) State - Suspended + * + * Resume task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity – Core 0 + * State - Running (Core 0) State - Running (Core N) State - Ready + */ +void test_task_affinity_resume_suspended_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create tasks for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* Create an additional high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + /* Suspend task the last task and set core affinity for CPU 0 */ + vTaskSuspend( xTaskHandles[ i ] ); + vTaskCoreAffinitySet( xTaskHandles[ i ], 1 << 0 ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The last task shall be in the suspended state */ + verifySmpTask( &xTaskHandles[ i ], eSuspended, -1 ); + + /* Resume the last task */ + vTaskResume( xTaskHandles[ i ] ); + + /* The last task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-70 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. After the scheduler has been + * started an additional high priority task shall be created with affinity for + * CPU core 0. This task shall be in the ready state. This test shall verify that + * when the affinity is changed the task will then enter the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) + * Priority – 2 Priority – 1 + * Affinity – None Affinity – None + * State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) + * Priority – 2 Priority – 1 + * Affinity – None Affinity – None + * State – Running (Core 0) State – Running (Core N) + * + * Create a new high priority task with affinity for CPU core 0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity – Core 0 + * State – Running (Core 0) State – Running (Core N) State – Ready + * + * Remove core affinity on the new task + * + * Task (T0) Task (TN - 1) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity – None Affinity – None + * State – Running (Core 0) State – Running State – Ready State – Running (Last Core) + */ +void test_task_affinity_modify_affinity( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create tasks for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task with affinity for core 0 */ + xTaskCreateAffinitySet( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, ( 1 << 0 ), &xTaskHandles[ i ] ); + + /* The last task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Allow the task to run on any core */ + vTaskCoreAffinitySet( xTaskHandles[ i ], tskNO_AFFINITY ); + + /* Verify the task is now in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-71 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. After the scheduler has been + * started a new high priority task will be created with affinity for CPU core 0. + * This test shall verify the new task remains in the ready state until the + * priority of the task running on core 0 is lowered. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) + * Priority – 2 Priority – 1 + * Affinity – None Affinity – None + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) + * Priority – 2 Priority – 1 + * Affinity – None Affinity – None + * State - Running (Core 0) State - Running (Core N) + * + * Create a new high priority task with affinity for core 0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity – Core 0 + * State - Running (Core 0) State - Running (Core N) State - Ready + * + * Lower the priority of task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 2 + * Affinity – None Affinity – None Affinity – Core 0 + * State - Ready State - Running (Core N) State - Running (Core 0) + */ +void test_task_affinity_modify_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create tasks for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task with affinity for core 0 only */ + xTaskCreateAffinitySet( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, ( 1 << 0 ), &xTaskHandles[ i ] ); + + /* The last task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Lower the priority of task T0 */ + vTaskPrioritySet( xTaskHandles[ 0 ], 1 ); + + /* The new task will now be running on core 0 */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-68 + * A single task of low priority will be created. A medium priority task will be + * created for each remaining available CPU core. A task of the highest priority + * will be created and suspended. After the scheduler has been started the low + * priority task will have preemption disabled. This test will verify that when the + * highest priority task is resumed it will not preempt the lowest priority task. + * Instead it will replace one of the medium priority tasks. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * State – Ready State – Ready State – Suspended + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * State - Running (core N) State - Running State - Suspended + * + * Disable preemption on task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled + * State - Running (core N) State - Running State - Suspended + * + * Resume task TN + 1 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled + * State - Running (core N) State - Ready State - Running + */ +void test_task_preemption_verification( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ 0 ] ); + + /* Create a high priority task task for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a higher priority task which will be suspended */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ i ] ); + vTaskSuspend( xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify the low priority task is running on the last available CPU core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all remaining tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, ( i - 1 ) ); + } + + /* Verify the highest priority task is suspended */ + verifySmpTask( &xTaskHandles[ i ], eSuspended, -1 ); + + /* Disable preemption for task T0 */ + vTaskPreemptionDisable( xTaskHandles[ 0 ] ); + + /* Resume the highest priority task. Normally T0 would begin running this + * task since it is the lowest priority. Since preemption is disabled a + * higher priority task is selected instead. */ + vTaskResume( xTaskHandles[ i ] ); + + /* The highest priority task will run on the first available CPU core */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 2 ) ); + + /* The low priority task remains running on the last core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-72 + * A single task of low priority will be created. A medium priority task will be + * created for each remaining available CPU core. After the scheduler has been + * started preemption will be disabled on the low priority task. This test will + * verify that when a new task of the highest priority is created, it will + * preempt a medium priority task rather than the low priority task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 2 + * State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 2 + * State - Running (core N) State - Running + * + * Disable preemption on task T0 + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 2 + * Preemption Disabled + * State - Running (core N) State - Running + * + * Create new task at priority 3 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled + * State - Running (core N) State - Ready State - Running + */ +void test_task_preemption_new_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ 0 ] ); + + /* Create tasks for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the low priority task is running on the last available CPU core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all remaining tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, ( i - 1 ) ); + } + + /* Disable preemption for low priority task T0 */ + vTaskPreemptionDisable( xTaskHandles[ 0 ] ); + + /* Create a high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ i ] ); + + /* The new task will now be a CPU core previously running a priority 2 task */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 2 ) ); + + /* The low priority task remains running on the last core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-73 + * A single task of low priority will be created. A high priority task will be + * created for each remaining available CPU core. An additional low priority task + * shall be created. After the scheduler has been started the first low priority + * task will have preemption disabled. This test will verify that when the + * priority is raised on the low priority task in the ready state it will not + * preempt the lowest priority task currently running. Instead it will replace + * one of the high priority tasks. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 1 + * State - Running (core N) State - Running State - Ready + * + * Disable preemption on task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled + * State - Running (core N) State - Running State - Ready + * + * Raise the priority on task TN + 1 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled + * State - Running (core N) State - Ready State - Running + */ +void test_task_preemption_change_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ 0 ] ); + + /* Create tasks for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify the low priority task is running on the last available CPU core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, ( i - 1 ) ); + } + + /* Verify the low priority task is not running */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Disable preemption for low priority task T0 */ + vTaskPreemptionDisable( xTaskHandles[ 0 ] ); + + /* Raise the priority on the idle low priority task */ + vTaskPrioritySet( xTaskHandles[ i ], 3 ); + + /* The new task will now be a CPU core previously running a priority 2 task */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 2 ) ); + + /* The low priority task remains running on the last core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-74 + * A single task of low priority will be created. A high priority task will be + * created for each remaining available CPU core. After the scheduler has been + * started preemption will be disabled on the low priority task. This test will + * verify that when a new high priority task is created with affinity for the + * same core utilized by the low priority task, it shall remain in the ready state. + * When the new task is allowed to run on any CPU core it will preempt a high + * priority task rather than the low priority task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 2 + * State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 2 + * State - Running (core N) State - Running + * + * Disable preemption on task T0 + * + * Task (T0) Task (TN) + * Priority – 1 Priority – 2 + * Preemption Disabled + * State - Running (core N) State - Running + * + * Create new task at priority 3 with affinity for the same CPU core as task T0 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled Affinity mask set + * State - Running (core N) State - Running State - Ready + * + * Clear the affinity mask for Task TN + 1 + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 2 Priority – 3 + * Preemption Disabled + * State - Running (core N) State - Ready State - Running + */ +void test_task_preemption_change_affinity( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ 0 ] ); + + /* Create tasks for each remaining CPU core */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the low priority task is running on the last available CPU core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, ( i - 1 ) ); + } + + /* Disable preemption for low priority task T0 */ + vTaskPreemptionDisable( xTaskHandles[ 0 ] ); + + /* Create a high priority task with affinity for CPU core 0 */ + xTaskCreateAffinitySet( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, ( 1 << ( configNUMBER_OF_CORES - 1 ) ), &xTaskHandles[ i ] ); + + /* The new task will be in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Allow the task to run on any core */ + vTaskCoreAffinitySet( xTaskHandles[ i ], tskNO_AFFINITY ); + + /* The new task will now be a CPU core previously running a priority 2 task */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 2 ) ); + + /* The low priority task remains running on the last core */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-87 + * Tasks of equal priority waiting in the ready queue. The one waiting for the longest + * time should be selected to run. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configUSE_TASK_PREEMPTION_DISABLE 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 + * State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T0) Task (TN - 1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 Priority – 1 + * State - Running State - Running State - Ready State - Ready + * + * Task T1 yields on core 1 + * + * Task (T0) Task (T1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 Priority – 1 + * State - Running State - Ready State - Running State - Ready + * + * Task T0 yields on core 0 + * + * Task (T0) Task (T1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 Priority – 1 + * State - Ready State - Ready State - Running State - Running + * + * Task TN yields on core 1 + * + * Task (T0) Task (T1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 Priority – 1 + * State - Ready State - Running State - Ready State - Running + */ +void test_task_yield_run_wait_longest( void ) +{ + TaskHandle_t xTaskHandles[ ( configNUMBER_OF_CORES + 2 ) ] = { NULL }; + uint32_t i; + + /* Create ( N + 2 ) tasks of priority 1. The ready list should have tasks + * in the following orders: + * [ T0, T1, T2, ..., TN, TN + 1 ] + */ + for( i = 0; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* Start the scheduler. The tasks running status: + * T0 : core 0 + * T1 : core 1 + * ... + * TN : in ready list + * TN + 1 : in ready list + */ + vTaskStartScheduler(); + + for( i = 0; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + if( i < configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + else + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + } + + /* T1 yield itself on core 1. TN should be selected to run on core 1. + * The tasks running status: + * T0 : core 0 + * T1 : in ready list + * ... + * TN : core 1 + * TN + 1 : in ready list + */ + vSetCurrentCore( 1 ); + taskYIELD(); + + for( i = 0; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + if( i == 1 ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + else if( i == ( configNUMBER_OF_CORES + 1 ) ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + else if( i == configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, 1 ); + } + else + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + } + + /* T0 yield itself on core 0. TN + 1 should be selected to run on core 0. + * The tasks running status: + * T0 : in ready list + * T1 : in ready list + * ... + * TN : core 1 + * TN + 1 : core 0 + */ + vSetCurrentCore( 0 ); + taskYIELD(); + + for( i = 0; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + if( ( i == 0 ) || ( i == 1 ) ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + else if( i == configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, 1 ); + } + else if( i == ( configNUMBER_OF_CORES + 1 ) ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); + } + else + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + } + + /* TN yield itself on core 1. T1 should now runs on core 1 since it stop running first. + * The tasks running status: + * T0 : in ready list + * T1 : core 1 + * ... + * TN : in ready list + * TN + 1 : core 0 + */ + vSetCurrentCore( 1 ); + taskYIELD(); + + for( i = 0; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + if( i == 0 ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + else if( i == configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + else if( i == 1 ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, 1 ); + } + else if( i == ( configNUMBER_OF_CORES + 1 ) ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); + } + else + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-88 + * Tasks of equal priority waiting in the ready queue. The new task of equal priority + * should be selected to run when a running task yields itself. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State – Running State – Running + * + * Create Task TN + 1 + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 + * State - Running State - Running State - Ready + * + * Task T0 yields on core 0 + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority – 1 + * State - Ready State - Running State - Running + */ +void test_task_yield_run_equal_priority_new_task( void ) +{ + TaskHandle_t xTaskHandles[ ( configNUMBER_OF_CORES + 1 ) ] = { NULL }; + uint32_t i; + + /* Create N tasks. */ + for( i = 0; i < ( configNUMBER_OF_CORES ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Create task TN+1. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Task T1 yields itself on core 0. */ + taskYIELD(); + + /* The new task TN+1 should runs on core 0. */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-106 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priority task. + * The lower priority will be switched out when it disinherits higher priority task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Running State – Ready State – Running + * uxMutexesHeld - 1 + * + * Task TN+1 disinherits task T1's priority. + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + * uxMutexesHeld - 0 + */ +void test_task_priority_inherit_disinherit( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + xTaskPriorityDisinherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the mutex held count is decreased. */ + TEST_ASSERT_EQUAL( 0U, xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld ); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify that the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-107 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priority task. + * The lower priority will be switched out when it is disinherited by higher priority + * task due to timeout. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Running State – Ready State – Running + * + * Task TN+1 is disinherited by task T1 due to timeout + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + */ +void test_task_priority_inherit_disinherit_timeout( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + vTaskPriorityDisinheritAfterTimeout( xTaskHandles[ configNUMBER_OF_CORES ], 1 ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify that the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); +} diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/FreeRTOSConfig.h new file mode 100644 index 000000000..d7d2a4b87 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/FreeRTOSConfig.h @@ -0,0 +1,161 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* https://www.FreeRTOS.org/a00110.html +*----------------------------------------------------------*/ + +/* SMP test specific configuration */ +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configNUMBER_OF_CORES 16 +#define configUSE_CORE_AFFINITY 1 +#define configUSE_TIME_SLICING 0 +#define configUSE_TASK_PREEMPTION_DISABLE 1 +#define configTICK_CORE 0 +#define configUSE_TICKLESS_IDLE 1 +#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 + +/* OS Configuration */ +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 +#define portREMOVE_STATIC_QUALIFIER 1 +#define portCRITICAL_NESTING_IN_TCB 1 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_PASSIVE_IDLE_HOOK 1 +#define configKERNEL_PROVIDED_STATIC_MEMORY 1 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) +extern const char * pcIdleTaskName; +#define configIDLE_TASK_NAME pcIdleTaskName + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configENABLE_MPU 0 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +#define configASSERT( x ) \ + do \ + { \ + if( x ) \ + { \ + vFakeAssert( true, __FILE__, __LINE__ ); \ + } \ + else \ + { \ + vFakeAssert( false, __FILE__, __LINE__ ); \ + } \ + } while( 0 ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) + extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); + #define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer ) +#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */ + +#define portSUPPRESS_TICKS_AND_SLEEP vPortSuppressTicksAndSleep + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/Makefile b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/Makefile new file mode 100644 index 000000000..c75db09f7 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/Makefile @@ -0,0 +1,51 @@ +# indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) + +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC := tasks.c + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +#PROJECT_DEPS_SRC := + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS := FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := covg_multiple_priorities_no_timeslice_mock_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +#SUITE_SUPPORT_SRC := + + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_port.h +MOCK_FILES_FP += $(KERNEL_DIR)/include/list.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/smp/multiple_priorities_no_timeslice_mock/list_macros.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/smp/multiple_priorities_no_timeslice_mock/local_portable.h + + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS += -include list_macros.h + +# List any addiitonal flags needed by the compiler +CFLAGS += + +# Try not to edit beyond this line unless necessary. + +# Project is determined based on path: $(UT_ROOT_DIR)/$(PROJECT) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +# Make variables available to included makefile +export + +include ../../testdir.mk diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/covg_multiple_priorities_no_timeslice_mock_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/covg_multiple_priorities_no_timeslice_mock_utest.c new file mode 100644 index 000000000..2ac0955ad --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/covg_multiple_priorities_no_timeslice_mock_utest.c @@ -0,0 +1,1259 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file covg_multiple_priorities_no_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Tasks includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "CException.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" +#include + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_list.h" +#include "mock_list_macros.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" +#include "mock_local_portable.h" + +/* ================================= MACROS =============================== */ + +/** + * @brief CException code for when a configASSERT should be intercepted. + */ +#define configASSERT_E 0xAA101 +#define EXIT_LOOP 0xAA102 + +/** + * @brief Expect a configASSERT from the function called. + * Break out of the called function when this occurs. + * @details Use this macro when the call passed in as a parameter is expected + * to cause invalid memory access. + */ +#define EXPECT_ASSERT_BREAK( call ) \ + do \ + { \ + shouldAbortOnAssertion = true; \ + CEXCEPTION_T e = CEXCEPTION_NONE; \ + Try \ + { \ + call; \ + TEST_FAIL(); \ + } \ + Catch( e ) \ + { \ + TEST_ASSERT_EQUAL( configASSERT_E, e ); \ + } \ + } while( 0 ) + +/* ============================ GLOBAL VARIABLES =========================== */ + +/** + * @brief Global idle task name pointer. + */ +const char * pcIdleTaskName = "IDLE"; + +/** + * @brief Global counter for the number of assertions in code. + */ +static int assertionFailed = 1; + +/** + * @brief Flag which denotes if test need to abort on assertion. + */ +static BaseType_t shouldAbortOnAssertion; + +/* =========================== EXTERN VARIABLES =========================== */ + +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile UBaseType_t xSchedulerRunning; +extern volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; +extern volatile TCB_t * pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ]; +extern volatile BaseType_t xYieldForTask; +extern volatile BaseType_t xYieldRequired; +extern volatile UBaseType_t uxCurrentNumberOfTasks; +extern volatile UBaseType_t uxSchedulerSuspended; +extern volatile UBaseType_t uxTopReadyPriority; +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; +extern UBaseType_t uxTaskNumber; +extern volatile TickType_t xTickCount; +extern volatile TickType_t xNextTaskUnblockTime; + +/* =========================== EXTERN FUNCTIONS =========================== */ + +extern BaseType_t prvCreateIdleTasks( void ); + +/* ========================== STATIC FUNCTIONS ========================== */ + +void vApplicationPassiveIdleHook( void ) +{ + /* Adding this function to pass compilation. */ +} + +static void vFakeAssertStub( bool x, + char * file, + int line, + int cmock_num_calls ) +{ + if( !x ) + { + assertionFailed++; + + if( shouldAbortOnAssertion == pdTRUE ) + { + Throw( configASSERT_E ); + } + } +} + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + /* Reset the idle task name to default value. */ + pcIdleTaskName = "IDLE"; + + vFakeAssert_StubWithCallback( vFakeAssertStub ); + + UnityMalloc_StartTest(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + UnityMalloc_EndTest(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + + +/* ========================== HELPER FUNCTIONS ========================== */ + +void * pvPortMalloc( size_t xSize ) +{ + return unity_malloc( xSize ); +} + +void vPortFree( void * pv ) +{ + return unity_free( pv ); +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief vTaskSuspend - suspends the running task + * + * This test is used to suspend a running task when task is actively + * running and not scheduled to yield. + * + * Coverage + * @code{c} + * if( xSchedulerRunning != pdFALSE ) + * { + * if( xTaskRunningOnCore == portGET_CORE_ID() ) + * { + * configASSERT( uxSchedulerSuspended == 0 ); + * vTaskYieldWithinAPI(); + * } + * else + * { + * prvYieldCore( xTaskRunningOnCore ); + * } + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( xSchedulerRunning != pdFALSE ) is false. + */ +void test_coverage_vTaskSuspend_scheduler_running_false( void ) +{ + TCB_t xTaskTCBs[ 1 ] = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + pxCurrentTCBs[ 0 ]->xTaskRunState = 1; + xSchedulerRunning = pdFALSE; + + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + vListInsertEnd_ExpectAnyArgs(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskSuspend( &xTaskTCBs[ 0 ] ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdFALSE, xYieldPendings[ 0 ] ); + TEST_ASSERT_EQUAL( 1, pxCurrentTCBs[ 0 ]->xTaskRunState ); +} + +/** + * @brief vTaskSuspend - suspends the task + * + * This test is used to ensure that one of the macro's conditions + * where TaskRunState is greater than zero is set to false. + * + * Coverage + * @code{c} + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) ) is false. + */ + +void test_coverage_vTaskSuspend_running_state_below_range( void ) +{ + TCB_t xTaskTCBs[ 1 ] = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + pxCurrentTCBs[ 0 ]->xTaskRunState = -1; + xSchedulerRunning = pdFALSE; + + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + vListInsertEnd_ExpectAnyArgs(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskSuspend( &xTaskTCBs[ 0 ] ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdFALSE, xYieldPendings[ 0 ] ); + TEST_ASSERT_EQUAL( -1, pxCurrentTCBs[ 0 ]->xTaskRunState ); +} + +/** + * @brief vTaskSuspend - suspends the task + * + * This test is used to cover the case where the other macro condition where + * TaskRunState is less than configNUMBER_OF_CORES is set to false. + * + * Coverage + * @code{c} + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) ) is false. + */ + +void test_coverage_vTaskSuspend_running_state_above_range( void ) +{ + TCB_t xTaskTCBs[ 1 ] = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCBs[ 0 ].uxPriority = 1; + xYieldPendings[ 0 ] = pdFALSE; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ 0 ]; + pxCurrentTCBs[ 0 ]->xTaskRunState = configNUMBER_OF_CORES + 1; + + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + vListInsertEnd_ExpectAnyArgs(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskSuspend( &xTaskTCBs[ 0 ] ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdFALSE, xYieldPendings[ 0 ] ); + TEST_ASSERT_EQUAL( configNUMBER_OF_CORES + 1, pxCurrentTCBs[ 0 ]->xTaskRunState ); +} + +/** + * @brief vTaskPrioritySet - sets the priority + * + * This test is to change the priorities of non + * running tasks + * + * Coverage + * @code{c} + * else if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) ) is false. + */ +void test_coverage_vTaskPrioritySet_non_running_state( void ) +{ + TCB_t xTaskTCBs[ 1 ] = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCBs[ 0 ].uxPriority = 4; + xTaskTCBs[ 0 ].uxBasePriority = 4; + xTaskTCBs[ 0 ].xTaskRunState = configNUMBER_OF_CORES + 1; + + vFakeAssert_Ignore(); + vFakePortCheckIfInISR_StopIgnore(); + vFakePortEnterCriticalSection_Ignore(); + vFakePortYieldCore_CMockIgnore(); + listGET_LIST_ITEM_VALUE_ExpectAnyArgsAndReturn( ( TickType_t ) 0x80000000UL ); + listIS_CONTAINED_WITHIN_ExpectAnyArgsAndReturn( pdFALSE ); + vFakePortExitCriticalSection_Ignore(); + + /* API call. */ + vTaskPrioritySet( &xTaskTCBs[ 0 ], 2 ); + + /* Validation. */ + TEST_ASSERT_EQUAL( configNUMBER_OF_CORES + 1, xTaskTCBs[ 0 ].xTaskRunState ); + TEST_ASSERT_EQUAL( 2, xTaskTCBs[ 0 ].uxPriority ); +} + +/** + * @brief vTaskPrioritySet - sets the priority + * + * This test verifies that the current task is not + * preempted by any other task of higher priority. + * + * Coverage + * @code{c} + * if( pxTCB->xPreemptionDisable == pdFALSE ) + * @endcode + * ( pxTCB->xPreemptionDisable == pdFALSE ) is false. + */ +void test_coverage_vTaskPrioritySet_running_state( void ) +{ + TCB_t xTaskTCBs[ 1 ] = { NULL }; + + /* Setup the variables and structure. */ + xTaskTCBs[ 0 ].uxPriority = 4; + xTaskTCBs[ 0 ].uxBasePriority = 4; + xTaskTCBs[ 0 ].xPreemptionDisable = pdTRUE; + xTaskTCBs[ 0 ].xTaskRunState = 1; + + BaseType_t xYieldRequired = pdFALSE; + BaseType_t xYieldForTask = pdFALSE; + + vFakeAssert_Ignore(); + vFakePortCheckIfInISR_StopIgnore(); + vFakePortEnterCriticalSection_Ignore(); + vFakePortYieldCore_CMockIgnore(); + listGET_LIST_ITEM_VALUE_ExpectAnyArgsAndReturn( ( TickType_t ) 0x80000000UL ); + listIS_CONTAINED_WITHIN_ExpectAnyArgsAndReturn( pdFALSE ); + vFakePortExitCriticalSection_Ignore(); + + /* API call. */ + vTaskPrioritySet( &xTaskTCBs[ 0 ], 2 ); + + /* Validation. */ + TEST_ASSERT_EQUAL( pdFALSE, xYieldRequired ); + TEST_ASSERT_EQUAL( pdFALSE, xYieldForTask ); +} + +/** + * @brief prvYieldCore - xCoreID is not equal to current core id. + * + * This test ensures that the first condition is true while the second + * condition is false in the if statement, so we will be performing the + * action with portYIELD_CORE, and the task is put in the yielding state + * + * Coverage + * @code{c} + * if( ( portCHECK_IF_IN_ISR() == pdTRUE ) && ( xCoreID == portGET_CORE_ID() ) ) + * ... + * @endcode + * ( portCHECK_IF_IN_ISR() == pdTRUE ) is true. + * ( xCoreID == portGET_CORE_ID() ) is false. + */ +void test_coverage_prvYieldCore_core_id_ne_current_coreid( void ) +{ + TCB_t task; + TCB_t task2; + TaskHandle_t xTaskHandle; + + task.xTaskRunState = 1; /* running on core 1 */ + task2.xTaskRunState = -2; /* running on core 2 taskTASK_YIELDING */ + xTaskHandle = &task; + pxCurrentTCBs[ 0 ] = &task; + pxCurrentTCBs[ 1 ] = &task; + pxCurrentTCBs[ 2 ] = &task2; + xSchedulerRunning = pdTRUE; + + /* Test Expectations */ + vFakePortEnterCriticalSection_Expect(); + /* Entering prvYieldCore */ + vFakePortGetCoreID_ExpectAndReturn( 2 ); + vFakePortYieldCore_Expect( 1 ); + /* Leaving prvYieldCore */ + vFakePortExitCriticalSection_Expect(); + + /* API call */ + vTaskPreemptionEnable( xTaskHandle ); + + /* Test Assertions */ + TEST_ASSERT_EQUAL( pdFALSE, xYieldPendings[ 2 ] ); + TEST_ASSERT_EQUAL( -2, pxCurrentTCBs[ 1 ]->xTaskRunState ); /* yielding state */ + TEST_ASSERT_EQUAL( -2, task.xTaskRunState ); /* yielding state */ +} + +/** + * @brief prvYieldCore - task runstate equal to yielding. + * + * This test ensures that when the task is already in the yielding state, + * nothing is done + * + * Coverage + * @code{c} + * if( pxCurrentTCBs[ xCoreID ]->xTaskRunState != taskTASK_YIELDING ) + * @endcode + * ( pxCurrentTCBs[ xCoreID ]->xTaskRunState != taskTASK_YIELDING ) is false. + */ +void test_coverage_prvYieldCore_runstate_eq_yielding( void ) +{ + TCB_t task; + TCB_t task2; + TaskHandle_t xTaskHandle; + + task.xTaskRunState = 1; /* running on core 1 */ + task2.xTaskRunState = -2; /* running on core 2 taskTASK_YIELDING */ + xTaskHandle = &task; + pxCurrentTCBs[ 0 ] = &task; + pxCurrentTCBs[ 1 ] = &task2; + pxCurrentTCBs[ 2 ] = &task2; + xSchedulerRunning = pdTRUE; + + /* Test Expectations */ + vFakePortEnterCriticalSection_Expect(); + /* Entering prvYieldCore */ + vFakePortGetCoreID_ExpectAndReturn( 2 ); + /* Leaving prvYieldCore */ + vFakePortExitCriticalSection_Expect(); + + /* API call */ + vTaskPreemptionEnable( xTaskHandle ); + + /* Test Assertions */ + TEST_ASSERT_EQUAL( pdFALSE, xYieldPendings[ 2 ] ); + TEST_ASSERT_EQUAL( -2, pxCurrentTCBs[ 1 ]->xTaskRunState ); /* yielding */ + TEST_ASSERT_EQUAL( 1, task.xTaskRunState ); /* nothing has changed */ +} + +/** + * @brief vTaskDelete - scheduler not running. + * + * This test ensures that if vTaskDelete is called and the scheuler is + * not running, the core is not yielded, but it is removed from the + * stateList, the eventList and inserted in the taskwaitingtermination + * list, the uxdeletedtaskwaiting for cleanup is increased and the + * uxtasknumber is increased + * + * Coverage + * @code{c} + * if( ( xSchedulerRunning != pdFALSE ) && + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) ) + * ... + * @endcode + * ( xSchedulerRunning != pdFALSE ) is false. + */ +void test_coverage_vTaskDelete_scheduler_not_running( void ) +{ + TCB_t task; + TaskHandle_t xTaskToDelete; + + task.xTaskRunState = 1; /* running on core 1 */ + xTaskToDelete = &task; + pxCurrentTCBs[ 0 ] = &task; + + xSchedulerRunning = pdFALSE; + + uxDeletedTasksWaitingCleanUp = 0; + uxTaskNumber = 1; + + /* Test Expectations */ + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( 0 ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + + /* if task != taskTaskNOT_RUNNING */ + vListInsertEnd_ExpectAnyArgs(); + vPortCurrentTaskDying_ExpectAnyArgs(); + + vFakePortExitCriticalSection_Expect(); + + + /* API Call */ + vTaskDelete( xTaskToDelete ); + + /* Test Verifications */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + TEST_ASSERT_EQUAL( 2, uxTaskNumber ); +} + +/** + * @brief This test ensures that if xTask Delete is called and the scheuler is + * running while the task runstate is more that the configNUMBER_OF_CORES, + * the core is not yielded, but it is removed from the + * stateList, the eventList and inserted in the taskwaitingtermination + * list, the uxdeletedtaskwaiting for cleanup is not changed + * uxtasknumber is increased + * + * Coverage + * @code{c} + * vTaskDelete( xTaskToDelete); + * + * if( ( xSchedulerRunning != pdFALSE ) && + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * INCLUDE_vTaskDelete = 1 + */ +void test_coverage_vTaskDelete_task_not_running( void ) +{ + TCB_t task; + TaskHandle_t xTaskToDelete; + + task.xTaskRunState = configNUMBER_OF_CORES + 2; /* running on core 1 */ + xTaskToDelete = &task; + pxCurrentTCBs[ 0 ] = &task; + + xSchedulerRunning = pdTRUE; + + uxDeletedTasksWaitingCleanUp = 0; + uxTaskNumber = 1; + + /* Test Expectations */ + vFakePortEnterCriticalSection_Expect(); + uxListRemove_ExpectAnyArgsAndReturn( 0 ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + + /* if task != taskTaskNOT_RUNNING */ + vListInsertEnd_ExpectAnyArgs(); + vPortCurrentTaskDying_ExpectAnyArgs(); + + vFakePortExitCriticalSection_Expect(); + + /* API Call */ + vTaskDelete( xTaskToDelete ); + + /* Test Verifications */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + TEST_ASSERT_EQUAL( 2, uxTaskNumber ); +} + +/** + * @brief This test ensures that when we call eTaskGetState with a task that is + * not running eReady is returned + * + * Coverage + * @code{c} + * eTaskGetSate( xTask ); + * + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * INCLUDE_eTaskGetState = 1 + * configUSE_TRACE_FACILITY = 1 + * INCLUDE_xTaskAbortDelay = 1 + */ +void test_coverage_eTaskGetState_task_not_running( void ) +{ + TCB_t task = { 0 }; + TaskHandle_t xTask = &task; + + task.xTaskRunState = configNUMBER_OF_CORES + 2; + List_t list = { 0 }; + eTaskState xRet; + + /* Test Expectations */ + vFakePortEnterCriticalSection_Expect(); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( &list ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); /* Event list container is NULL. */ + vFakePortExitCriticalSection_Expect(); + + /* API Call */ + xRet = eTaskGetState( xTask ); + + /* Test Verifications */ + TEST_ASSERT_EQUAL( eReady, xRet ); +} + +/** + * @brief This test ensures that when we call vTaskPreemtionDisable with a null + * handle, the pxCurrentTCBs of the running core is used + * + * Coverage + * @code{c} + * vTaskPreemptionEnable( xTask ); + * + * pxTCB = prvGetTCBFromHandle( xTask ); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * INCLUDE_eTaskGetState = 1 + * configUSE_TRACE_FACILITY = 1 + * INCLUDE_xTaskAbortDelay = 1 + * INCLUDE_xTaskGetCurrentTaskHandle = 1 + * configUSE_MUTEXES = 1 + */ +void test_coverage_vTaskPreemptionDisable_null_handle( void ) +{ + TCB_t xTask = { 0 }; + + pxCurrentTCBs[ 0 ] = &xTask; + + /* Test Expectations */ + vFakePortEnterCriticalSection_Expect(); + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + vFakePortExitCriticalSection_Expect(); + + /* API Call */ + vTaskPreemptionDisable( NULL ); + + /* Test Verifications */ + TEST_ASSERT_EQUAL( pdTRUE, pxCurrentTCBs[ 0 ]->xPreemptionDisable ); +} + +/** + * @brief This test ensures that when we call vTaskSuspendAll and we task of the + * current core has a critical nesting count of 1 only the scheduler is + * suspended + * + * Coverage + * @code{c} + * vTaskSuspendAll(); + * + * if( portGET_CRITICAL_NESTING_COUNT() == 0U ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_coverage_vTaskSuspendAll_critical_nesting_ne_zero( void ) +{ + TCB_t xTask = { 0 }; + + xTask.uxCriticalNesting = 1; + pxCurrentTCBs[ 0 ] = &xTask; + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = 0U; + + /* Test Expectations */ + vFakePortAssertIfISR_Expect(); + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetTaskLock_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortGetISRLock_Expect(); + vFakePortReleaseISRLock_Expect(); + vFakePortClearInterruptMask_Expect( 0 ); + + /* API Call */ + vTaskSuspendAll(); + + /* Test Verifications */ + TEST_ASSERT_EQUAL( 1, uxSchedulerSuspended ); +} + +/** + * @brief This test ensures that when we call prvGetExpectedIdleTime and the top + * ready priority is greater than the idle task, we return zero, + * as a suggestion to sleep + * + * Coverage + * @code{c} + * prvGetExpectedIdleTime(); + * + * if( uxTopReadyPriority > tskIDLE_PRIORITY ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configUSE_TICKLESS_IDLE != 0 + * configUSE_PORT_OPTIMISED_TASK_SELECTION = 0 + */ +void test_coverage_prvGetExpectedIdleTime_top_priority_gt_idle_prio( void ) +{ + CEXCEPTION_T e = CEXCEPTION_NONE; + TCB_t xTCB = { 0 }; + + pxCurrentTCBs[ 0 ] = &xTCB; + + xTCB.uxPriority = tskIDLE_PRIORITY + 1; + + /* Test Setup */ + uxDeletedTasksWaitingCleanUp = 0; + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Test Expectations */ + vFakePortYield_Expect(); + + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( configNUMBER_OF_CORES - 1 ); + + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + + listCURRENT_LIST_LENGTH_ExpectAndThrow( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ), + EXIT_LOOP ); + + + /* API Call */ + portTASK_FUNCTION( prvIdleTask, args ); + + Try + { + prvIdleTask( NULL ); + } + Catch( e ) + { + if( e == EXIT_LOOP ) + { + TEST_PASS(); + } + else + { + TEST_FAIL(); + } + } + /* Test Verifications */ + + /* this function (vPortSuppressTicksAndSleep_Expect) not being called is the aim of this test, it proves that the + * task did not go to sleep, technically nothing happens */ +} + +/** + * @brief This test ensures that when we call prvGetExpectedIdleTime, and the + * ready tasks lists contains more than one element, + * then we return zero as a suggestion to sleep + * + * Coverage + * @code{c} + * prvGetExpectedIdleTime(); + * + * else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configUSE_TICKLESS_IDLE != 0 + * configUSE_PORT_OPTIMISED_TASK_SELECTION = 0 + */ +void test_coverage_prvGetExpectedIdleTime_ready_list_gt_one( void ) +{ + CEXCEPTION_T e = CEXCEPTION_NONE; + TCB_t xTCB = { 0 }; + + pxCurrentTCBs[ 0 ] = &xTCB; + xTCB.uxPriority = tskIDLE_PRIORITY; + + /* Test Setup */ + uxDeletedTasksWaitingCleanUp = 0; + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Test Expectations */ + vFakePortYield_Expect(); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( configNUMBER_OF_CORES - 1 ); + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( configNUMBER_OF_CORES - 1 ); + + listCURRENT_LIST_LENGTH_ExpectAndThrow( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ), + EXIT_LOOP ); + + /* API Call */ + portTASK_FUNCTION( prvIdleTask, args ); + + Try + { + prvIdleTask( NULL ); + } + Catch( e ) + { + if( e == EXIT_LOOP ) + { + TEST_PASS(); + } + else + { + TEST_FAIL(); + } + } + /* Test Verifications */ + + /* this function (vPortSuppressTicksAndSleep_Expect) not being called is the aim of this test, it proves that the + * task did not go to sleep, technically nothing happens */ +} + +/** + * @brief This test ensures that when we call prvIdleTask and the ready tasks + * lists contains 1 elemets and the top ready priority is less or equal + * to the idle priority, then we let the suggested time to sleep is + * returned + * + * Coverage + * @code{c} + * prvGetExpectedIdleTime(); + * + * else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configUSE_TICKLESS_IDLE != 0 + * configUSE_PORT_OPTIMISED_TASK_SELECTION = 0 + */ +void test_coverage_prvGetExpectedIdleTime_ready_list_eq_1( void ) +{ + CEXCEPTION_T e = CEXCEPTION_NONE; + TCB_t xTCB = { 0 }; + + xTickCount = 230; + xNextTaskUnblockTime = 240; /* expectedidletime = xNextTaskUnblockTime - xTickCount */ + pxCurrentTCBs[ 0 ] = &xTCB; + xTCB.uxPriority = tskIDLE_PRIORITY; + + /* Test Setup */ + uxDeletedTasksWaitingCleanUp = 0; + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Test Expectations */ + vFakePortYield_Expect(); + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 1 ); + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 1 ); + + /* vTaskSuspendAll */ + vFakePortAssertIfISR_Expect(); + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortReleaseISRLock_Expect(); + vFakePortClearInterruptMask_Expect( 0 ); + + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 1 ); + + /* Test Verifications */ + + /* this function being called is the aim of this test, it proves that the + * task went to sleep the specified amount of time. */ + vPortSuppressTicksAndSleep_Expect( xNextTaskUnblockTime - xTickCount ); + + vFakePortEnterCriticalSection_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortReleaseTaskLock_Expect(); + vFakePortExitCriticalSection_Expect(); + + listCURRENT_LIST_LENGTH_ExpectAndThrow( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ), + EXIT_LOOP ); + + + /* API Call */ + portTASK_FUNCTION( prvIdleTask, args ); + + Try + { + prvIdleTask( NULL ); + } + Catch( e ) + { + if( e == EXIT_LOOP ) + { + TEST_PASS(); + } + else + { + TEST_FAIL(); + } + } + /* Test Verifications */ + /* the verification of the test is above in the expectations */ +} + +void port_assert_if_isr_cb( int num_callbacks ) +{ + xTickCount = 239; +} + +/** + * @brief This test ensures that when we call prvIdleTask and the ready tasks + * lists contains 1 elemets and the top ready priority is less or equal + * to the idle priority, then we let the suggested time to sleep is + * returned + * + * Coverage + * @code{c} + * prvGetExpectedIdleTime(); + * + * else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configUSE_TICKLESS_IDLE != 0 + * configUSE_PORT_OPTIMISED_TASK_SELECTION = 0 + */ +void test_coverage_prvGetExpectedIdleTime_ready_list_eq_2( void ) +{ + CEXCEPTION_T e = CEXCEPTION_NONE; + TCB_t xTCB = { 0 }; + + xTickCount = 238; + xNextTaskUnblockTime = 240; /* expectedidletime = xNextTaskUnblockTime - xTickCount */ + pxCurrentTCBs[ 0 ] = &xTCB; + xTCB.uxPriority = tskIDLE_PRIORITY; + + /* Test Setup */ + uxDeletedTasksWaitingCleanUp = 0; + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Test Expectations */ + vFakePortYield_Expect(); + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( configNUMBER_OF_CORES + 1 ); + vFakePortYield_Expect(); + + /* pxCurrentTCB */ + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); + + /* vTaskSuspendAll */ + vFakePortAssertIfISR_Stub( port_assert_if_isr_cb ); + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortReleaseISRLock_Expect(); + vFakePortClearInterruptMask_Expect( 0 ); + + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); + + vFakePortEnterCriticalSection_Expect(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortReleaseTaskLock_Expect(); + vFakePortExitCriticalSection_Expect(); + + listCURRENT_LIST_LENGTH_ExpectAndThrow( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ), + EXIT_LOOP ); + + /* API Call */ + portTASK_FUNCTION( prvIdleTask, args ); + + Try + { + prvIdleTask( NULL ); + } + Catch( e ) + { + if( e == EXIT_LOOP ) + { + TEST_PASS(); + } + else + { + TEST_FAIL(); + } + } + /* Test Verifications */ + + /* this function (vPortSuppressTicksAndSleep_Expect) not being called is + * the aim of this test, it proves that the + * task did not go to sleep, technically nothing happens */ +} + +/** + * @brief This test ensures that when we call prvGetExpectedIdleTime and the top + * ready priority is equal than the idle priority, and the current task + * priority is less than or equal the idle priority nothing happens a + * zero is returned + * + * Coverage + * @code{c} + * prvGetExpectedIdleTime(); + * + * if( uxTopReadyPriority > tskIDLE_PRIORITY ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * configUSE_TICKLESS_IDLE != 0 + * configUSE_PORT_OPTIMISED_TASK_SELECTION = 0 + */ +void test_coverage_prvGetExpectedIdleTime_top_ready_prio_gt_idle_prio_current_prio_lt_idle( void ) +{ + CEXCEPTION_T e = CEXCEPTION_NONE; + TCB_t xTCB = { 0 }; + + pxCurrentTCBs[ 0 ] = &xTCB; + + /* Test Setup */ + uxDeletedTasksWaitingCleanUp = 0; + xTCB.uxPriority = tskIDLE_PRIORITY; + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + + /* Test Expectations */ + vFakePortYield_Expect(); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); + + ulFakePortSetInterruptMask_ExpectAndReturn( 0 ); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortClearInterruptMask_Expect( 0 ); + + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 1 ); + listCURRENT_LIST_LENGTH_ExpectAndThrow( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ), + EXIT_LOOP ); + + + /* API Call */ + portTASK_FUNCTION( prvIdleTask, args ); + + Try + { + prvIdleTask( NULL ); + } + Catch( e ) + { + if( e == EXIT_LOOP ) + { + TEST_PASS(); + } + else + { + TEST_FAIL(); + } + } + /* Test Verifications */ + + /* this function (vPortSuppressTicksAndSleep_Expect) not being called is + * the aim of this test, it proves that the + * task did not go to sleep, technically nothing happens */ +} + +/** + * @brief This test ensures that when we call prvCreateIdleTasks with and idle + * name that is just as long as configMAX_TASK_NAME_LEN + * no core id number is added at the end + * + * Coverage + * @code{c} + * prvCreateIdleTasks(); + * + * if( x < configMAX_TASK_NAME_LEN ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_coverage_prvCreateIdleTasks_name_within_max_len( void ) +{ + BaseType_t prvCreateIdleTasks( void ); + + TCB_t * xIdleTask; + TCB_t xTask = { 0 }; + int i; + + pcIdleTaskName = "IDLE longXX"; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + pxCurrentTCBs[ i ] = &xTask; + } + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + /* prvInitialiseNewTask */ + vListInitialiseItem_ExpectAnyArgs(); + vListInitialiseItem_ExpectAnyArgs(); + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + pxPortInitialiseStack_ExpectAnyArgsAndReturn( NULL ); + + vFakePortEnterCriticalSection_Expect(); + listINSERT_END_ExpectAnyArgs(); + portSetupTCB_CB_ExpectAnyArgs(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortExitCriticalSection_Expect(); + } + + /* API Call */ + prvCreateIdleTasks(); + + /* Test Verifications */ + xIdleTask = ( TCB_t * ) xIdleTaskHandles[ 0 ]; + TEST_ASSERT_EQUAL_STRING( configIDLE_TASK_NAME, xIdleTask->pcTaskName ); + + /* Clean up idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vPortFreeStack( xIdleTaskHandles[ i ]->pxStack ); + vPortFree( xIdleTaskHandles[ i ] ); + xIdleTaskHandles[ i ] = NULL; + } +} + +/** + * @brief This test ensures that when we call prvCreateIdleTasks with and idle + * name that is longer than configMAX_TASK_NAME_LEN the name is + * truncated to configMAX_TASK_NAME_LEN + * + * Coverage + * @code{c} + * prvCreateIdleTasks(); + * + * if( x < configMAX_TASK_NAME_LEN ) + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + */ +void test_coverage_prvCreateIdleTasks_name_too_long( void ) +{ + BaseType_t prvCreateIdleTasks( void ); + + TCB_t xTask = { 0 }; + TCB_t * xIdleTask; + int i; + + pcIdleTaskName = "IDLE long name"; + + uxCurrentNumberOfTasks = 2; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + pxCurrentTCBs[ i ] = &xTask; + } + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + /* prvInitialiseNewTask */ + vListInitialiseItem_ExpectAnyArgs(); + vListInitialiseItem_ExpectAnyArgs(); + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + pxPortInitialiseStack_ExpectAnyArgsAndReturn( NULL ); + vFakePortEnterCriticalSection_Expect(); + listINSERT_END_ExpectAnyArgs(); + portSetupTCB_CB_ExpectAnyArgs(); + vFakePortGetCoreID_ExpectAndReturn( 0 ); + vFakePortExitCriticalSection_Expect(); + } + + prvCreateIdleTasks(); + + xIdleTask = ( TCB_t * ) xIdleTaskHandles[ 0 ]; + + /* Test Verifications */ + TEST_ASSERT_EQUAL_STRING_LEN( configIDLE_TASK_NAME, + xIdleTask->pcTaskName, + configMAX_TASK_NAME_LEN - 1 ); + + /* Clean up idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vPortFreeStack( xIdleTaskHandles[ i ]->pxStack ); + vPortFree( xIdleTaskHandles[ i ] ); + xIdleTaskHandles[ i ] = NULL; + } +} + + +/** + * @brief This test ensures that if the scheduler is not running, and the + * scheduler is suspended, taskSCHEDULER_SUSPENDED is returned + * + * Coverage + * @code{c} + * xTaskGetSchedulerState(); + * + * taskENTER_CRITICAL(); + * taskEXIT_CRITICAL(); + * + * @endcode + * + * configNUMBER_OF_CORES > 1 + * INCLUDE_xTaskGetSchedulerState = 1 + * configUSE_TIMERS = 1 + */ +void test_coverage_xTaskGetSchedulerState_scheduler_not_running_and_suspended( void ) +{ + BaseType_t xRet; + + xSchedulerRunning = pdTRUE; + uxSchedulerSuspended = pdTRUE; + + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + xRet = xTaskGetSchedulerState(); + + TEST_ASSERT_EQUAL( taskSCHEDULER_SUSPENDED, xRet ); +} diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/list_macros.h b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/list_macros.h new file mode 100644 index 000000000..edfebdd19 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/list_macros.h @@ -0,0 +1,74 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef LIST_MACRO_H +#define LIST_MACRO_H + +#include +#include +#include +#include + +struct tskTaskControlBlock; + +#undef listLIST_IS_EMPTY +BaseType_t listLIST_IS_EMPTY( const List_t * pxList ); + +#undef listGET_OWNER_OF_HEAD_ENTRY +struct tskTaskControlBlock * listGET_OWNER_OF_HEAD_ENTRY( const List_t * pxList ); + +#undef listIS_CONTAINED_WITHIN +BaseType_t listIS_CONTAINED_WITHIN( List_t * list, + const ListItem_t * listItem ); + +#undef listGET_LIST_ITEM_VALUE +TickType_t listGET_LIST_ITEM_VALUE( ListItem_t * listItem ); + +#undef listSET_LIST_ITEM_VALUE +void listSET_LIST_ITEM_VALUE( ListItem_t * listItem, + TickType_t itemValue ); + + +#undef listLIST_ITEM_CONTAINER +List_t * listLIST_ITEM_CONTAINER( const ListItem_t * listItem ); + +#undef listCURRENT_LIST_LENGTH +UBaseType_t listCURRENT_LIST_LENGTH( List_t * list ); + +#undef listGET_ITEM_VALUE_OF_HEAD_ENTRY +TickType_t listGET_ITEM_VALUE_OF_HEAD_ENTRY( List_t * list ); + +#undef listGET_LIST_ITEM_OWNER +struct tskTaskControlBlock * listGET_LIST_ITEM_OWNER( ListItem_t * listItem ); + +#undef listINSERT_END +void listINSERT_END( List_t * pxList, + ListItem_t * listItem ); + +#undef listREMOVE_ITEM +void listREMOVE_ITEM( ListItem_t * listItem ); + +#endif /* ifndef LIST_MACRO_H */ diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/local_portable.h b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/local_portable.h new file mode 100644 index 000000000..40592483e --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice_mock/local_portable.h @@ -0,0 +1,37 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef LOCAL_PORTABLE_H +#define LOCAL_PORTABLE_H + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ); + +BaseType_t xPortStartScheduler( void ); + +void vPortEndScheduler( void ); +#endif /* LOCAL_PORTABLE_H */ diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/FreeRTOSConfig.h new file mode 100644 index 000000000..48d35be79 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/FreeRTOSConfig.h @@ -0,0 +1,156 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* https://www.FreeRTOS.org/a00110.html +*----------------------------------------------------------*/ + +/* SMP test specific configuration */ +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configNUMBER_OF_CORES 16 +#define configUSE_CORE_AFFINITY 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_TASK_PREEMPTION_DISABLE 1 +#define configTICK_CORE 0 + +/* OS Configuration */ +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 +#define portREMOVE_STATIC_QUALIFIER 1 +#define portCRITICAL_NESTING_IN_TCB 1 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_PASSIVE_IDLE_HOOK 0 +#define configKERNEL_PROVIDED_STATIC_MEMORY 1 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configENABLE_MPU 0 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +#define configASSERT( x ) \ + do \ + { \ + if( x ) \ + { \ + vFakeAssert( true, __FILE__, __LINE__ ); \ + } \ + else \ + { \ + vFakeAssert( false, __FILE__, __LINE__ ); \ + } \ + } while( 0 ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) + extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); + #define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer ) +#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/Makefile b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/Makefile new file mode 100644 index 000000000..934cd2bbe --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/Makefile @@ -0,0 +1,47 @@ +# indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC := tasks.c + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +PROJECT_DEPS_SRC := list.c queue.c + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS := FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := multiple_priorities_timeslice_utest.c covg_multiple_priorities_timeslice_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +SUITE_SUPPORT_SRC := smp_utest_common.c + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_port.h + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS += + +# List any addiitonal flags needed by the compiler +CFLAGS += + +# Try not to edit beyond this line unless necessary. + +# Project is determined based on path: $(UT_ROOT_DIR)/$(PROJECT) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +# Make variables available to included makefile +export + +include ../../testdir.mk + + diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/covg_multiple_priorities_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/covg_multiple_priorities_timeslice_utest.c new file mode 100644 index 000000000..5b6d9878c --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/covg_multiple_priorities_timeslice_utest.c @@ -0,0 +1,405 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file covg_multiple_priority_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +/* =========================== EXTERN VARIABLES =========================== */ +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile TCB_t * pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern UBaseType_t uxTopReadyPriority; +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; +extern List_t xDelayedTaskList1; +extern List_t * pxDelayedTaskList; +extern UBaseType_t uxSchedulerSuspended; +extern BaseType_t xTickCount; +extern BaseType_t xNextTaskUnblockTime; +extern BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; + +/* =========================== EXTERN FUNCTIONS =========================== */ +extern void prvIdleTask( void ); +extern void prvPassiveIdleTask( void ); +extern BaseType_t xTaskIncrementTick( void ); + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief xTaskIncrementTick - no equal priority task for time slice. + * + * No equal priority ready task when incrementing tick. Verify that the return value + * indicates switching is not required. + * + * Coverage + * @code{c} + * for( x = ( ( UBaseType_t ) 0 ); x < ( ( UBaseType_t ) configNUMBER_OF_CORES ); x++ ) + * { + * if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ x ]->uxPriority ] ) ) > ( UBaseType_t ) 1 ) + * { + * xYieldRequiredForCore[ x ] = pdTRUE; + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * } + * @endcode + * ( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ x ]->uxPriority ] ) ) > ( UBaseType_t ) 1 ) is false. + */ +void test_coverage_xTaskIncrementTick_no_eq_priority_task( void ) +{ + BaseType_t xReturn; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + TCB_t xTaskTCB = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxSchedulerSuspended = pdFALSE; + xTickCount = 0; + xNextTaskUnblockTime = 0; + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create one more higher priority task to run on core 0. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxPriority = tskIDLE_PRIORITY + 1; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xTaskRunState = 0; + xTaskTCB.xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ]; + xTaskTCB.uxTaskAttributes = 0; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCB.xStateListItem ); + + /* API calls. */ + xReturn = xTaskIncrementTick(); + + /* Validations. */ + + /* Core 0 is running a higher priority task. No other task of equal priority is + * waiting to run. Switching is not required in this test. */ + TEST_ASSERT_EQUAL( pdFALSE, xReturn ); + TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); +} + +/** + * @brief xTaskIncrementTick - current core has yield pending. + * + * No equal priority ready task when incrementing tick. However, the current core + * has yield pending. Verify that the return value indicates switching is required. + * + * Coverage + * @code{c} + * if( ( xYieldRequiredForCore[ x ] != pdFALSE ) || ( xYieldPendings[ x ] != pdFALSE ) ) + * { + * if( x == ( UBaseType_t ) xCoreID ) + * { + * xSwitchRequired = pdTRUE; + * } + * else + * { + * prvYieldCore( x ); + * } + * } + * @endcode + * ( xYieldRequiredForCore[ x ] != pdFALSE ) is false. + * ( xYieldPendings[ x ] != pdFALSE ) is true. + * ( x == ( UBaseType_t ) xCoreID ) is true. + */ +void test_coverage_xTaskIncrementTick_no_eq_priority_task_yield_pending( void ) +{ + BaseType_t xReturn; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + TCB_t xTaskTCB = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxSchedulerSuspended = pdFALSE; + xTickCount = 0; + xNextTaskUnblockTime = 0; + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create one more higher priority task to run on core 0. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxPriority = tskIDLE_PRIORITY + 1; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xYieldPendings[ 0 ] = pdTRUE; + xTaskTCB.xTaskRunState = 0; + xTaskTCB.xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ]; + xTaskTCB.uxTaskAttributes = 0; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCB.xStateListItem ); + + /* API calls. */ + xReturn = xTaskIncrementTick(); + + /* Validations. */ + + /* Core 0 is running a higher priority task. No other task of equal priority is + * waiting to run. However, core 0 has yield pending. Switching is required for + * core 0. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); +} + +/** + * @brief xTaskIncrementTick - task with preemption disabled. + * + * The running task has preemption disabled. Verify the return value indicates switching + * is not required. + * + * Coverage + * @code{c} + * for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configNUMBER_OF_CORES; x++ ) + * { + * #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + * if( pxCurrentTCBs[ x ]->xPreemptionDisable == pdFALSE ) + * #endif + * { + * .... + * } + * ... + * } + * @endcode + * ( pxCurrentTCBs[ x ]->xPreemptionDisable == pdFALSE ) is false. + */ +void test_coverage_xTaskIncrementTick_preemption_disabled_task( void ) +{ + BaseType_t xReturn; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + TCB_t xTaskTCB = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY; + uxSchedulerSuspended = pdFALSE; + xTickCount = 0; + xNextTaskUnblockTime = 0; + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create one more task with preemption disabled to run on core 0. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + xTaskTCB.uxPriority = tskIDLE_PRIORITY; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.xTaskRunState = 0; + xTaskTCB.xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCB.uxTaskAttributes = 0; + xTaskTCB.xPreemptionDisable = pdTRUE; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCB.xStateListItem ); + + /* API calls. */ + xReturn = xTaskIncrementTick(); + + /* Validations. */ + + /* Equal priority task is waiting to run. Preemption is disabled for task running + * on core 0. Switching is not required in this test. */ + TEST_ASSERT_EQUAL( pdFALSE, xReturn ); + TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); +} + +/** + * @brief xTaskIncrementTick - ready higher priority delayed task. + * + * Verify that the core is yielding when ready a higher priority delayed ready task. + * + * Coverage + * @code{c} + * prvAddTaskToReadyList( pxTCB ); + * ... + * #if ( configUSE_PREEMPTION == 1 ) + * { + * ... + * #if ( configNUMBER_OF_CORES == 1 ) + * { + * ... + * } + * #else + * { + * prvYieldForTask( pxTCB ); + * } + * #endif + * } + * #endif + * @endcode + * prvYieldForTask( pxTCB ) is covered. + */ +void test_coverage_xTaskIncrementTick_ready_higher_priority_delayed_task( void ) +{ + BaseType_t xReturn; + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + TCB_t xTaskTCB = { NULL }; + List_t xEventList = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + vListInitialise( &xEventList ); + uxTopReadyPriority = tskIDLE_PRIORITY; + uxSchedulerSuspended = pdFALSE; + xTickCount = 0; + xNextTaskUnblockTime = 0; + vListInitialise( &xDelayedTaskList1 ); + pxDelayedTaskList = &xDelayedTaskList1; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create one more higher priority task to run on core 0. */ + xTaskTCB.uxPriority = tskIDLE_PRIORITY + 1; + xTaskTCB.xStateListItem.pvOwner = &xTaskTCB; + xTaskTCB.uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + xTaskTCB.xTaskRunState = 0; + xTaskTCB.xStateListItem.pxContainer = pxDelayedTaskList; + xTaskTCB.uxTaskAttributes = 0; + xTaskTCB.xPreemptionDisable = pdTRUE; + listINSERT_END( pxDelayedTaskList, &xTaskTCB.xStateListItem ); + xTaskTCB.xEventListItem.pvOwner = &xTaskTCB; + xTaskTCB.xEventListItem.pxContainer = &xEventList; + listINSERT_END( &xEventList, &xTaskTCB.xEventListItem ); + + /* API calls. */ + xReturn = xTaskIncrementTick(); + + /* Validations. */ + /* Core 0 is running a idle priority task. Switching is required in this test. */ + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); + + /* The implementation will select the last core to yield for the higher priority + * task. Verify that the task running on the last core has state taskTASK_YIELDING. */ + TEST_ASSERT_EQUAL( taskTASK_YIELDING, xTaskTCBs[ configNUMBER_OF_CORES - 1 ].xTaskRunState ); + TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); +} diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/multiple_priorities_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/multiple_priorities_timeslice_utest.c new file mode 100644 index 000000000..cf1ff8e62 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_timeslice/multiple_priorities_timeslice_utest.c @@ -0,0 +1,1503 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file multiple_priorities_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +/* =========================== EXTERN VARIABLES =========================== */ + +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================= HELPER FUNCTIONS ========================= */ +void vApplicationPassiveIdleHook( void ) +{ + /* Adding this function to pass compilation. */ +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-89 + * A task of equal priority will be created for each available CPU core. An + * additional task will be created in the ready state. This test will verify + * that as OS ticks are generated the ready task will be made to run on each + * CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + */ +void test_timeslice_verification_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES + 1 tasks of equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Generate a tick for each configNUMBER_OF_CORES. This will cause each + * task to be either moved to the ready state or the running state */ + for( i = 0; i <= configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + if( i < configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + else + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-90 + * A task of equal priority will be created for each available CPU core + * except for one. This will leave a CPU core running the idle task. This test + * will verify that as OS ticks are generated the tasks will remain on the same + * CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN - 1) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN - 1) + * Priority – 1 + * State - Running (Core N - 1) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN - 1) + * Priority – 1 + * State - Running (Core N - 1) + */ +void test_timeslice_verification_idle_core( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create ( configNUMBER_OF_CORES - 1 ) tasks of equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state prior to incrementing a tick */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the idle task is running on the last CPU Core */ + verifyIdleTask( 0, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES - 1; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-91 + * A high priority task will be created for each available CPU core. An + * additional low priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all CPU cores will remain running + * their original tasks and the ready task never enters the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_timeslice_verification_different_priority_tasks( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + /* The low priority task should never enter the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-103 + * A low priority task will be created for each available CPU core. An additional + * High priority task will be created in the ready state. This test will verify that + * as OS ticks are generated the high priority task remains running. The low priority + * tasks rotate on cores. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 1 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 Priority – 1 + * State - Running State - Running State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. The high priority task + * remains running. The low priority tasks rotate on cores. + */ +void test_timeslice_verification_low_priority_tasks_rotate( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create 1 task with high priority. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create configNUMBER_OF_CORES tasks of low priority */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state except TN+1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Verify low priority tasks rotate on cores each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + if( ( i + 1 ) == configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } + else + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i + 1 ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-104 + * A high priority task will be created for each available CPU core. An + * additional low priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all CPU cores will remain running + * their original tasks and the ready task never enters the running state. The + * test will then increase the priority of the ready task and verify tasks now + * begin to run on each CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * Raise the priority of task TN + 1 and verify on each tick it executes on a + * different CPU core + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + */ +void test_priority_change_tasks_different_priority_raise_to_equal( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + /* The low priority task should never enter the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } + + /* Raise the priority of the low priority task to match the running tasks */ + vTaskPrioritySet( xTaskHandles[ configNUMBER_OF_CORES ], 2 ); + + /* After the first tick the ready task will be running on the first CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the the last task has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-93 + * A low priority task will be created for each available CPU core. This test will + * verify that as OS ticks are generated all CPU cores will remain running their original + * tasks. The test will then increase the priority of the first task and verify tasks + * remain running on original core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 1) State - Running (Core N) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 1) State - Running (Core N) + * + * Raise the priority of task T1 and verify on each tick the running state is not changed. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 1) State - Running (Core N) + */ +void test_priority_change_tasks_equal_priority_raise_to_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of low priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify all the tasks are still in the running state after system ticks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Raise the priority of the first task. */ + vTaskPrioritySet( xTaskHandles[ 0 ], 2 ); + + /* Verify all the tasks are still in the running state after system ticks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-105 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. The test will then lower the priority of the last task and verify + * tasks now remain running on a dedicated CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Lower the priority of task TN + 1 + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_priority_change_tasks_equal_priority_lower_ready_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Lower the priority of the last ready task. */ + vTaskPrioritySet( xTaskHandles[ configNUMBER_OF_CORES ], 1 ); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, ( j + configNUMBER_OF_CORES - 1 ) % configNUMBER_OF_CORES ); + } + + /* Verify the low priority task remains in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-94 + * A high priority task will be created for each available CPU core. This test will + * verify that as OS ticks are generated all tasks will execute on each CPU core. + * The test will then lower the priority of the last task and verify tasks now remain + * running on a dedicated CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Running (Core 1) State - Running (Core N) + * + * Lower the priority of task TN. + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Running (Core N) + */ +void test_priority_change_tasks_equal_priority_lower_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i, j; + + /* Create configNUMBER_OF_CORES tasks of equal priority. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify that all the tasks are in the running state after system ticks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Lower the priority of the last core. */ + vTaskPrioritySet( xTaskHandles[ configNUMBER_OF_CORES - 1 ], 1 ); + + /* Verify that all the tasks are still in the running state after system ticks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-95 + * A task will be created for each available CPU core. This test will verify that as + * OS ticks are generated all tasks will execute on a fixed CPU core. A new task + * will be created. The test will then verify tasks now execute on each + * available CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Create a new task + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + */ +void test_task_create_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Create a new task of equal priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify the last created task runs on each core or enters the ready state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* + * Verify the the last task has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted + */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-96 + * A high priority task will be created for each available CPU core. This test + * will verify that as OS ticks are generated all tasks will execute on a fixed + * CPU core. A new low priority task will be created. The test will then verify + * the tasks remain executing on the original CPU cores and do not rotate. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 2 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Create a new low priority task + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_task_create_tasks_lower_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Create a new low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-102 + * A low priority task will be created for each available CPU core. This test will + * verify that as OS ticks are generated all tasks will execute on a fixed CPU core. + * A new high priority task will be created. The test will then verify the new task + * is running and remain tasks rotate on cores. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running State - Running + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running State - Running + * + * Create a new high priority task + * + * Call xTaskIncrementTick() for each configured CPU core. The created task remains running. + * The other tasks rotate on cores. + * + * Task (T1) Task (TN) Task (TN+1) + * Priority – 1 Priority – 1 Priority – 2 + * State - Running State - Ready State - Running + */ +void test_task_create_tasks_higher_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + uint32_t j; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Create a new high priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify the created task is running on the last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i != ( configNUMBER_OF_CORES - 1 ) ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + else + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + } + + /* Verify the high priority task running on the last core. Other lower priority tasks + * rotate on cores. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify the lower priority tasks rotate. */ + if( i < ( configNUMBER_OF_CORES - 1 ) ) + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES - i - 2 ], eReady, -1 ); + } + else + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES - 1 ], eReady, -1 ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-97 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. A task will be deleted. The test will then verify the tasks remain + * executing on fixed CPU cores and do not rotate. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Delete the last created task + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 2 + * State - Running + */ +void test_task_delete_tasks_equal_priorities_delete_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Delete last task. + * Before ready list : [ 1(0), 2(1), ..., N(N-1), 0 ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1) ] + */ + vTaskDelete( xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, ( j + configNUMBER_OF_CORES - 1 ) % configNUMBER_OF_CORES ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-98 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. A task will be suspended. The test will then verify the tasks remain + * executing on fixed CPU cores and do not rotate. When the suspended task is + * resumed it will begin executing on each CPU core on each tick. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Suspend the last created task + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Resume the suspended task. The tasks will now rotate to each CPU on each tick. + */ +void test_task_suspend_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Suspend last task. + * Before ready list : [ 1(0), 2(1), ..., N(N-1), 0 ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1) ] + */ + vTaskSuspend( xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, ( j + configNUMBER_OF_CORES - 1 ) % configNUMBER_OF_CORES ); + } + } + + /* Resume suspended task. + * Before ready list : [ 1(0), 2(1), ..., 0(N-1) ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1), N ] + */ + vTaskResume( xTaskHandles[ configNUMBER_OF_CORES ] ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the the last task has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted + */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-99 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. A task will be blocked. The test will then verify the tasks remain + * executing on fixed CPU cores and do not rotate. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (0) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Block the task running on core 0, which is task 1. + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not + * change state. + * + * Task (TN) + * Priority – 2 + * State - Running + * + * After blocking the task, verify task 1 can be scheduled on each core. + */ +void test_task_block_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Block the first task on core 0, which is task 1. + * Before ready list : [ 0, 1(0), 2(1), ..., N(N-1) ] + * After ready list : [ 0(0), 2(1), ..., N(N-1) ] + */ + vTaskDelay( configNUMBER_OF_CORES + 1 ); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + if( j == 0 ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, 0 ); + } + else if( j == 1 ) + { + /* Task 1 is currently been blocked. */ + verifySmpTask( &xTaskHandles[ j ], eBlocked, -1 ); + } + else + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j - 1 ); + } + } + } + + /* After ( configNUMBER_OF_CORES + 1 ) ticks, the task 1 will be added back to + * the ready list. Verify that the task 1 can be scheduled on each core when + * xTaskIncrementTick is called. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* + * Verify the the task 1 has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted + */ + verifySmpTask( &xTaskHandles[ 1 ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-100 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created with affinity for the largest + * numbered CPU core. This test will verify that as OS ticks are generated the + * task with CPU affinity will either be in the ready state or running on the + * specified CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – Last CPU Core + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – Last CPU Core + * State - Running State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 3 + * 2 -1 + * 3 3 + * 4 -1 + * + */ +void test_task_affinity_verification( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task with core affinity for the last CPU core */ + xTaskCreateAffinitySet( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, ( 1 << ( configNUMBER_OF_CORES - 1 ) ), &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the task is either in the ready state or running on the last CPU core */ + int32_t core = ( i % 2 == 0 ) ? ( configNUMBER_OF_CORES - 1 ) : -1; + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], ( core == -1 ) ? eReady : eRunning, core ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-101 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. The test will then set the last task to have affinity for the last + * CPU core. The last task will only run on the last CPU core or be in the ready + * state. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – None + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – None + * State - Running State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Set affinity for the last task to the last CPU core. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – Last CPU Core + * State - Running State - Ready + * + * Verify the task only runs on the specified core or is in the ready state. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 -1 + * 2 3 + * 3 -1 + * 4 3 + */ +void test_task_affinity_set_affinity_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* After the first tick the ready task will be running on CPU core 1 */ + int32_t core = 1; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Set CPU core affinity on the last task for the last CPU core */ + vTaskCoreAffinitySet( xTaskHandles[ configNUMBER_OF_CORES ], 1 << ( configNUMBER_OF_CORES - 1 ) ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the task is either in the ready state or running on the last CPU core */ + core = ( i % 2 == 1 ) ? ( configNUMBER_OF_CORES - 1 ) : -1; + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], ( core == -1 ) ? eReady : eRunning, core ); + } +} diff --git a/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/FreeRTOSConfig.h new file mode 100644 index 000000000..b8ab8adf7 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/FreeRTOSConfig.h @@ -0,0 +1,155 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* https://www.FreeRTOS.org/a00110.html +*----------------------------------------------------------*/ + +/* SMP test specific configuration */ +#define configRUN_MULTIPLE_PRIORITIES 0 +#define configNUMBER_OF_CORES 16 +#define configUSE_CORE_AFFINITY 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_TASK_PREEMPTION_DISABLE 0 +#define configTICK_CORE 0 + +/* OS Configuration */ +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 +#define portREMOVE_STATIC_QUALIFIER 1 +#define portCRITICAL_NESTING_IN_TCB 1 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_PASSIVE_IDLE_HOOK 0 +#define configUSE_TICKLESS_IDLE 1 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configENABLE_MPU 0 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +#define configASSERT( x ) \ + do \ + { \ + if( x ) \ + { \ + vFakeAssert( true, __FILE__, __LINE__ ); \ + } \ + else \ + { \ + vFakeAssert( false, __FILE__, __LINE__ ); \ + } \ + } while( 0 ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) + extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); + #define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer ) +#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/Makefile b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/Makefile new file mode 100644 index 000000000..4eff3c3bb --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/Makefile @@ -0,0 +1,45 @@ +# indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC := tasks.c + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +PROJECT_DEPS_SRC := list.c queue.c + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS := FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := single_priority_no_timeslice_utest.c covg_single_priority_no_timeslice_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +SUITE_SUPPORT_SRC := smp_utest_common.c + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_port.h + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS += + +# List any addiitonal flags needed by the compiler +CFLAGS += + +# Try not to edit beyond this line unless necessary. + +# Project is determined based on path: $(UT_ROOT_DIR)/$(PROJECT) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +# Make variables available to included makefile +export + +include ../../testdir.mk diff --git a/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/covg_single_priority_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/covg_single_priority_no_timeslice_utest.c new file mode 100644 index 000000000..c571e408c --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/covg_single_priority_no_timeslice_utest.c @@ -0,0 +1,452 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file single_priority_no_timeslice_covg_utest */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +#define MAX_TASKS 3 + +/* =========================== EXTERN FUNCTIONS =========================== */ +extern void prvCheckForRunStateChange( void ); + +/* =========================== EXTERN VARIABLES =========================== */ +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile UBaseType_t uxSchedulerSuspended; +extern volatile TCB_t * pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern List_t xSuspendedTaskList; +extern List_t xPendingReadyList; +extern volatile UBaseType_t uxTopReadyPriority; +extern volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; +extern volatile TickType_t xNextTaskUnblockTime; +extern volatile TickType_t xTickCount; +extern TickType_t xPendedTicks; + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================== Helper functions for Test Cases ============================== */ +void created_task( void * arg ) +{ + while( 1 ) + { + vTaskDelay( 100 ); + } +} + +static void prvPortEnableInterruptsCb( int cmock_num_calls ) +{ + ( void ) cmock_num_calls; + + pxCurrentTCBs[ 0 ]->xTaskRunState = 0; +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief prvCheckForRunStateChange - first time enter critical section. + * + * Check for run state when entering the critical section for the first time. Verify + * that the task is of running state when exiting this function. + * + * Coverage + * @code{c} + * if( uxPrevCriticalNesting == 0U ) + * { + * configASSERT( uxPrevSchedulerSuspended != ( UBaseType_t ) pdFALSE ); + * portRELEASE_ISR_LOCK(); + * } + * @endcode + * ( uxPrevCriticalNesting == 0U ) is false. + */ +void test_coverage_prvCheckForRunStateChange_first_time_critical_section( void ) +{ + TCB_t xTaskTCB = { NULL }; + + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.uxCriticalNesting = 1; + xTaskTCB.xTaskRunState = taskTASK_YIELDING; + uxSchedulerSuspended = 0; + + /* Clear callback in commonSetUp. */ + vFakePortCheckIfInISR_StopIgnore(); + vFakePortEnableInterrupts_StopIgnore(); + vFakePortGetISRLock_StubWithCallback( NULL ); + vFakePortGetTaskLock_StubWithCallback( NULL ); + vFakePortReleaseISRLock_StubWithCallback( NULL ); + vFakePortReleaseTaskLock_StubWithCallback( NULL ); + + /* Expection. */ + vFakePortEnableInterrupts_StubWithCallback( prvPortEnableInterruptsCb ); + + vFakePortReleaseISRLock_Expect(); + vFakePortReleaseTaskLock_Expect(); + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + + /* API Call. */ + prvCheckForRunStateChange(); + + /* Validation. */ + /* Critical nesting count is set correctly. */ + TEST_ASSERT_EQUAL( 1, xTaskTCB.uxCriticalNesting ); + /* Task is of running state now. */ + TEST_ASSERT_EQUAL( 0, xTaskTCB.xTaskRunState ); +} + +/** + * @brief prvCheckForRunStateChange - first time suspend scheduler. + * + * Check for run state when suspending the scheduler for the first time. Verify + * that the task is of running state when exiting this function. + * + * Coverage + * @code{c} + * if( uxPrevCriticalNesting == 0U ) + * { + * configASSERT( uxPrevSchedulerSuspended != ( UBaseType_t ) pdFALSE ); + * portRELEASE_ISR_LOCK(); + * } + * @endcode + * ( uxPrevCriticalNesting == 0U ) is true. + */ +void test_coverage_prvCheckForRunStateChange_first_time_suspend_scheduler( void ) +{ + TCB_t xTaskTCB = { NULL }; + + pxCurrentTCBs[ 0 ] = &xTaskTCB; + xTaskTCB.uxCriticalNesting = 0; + xTaskTCB.xTaskRunState = taskTASK_YIELDING; + uxSchedulerSuspended = 0; + + /* Clear callback in commonSetUp. */ + vFakePortCheckIfInISR_StopIgnore(); + vFakePortEnableInterrupts_StopIgnore(); + vFakePortGetTaskLock_StubWithCallback( NULL ); + vFakePortReleaseTaskLock_StubWithCallback( NULL ); + + /* Expection. */ + vFakePortEnableInterrupts_StubWithCallback( prvPortEnableInterruptsCb ); + + vFakePortReleaseTaskLock_Expect(); + vFakePortGetTaskLock_Expect(); + vFakePortGetISRLock_Expect(); + vFakePortReleaseISRLock_Expect(); + + /* API Call. */ + prvCheckForRunStateChange(); + + /* Validation. */ + /* Critical nesting count is set correctly. */ + TEST_ASSERT_EQUAL( 0, uxSchedulerSuspended ); + /* Task is of running state now. */ + TEST_ASSERT_EQUAL( 0, xTaskTCB.xTaskRunState ); +} + +/* + * The kernel will be configured as follows: + #define configNUMBER_OF_CORES (N > 1) + #define configUSE_CORE_AFFINITY 1 + * Coverage for + * static TickType_t prvGetExpectedIdleTime( void ) + */ + +/* + * Coverage for: UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + * const UBaseType_t uxArraySize, + * configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) + */ +void test_task_get_system_state( void ) +{ + TaskStatus_t * tsk_status_array; + TaskHandle_t created_handles[ 3 ]; + + tsk_status_array = calloc( MAX_TASKS, sizeof( TaskStatus_t ) ); + + for( int i = 0; i < 3; i++ ) + { + xTaskCreate( created_task, "Created Task", configMINIMAL_STACK_SIZE, NULL, 1, &created_handles[ i ] ); + } + + /*Get System states */ + int no_of_tasks = uxTaskGetSystemState( tsk_status_array, MAX_TASKS, NULL ); + TEST_ASSERT( ( no_of_tasks > 0 ) && ( no_of_tasks <= MAX_TASKS ) ); +} + +/* + * Coverage for: UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + * const UBaseType_t uxArraySize, + * configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) + */ +void test_task_get_system_state_custom_time( void ) +{ + TaskStatus_t * tsk_status_array; + TaskHandle_t created_handles[ 3 ]; + uint32_t ulTotalRunTime = ( uint32_t ) 200; /* Custom time value */ + + tsk_status_array = calloc( MAX_TASKS, sizeof( TaskStatus_t ) ); + + for( int i = 0; i < 3; i++ ) + { + xTaskCreate( created_task, "Created Task", configMINIMAL_STACK_SIZE, NULL, 1, &created_handles[ i ] ); + } + + /*Get System states */ + int no_of_tasks = uxTaskGetSystemState( tsk_status_array, MAX_TASKS, &ulTotalRunTime ); + TEST_ASSERT( ( no_of_tasks > 0 ) && ( no_of_tasks <= MAX_TASKS ) ); +} + +/* + * Coverage for: UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + * const UBaseType_t uxArraySize, + * configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) + */ +void test_task_get_system_state_unavilable_task_space( void ) +{ + TaskStatus_t * tsk_status_array; + TaskHandle_t created_handles[ 3 ]; + + tsk_status_array = calloc( MAX_TASKS, sizeof( TaskStatus_t ) ); + + for( int i = 0; i < 3; i++ ) + { + xTaskCreate( created_task, "Created Task", configMINIMAL_STACK_SIZE, NULL, 1, &created_handles[ i ] ); + } + + /*Get System states */ + int no_of_tasks = uxTaskGetSystemState( tsk_status_array, MAX_TASKS - 1, NULL ); + TEST_ASSERT( ( no_of_tasks == 0 ) && ( no_of_tasks <= MAX_TASKS ) ); +} + +/** + * @brief vTaskStepTick - step ticks to next task unblock time. + * + * Step ticks to next task unblock time to increase xPendedTicks. Verify that xTickCount + * and xPendedTicks are increased accordingly. + * + * Coverage + * @code{c} + * if( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime ) + * { + * ... + * taskENTER_CRITICAL(); + * { + * xPendedTicks++; + * } + * taskEXIT_CRITICAL(); + * xTicksToJump--; + * } + * @endcode + * ( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime ) is true. + */ +void test_coverage_vTaskStepTick_eq_task_unblock_time( void ) +{ + TickType_t xTicksToJump; + + /* Setup the variables and structure. */ + xPendedTicks = 0; + xTickCount = 10; + xTicksToJump = 10; + uxSchedulerSuspended = pdTRUE; + + xNextTaskUnblockTime = 20; + + /* Clear callback in commonSetUp. */ + vFakePortEnterCriticalSection_StubWithCallback( NULL ); + vFakePortExitCriticalSection_StubWithCallback( NULL ); + + /* Expections. */ + vFakePortEnterCriticalSection_Expect(); + vFakePortExitCriticalSection_Expect(); + + /* API call. */ + vTaskStepTick( xTicksToJump ); + + /* Validations. */ + /* xTickCount is set to one tick before xNextUnblockTime. */ + TEST_ASSERT_EQUAL( 19, xTickCount ); + /* xPendedTicks is increased. */ + TEST_ASSERT_EQUAL( 1, xPendedTicks ); +} + +/** + * @brief xTaskResumeFromISR - resume higher priority suspended task + * + * This test resume a higher priority task from ISR when scheduler suspended. The + * return value of xTaskResumeFromISR indicates yield required for the core calling + * this API. + * + * Coverage + * @code{c} + * #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) + * { + * xYieldRequired = pdTRUE; + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) is true. + */ +void test_coverage_xTaskResumeFromISR_resume_higher_priority_suspended_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1U ] = { NULL }; + uint32_t i; + BaseType_t xReturn; + + /* Setup the variables and structure. */ + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xPendingReadyList ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = 1; + xTaskTCBs[ i ].xTaskRunState = i; + xYieldPendings[ i ] = pdFALSE; + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* A suspended task is created to be resumed from ISR. The task has higher priority + * than uxTopReadyPriority and the scheduler is suspended. The task will be added + * to xPendingReadyList after resumed from ISR. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority = 2; + listINSERT_END( &xSuspendedTaskList, &xTaskTCBs[ i ].xStateListItem ); + uxTopReadyPriority = 1; + uxSchedulerSuspended = pdTRUE; + + /* Expections. */ + vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + + /* API calls. */ + xReturn = xTaskResumeFromISR( &xTaskTCBs[ i ] ); + + /* Validations. In single priority test, the calling core is requested to yield + * since a higher priority task is resumed. */ + TEST_ASSERT( xReturn == pdTRUE ); +} + +/** + * @brief xTaskResumeFromISR - resume lower priority suspended task + * + * This test resume a lower priority task from ISR when scheduler suspended. The + * return value of xTaskResumeFromISR indicates yield not required for the core + * calling this API. + * + * Coverage + * @code{c} + * #if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PREEMPTION == 1 ) ) + * { + * prvYieldForTask( pxTCB ); + * + * if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) + * { + * xYieldRequired = pdTRUE; + * } + * } + * #endif + * @endcode + * ( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) is false. + */ +void test_coverage_xTaskResumeFromISR_resume_lower_priority_suspended_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1U ] = { NULL }; + uint32_t i; + BaseType_t xReturn; + + /* Setup the variables and structure. */ + vListInitialise( &xSuspendedTaskList ); + vListInitialise( &xPendingReadyList ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = 2; + xTaskTCBs[ i ].xTaskRunState = i; + xYieldPendings[ i ] = pdFALSE; + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* A suspended task is created to be resumed from ISR. The task has lower priority + * than uxTopReadyPriority and the scheduler is suspended. The task will be added + * to xPendingReadyList after resumed from ISR. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority = 1; + listINSERT_END( &xSuspendedTaskList, &xTaskTCBs[ i ].xStateListItem ); + uxTopReadyPriority = 2; + uxSchedulerSuspended = pdTRUE; + + /* Expections. */ + vFakePortAssertIfInterruptPriorityInvalid_Ignore(); + + /* API calls. */ + xReturn = xTaskResumeFromISR( &xTaskTCBs[ i ] ); + + /* Validations. In single priority test, the calling core is not requested to yield + * since a lower priority task is resumed. */ + TEST_ASSERT( xReturn == pdFALSE ); +} diff --git a/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c new file mode 100644 index 000000000..1b31bd06e --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c @@ -0,0 +1,2612 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file single_priority_no_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +/* =========================== EXTERN VARIABLES =========================== */ + +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-1 + * The purpose of this test is to verify when multiple CPU cores are available and + * the FreeRTOS kernel is configured as (configRUN_MULTIPLE_PRIORITIES = 0) that tasks + * of equal priority will execute simultaneously. The kernel will be configured as follows: + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority –1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_verification_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-2 + * The purpose of this test is to verify when multiple CPU cores are available and + * the FreeRTOS kernel is configured as (configRUN_MULTIPLE_PRIORITIES = 0) that + * tasks of different priorities will not execute simultaneously. The kernel will be + * configured as follows: + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * One high priority task will be created. N low priority tasks will be created + * per remaining CPU cores. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + */ +void test_priority_verification_tasks_different_priorities( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-3 + * A task of equal priority will be created for each available CPU core. + * This test will verify that when the priority of one task is lowered the + * task is no longer running. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Running (Core 0) State - Running (Core N) + * + * After calling vTaskPrioritySet() and lowering the priority of task T1 + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 2 + * State - Ready State - Running (Core N) + */ +void test_priority_change_tasks_equal_priority_lower( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks of equal priority for all available CPU cores */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Lower the priority of task T0 */ + vTaskPrioritySet( xTaskHandles[ 0 ], 1 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify T0 is the the ready state */ + verifySmpTask( &xTaskHandles[ 0 ], eReady, -1 ); + + /* Verify the idle task is now running on CPU core 0 */ + verifyIdleTask( 0, 0 ); + + /* Verify all other tasks remain in the running state on the same CPU cores */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-4 + * A task of equal priority will be created for each available CPU core. + * This test will verify that when the priority of one task is raised it + * shall remain running and all other tasks will enter the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * After calling vTaskPrioritySet() and raising the priority of task T1 + * + * Task (T1) Task (T2) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + */ +void test_priority_change_tasks_equal_priority_raise( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create tasks of equal priority for all available CPU cores */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Raise the priority of task T0 */ + vTaskPrioritySet( xTaskHandles[ 0 ], 2 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 2, xTaskDetails.xHandle->uxPriority ); + + /* Verify T0 is the the running state */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-111 + * A task of priority higher than idle is created. The test verify that when the priority + * of the task is raised, running idle task won't be altered. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * A Task is created prior to starting the scheduler. + * + * Task (T1) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Idle task (1) Idle task (N) + * Priority – 1 Priority – idle Priority – idle + * State - Running (Core 1) State - Running (Core 2) State - ready + * + * After calling vTaskPrioritySet() and raising the priority of task T1 + * + * Task (T1) Idle task (1) Idle task (N) + * Priority – 2 Priority – idle Priority – idle + * State - Running (Core 0) State - Running (Core 1) State - ready + */ +void test_priority_change_task_high_priority_raise( void ) +{ + TaskHandle_t xTaskHandles[ 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create a task to run. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ 0 ] ); + + /* Start scheduler. */ + vTaskStartScheduler(); + + /* Verify the task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Raise the priority of the running task. */ + vTaskPrioritySet( xTaskHandles[ 0 ], 2 ); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 2, xTaskDetails.xHandle->uxPriority ); + + /* Verify the task is still in the running state */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify the idle task is still running on the same core. */ + verifyIdleTask( i - 1, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-5 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * only the high priority task is in the running state. Each low priority task + * will then be raised to high priority and enter the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * After calling vTaskPrioritySet() and raising the priority of tasks TN + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 2 + * State - Running (Core 0) State - Running (Core N) + */ +void test_priority_change_tasks_different_priority_raise( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Raise the priority of the task */ + vTaskPrioritySet( xTaskHandles[ i ], 2 ); + + /* Verify the priority has been raised */ + vTaskGetInfo( xTaskHandles[ i ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 2, xTaskDetails.xHandle->uxPriority ); + + /* Verify the task is now in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, configNUMBER_OF_CORES - i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-6 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * only the high priority task is in the running state. The high priority task + * shall be lowered. This will cause all low priority tasks to enter the running + * state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority –1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * After calling vTaskPrioritySet() and lowering the + * priority of all low priority tasks. + * + * Task (T1) Task (T2) Task (TN) + * Priority – 1 Priority – 1 Priority – 1 + * State - Running (Core N - 1) State - Running (Core 0) State - Running (Core N - 2) + */ +void test_priority_change_tasks_different_priority_lower( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Lower the priority of the high priority task to match all other tasks */ + vTaskPrioritySet( xTaskHandles[ 0 ], 1 ); /*After this returns task[0] is not running, task[1] is running on 0 */ + + /* Verify the priority has been lowered */ + vTaskGetInfo( xTaskHandles[ 0 ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the task remains running. */ + + /* When priority dropped in prvSelectHighestPriorityTask, all the idle cores + * will yield for context switch. The ready queue is a FIFO. Core 0 will choose + * The first task in the ready queue which is task 1. Task 0 will be selected + * by the last core which calls context switch. + * Core 0 choose xTaskHandles[1] + * Core 1 choose xTaskHandles[2] + * .... + * Core N-2 choose xTaskHandles[N-1] + * Core N-1 choose xTaskHandles[0] + */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, ( BaseType_t ) ( configNUMBER_OF_CORES - 1 ) ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( BaseType_t ) ( i - 1 ) ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-7 + * Tasks of equal priority will be created for N - 1 CPU cores. The remaining + * tasks will be idle. Once the scheduler is started a new task of equal + * priority shall be created. The test shall verify the new task is in the + * running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task N-1 + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task N-1 + * Priority – 1 + * State - Running (Core N) + * + * Create a new task with priority 1 + * + * Task N - 1 New Task + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Running (Last available core) + * + */ +void test_task_create_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining CPU core is running the idle task */ + verifyIdleTask( 0, i ); + + /* Create a new task of equal priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-8 + * Tasks of equal priority will be created for N - 1 CPU cores. The remaining + * task will be idle. Once the scheduler is started a new task of lower + * priority shall be created. The test shall verify the new task is in the + * ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task N-1 + * Priority – 2 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task N-1 + * Priority – 2 + * State - Running (Core N) + * + * Create a new task with priority 2 + * + * Task N - 1 New Task + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + */ +void test_task_create_tasks_lower_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining CPU core is running the idle task */ + verifyIdleTask( 0, i ); + + /* Create a new task of lower priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-9 + * Tasks of equal priority will be created for N - 1 CPU cores. The remaining + * task will be idle. Once the scheduler is started a new task of higher + * priority shall be created. The test shall verify the new task is in the + * running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task N-1 + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task N-1 + * Priority – 1 + * State - Running (Core N) + * + * Create a new task with priority 2 + * + * Task N - 1 New Task + * Priority – 1 Priority – 2 + * State - Ready State - Running (First available core) + * + */ +void test_task_create_tasks_higher_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i, xCoreToRunTask; + + /* Create all tasks at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* The task running status on each core after scheduler started: + * core 0 xTaskHandles[0] + * core 1 xTaskHandles[1] + * core 2 xTaskHandles[2] + * ..... + * core N - 2 xTaskHandles[N - 2] + * core N - 1 xIdleTaskHandles[0] + */ + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify remaining CPU core is running the idle task */ + verifyIdleTask( 0, i ); + + /* Create a new task of higher priority. prvYieldForTask will be called to yield + * for this task. Since all the core has lower priority than this task. These cores + * will be requested to yield. The task is choosen by the core yield order. + * This task is created on core 0. + * vTaskExitCritical does the following: + * 1. release the spinlock -> All the other cores yield + * 2. Check xYieldPendings for this core -> This core yields. + * core N-1 won't yield since it is already running the idle task. + * The core yields in the following order. + * core 1 choose The new task xTaskHandles[N-1] + * core 2 choose xIdleTaskHandles[1] + * ..... + * core N - 2 choose xIdleTaskHandles[N-3] + * core 0 choose xIdleTaskHandles[N-2] + */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state. The created task will increase the priority */ + xCoreToRunTask = 1; + + if( xCoreToRunTask == ( configNUMBER_OF_CORES - 1 ) ) + { + /* Core 1 is the last core ( configNUMBER_OF_CORES - 1 ), then it is already running + * idle task. The last core to choose task is core 0. */ + xCoreToRunTask = 0; + } + + verifySmpTask( &xTaskHandles[ i ], eRunning, xCoreToRunTask ); + + /* Verify all tasks are in the ready state */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Verify all the idle task running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i == xCoreToRunTask ) + { + /* This core is running the task. */ + } + else if( i == 0 ) + { + /* Core 0 choose the last. It chooses the configNUMBER_OF_CORES - 2 idle task. */ + verifyIdleTask( ( BaseType_t ) ( configNUMBER_OF_CORES - 2 ), i ); + } + else if( i == ( configNUMBER_OF_CORES - 1 ) ) + { + /* The last core won't yield, since it is running an idle task already. */ + verifyIdleTask( 0, i ); + } + else + { + verifyIdleTask( ( BaseType_t ) ( i - 1 ), i ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-10 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a new task of equal priority is created it will + * be in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Create a new task of equal priority + * + * Task (TN) New Task + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_task_create_all_cores_equal_priority_equal( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task of equal priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-11 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a new task of lower priority is created it will + * be in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 2 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Create a new task of lower priority + * + * Task (TN) New Task + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_task_create_all_cores_equal_priority_lower( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task of lower priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify all tasks remain in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-12 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a new task of higher priority is created it will + * be in the running state and all other tasks will now be in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Create a new task of higher priority + * + * Task (TN) New Task + * Priority – 1 Priority – 2 + * State - Ready State - Running ( First available core ) + */ +void test_task_create_all_cores_equal_priority_higher( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Create a new task of higher priority */ + + /* The created task has higher priority than other tasks. This will cause all + * the other cores yield. The task is choosen by core yield order which is accending + * in vYieldCores. Since core 0 create the task, it will yield last due to the mock + * implementation. + * core 1 choose xTaskHandles[N] + * core 2 choose xIdleTaskHandles[0] + * ... + * core N-1 choose xIdleTaskHandles[N-3] + * core 0 choose xIdleTaskHandles[N-2] + */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 1 ); + + /* Verify all tasks remain in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Verify all the idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i == 0 ) + { + verifyIdleTask( configNUMBER_OF_CORES - 2, i ); + } + else if( i == 1 ) + { + /* This core is running task. */ + } + else + { + verifyIdleTask( i - 2, i ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-13 + * A single task of high priority will be created. A low priority task will + * be created for each remaining available CPU core. This test will verify when + * a new task is created at priority equal to the running task it will be in + * the running state. The original low priority task will remain in the ready + * state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Create a new task at the same priority as task (T1) + * + * Task (T1) Task (TN) New Task + * Priority – 2 Priority – 1 Priority – 2 + * State - Running (Core 0) State - Ready State - Running (Last available core) + */ +void test_task_create_all_cores_different_priority_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Create a new task of high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + /* Verify the new task is in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks remain in the ready state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-14 + * A single task of high priority will be created. A low priority task will + * be created for each remaining available CPU core. This test will verify when + * a new task is created at low priority it will be in the ready state. The + * original low priority tasks will also remain in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Create a new task at the same priority as task (T1) + * + * Task (T1) Task (TN) New Task + * Priority – 2 Priority – 1 Priority – 1 + * State - Running (Core 0) State - Ready State - Ready + */ +void test_task_create_all_cores_different_priority_low( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Create a new task of high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Verify the new task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify all tasks remain in the ready state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-15 + * Tasks of equal priority shall be created for each available CPU core. + * This test will verify when a task is deleted the remaining tasks are still + * in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) + * + * Delete task (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Deleted State - Running (Core N) + */ +void test_task_delete_tasks_equal_priority_delete_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create all tasks at equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Delete task T0 */ + vTaskDelete( xTaskHandles[ 0 ] ); + + /* Verify a single task is pending deletion */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + + /* Verify task T0 is in the deleted state */ + verifySmpTask( &xTaskHandles[ 0 ], eDeleted, -1 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all remaining tasks are still running */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-16 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * only the high priority task is in the running state. Each low priority task + * will then be deleted. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Delete each low priority task + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Deleted + */ +void test_task_delete_tasks_different_priorities_delete_low( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ 1 ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Delete low priority task */ + vTaskDelete( xTaskHandles[ i ] ); + + /* Verify T0 remains running on core 0 */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify task T[i] is in the deleted state */ + verifySmpTask( &xTaskHandles[ i ], eDeleted, -1 ); + } + + /* Remains 0 since all deleted tasks were not running */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-17 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * only the high priority task is in the running state. The high priority task + * will then be deleted. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Delete the high priority task + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Deleted State - Running (Core 0) + */ +void test_task_delete_tasks_different_priorities_delete_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ 1 ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Verify no tasks are pending deletion */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Delete task T0 */ + vTaskDelete( xTaskHandles[ 0 ] ); + + /* Verify the task has been deleted */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + verifySmpTask( &xTaskHandles[ 0 ], eDeleted, -1 ); + + /* Verify all previous ready tasks are now running */ + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i - 1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-18 + * Tasks of equal priority shall be created for each available CPU core. + * One additional task shall be created while will be idle. This test will + * verify when a task is deleted the idle task will begin running. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 Priority - 1 + * State - Ready State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) Task (T2) + * Priority – 1 Priority – 1 Priority – 1 + * State - Running (Core 0) State - Running (Core N) State - Ready + * + * Delete task (T1) + * Task (T1) Task (TN) Task (T3) + * Priority – 1 Priority – 1 Priority – 1 + * State - Deleted State - Running (Core N) State - Running (Core 0) + */ +void test_task_delete_tasks_equal_priority_delete_running( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES + 1 tasks of equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify tasks are running and one task is ready */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify there are no deleted tasks pending cleanup */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Delete task 1 running on core 0 */ + vTaskDelete( xTaskHandles[ 0 ] ); + + /* Verify a deleted task is now pending cleanup */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + + /* Verify task T0 has been deleted */ + verifySmpTask( &xTaskHandles[ 0 ], eDeleted, -1 ); + + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + /* Verify all other tasks are in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The last task will be running on core 0 */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-19 + * A task of high priority will be created for each available CPU core. A low + * priority task will also be created and be in the ready state. This test + * will verify that when a high priority task is deleted the low priority task + * will remain in the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority - 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority - 1 + * State - Running (Core N) State - Ready + * + * Delete task (T0) + * + * Task (T0) Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 Priority – 1 + * State - Deleted State - Running (Core N) State - Ready + */ +void test_task_delete_all_cores_high_priority_delete_high_priority_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create tasks of high priority */ + for( i = 0; i < ( configNUMBER_OF_CORES ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task of low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify tasks are running and one task is ready */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify there are no deleted tasks pending cleanup */ + TEST_ASSERT_EQUAL( 0, uxDeletedTasksWaitingCleanUp ); + + /* Delete task running on core 0 */ + vTaskDelete( xTaskHandles[ 0 ] ); + + /* Verify a deleted task is now pending cleanup */ + TEST_ASSERT_EQUAL( 1, uxDeletedTasksWaitingCleanUp ); + + /* Verify task T0 has been deleted */ + verifySmpTask( &xTaskHandles[ 0 ], eDeleted, -1 ); + + /* Verify core 0 is now idle */ + verifyIdleTask( 0, 0 ); + + for( i = 1; i < ( configNUMBER_OF_CORES ); i++ ) + { + /* Verify all other tasks are in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The last task will remain in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-21 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a task is suspended the CPU core will execute + * the idle task. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – N + * State - Running (Core N) + * + * Suspend task (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Suspended State - Running (Core N) + * + * Resume task (T1) + * + * Task (TN) + * Priority – N + * State - Running (Core N) + */ +void test_task_suspend_all_cores_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Suspend task T0 */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the task has been suspended */ + verifySmpTask( &xTaskHandles[ 0 ], eSuspended, -1 ); + + /* Verify all other tasks are running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Resume task T0 */ + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-22 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * that when the high priority task is suspended the low priority tasks will + * enter the running state. When the high priority task is resumed, each low + * priority task will return to the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Suspend task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Suspended State - Running (Core N) + * + * Resume task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (First available core) State - Ready + */ +void test_task_suspend_all_cores_different_priority_suspend_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i, xCoreToRunTask; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + /* SMP cores start with idle task. Idle task will yield itself when first time it runs + * The task running status when the scheduler starts. + * Core 0 : xTaskHandles[0] with priority 2 + * Core 1 : xIdleTaskHandles[0] + * ... + * Core N-1 : xIdleTaskHandles[N-2] + */ + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* The task running status when xTaskHandles[0] suspend ifself on Core 0. + * 1. Core 0 will yield itself and call prvSelectHighestPriorityTask + * 2. In prvSelectHighestPriorityTask, the top running priority is dropped. + * All the other cores running the idle are requested to yield. The mock implementation + * assume that cores yield in ascending order. + * Core 0 will choose xTaskHandles[1] + * Core 1 will choose xTaskHandles[2] + * ... + * Core N-1 will choose xIdleTaskHandles[N-1] since it is the first idle task in ready queue. + */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the suspended task is not running. */ + verifySmpTask( &xTaskHandles[ 0 ], eSuspended, -1 ); + + /* Verify all other tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i - 1 ); + } + + /* Verify the last core will run the last idle task. */ + verifyIdleTask( ( configNUMBER_OF_CORES - 1 ), ( configNUMBER_OF_CORES - 1 ) ); + + /* xTaskHandles[0] is resumed from Core 0. + * 1. prvYieldForTask is called xTaskHandles[0] to find core to run. + * 2. The cores which is not running idle task and has lower priority than xTaskHandles[0] is request to yield. + * 3. The core 0 will yield last since it is the core to call the FreeRTOS APIs + * Core N-1 will not yield since it is already running xIdleTaskHandles[N-1] + * Other cores will yield in the following order: + * Tasks will be choosen then idle task in FIFO order + * Core 1 will choose xTaskHandles[0] + * Core 2 will choose xIdleTaskHandles[0] + * ... + * Core N-2 will choose xIdleTaskHandles[N-4] + * Core 0 will choose xIdleTaskHandles[N-3] + */ + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify the high priority task is running */ + xCoreToRunTask = 1; + + if( xCoreToRunTask == ( configNUMBER_OF_CORES - 1 ) ) + { + /* Core 1 is the last core. Since it is already running the idle task. It + * won't be request to yield. Core 0 will choose the task to run. */ + xCoreToRunTask = 0; + } + + verifySmpTask( &xTaskHandles[ 0 ], eRunning, xCoreToRunTask ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Verify the idle task running status. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i == xCoreToRunTask ) + { + /* The core is running task. */ + } + else if( i == 0 ) + { + verifyIdleTask( ( configNUMBER_OF_CORES - 3 ), i ); + } + else if( i == ( configNUMBER_OF_CORES - 1 ) ) + { + verifyIdleTask( ( configNUMBER_OF_CORES - 1 ), ( configNUMBER_OF_CORES - 1 ) ); + } + else + { + verifyIdleTask( ( ( configNUMBER_OF_CORES + i - 2 ) % configNUMBER_OF_CORES ), i ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-23 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. This test will verify that + * as each low priority task is suspended, the high priority task shall remain + * in the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Suspend tasks (TN) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Suspended + * + * Resume tasks (TN) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + */ +void test_task_suspend_all_cores_different_priority_suspend_low( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Suspend low priority task */ + vTaskSuspend( xTaskHandles[ i ] ); + + /* Verify T0 remains running on core 0 */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify task T[i] is in the deleted state */ + verifySmpTask( &xTaskHandles[ i ], eSuspended, -1 ); + } + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Resume low priority task */ + vTaskResume( xTaskHandles[ i ] ); + + /* Verify T0 remains running on core 0 */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify task T[i] is in the suspended state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-24 + * A single task of high priority will be created for each available CPU core. + * An additional low priority task shall be created. This test will verify that + * when a high priority task is suspended the low priority task will remain in + * the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Suspend tasks (T1) + * + * Task (T1) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Suspended State - Ready + * + * Resume tasks (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + */ +void test_task_suspend_all_cores_high_priority_suspend( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a task for each CPU core at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all high priority tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Suspend the high priority task */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the task is suspended */ + verifySmpTask( &xTaskHandles[ 0 ], eSuspended, -1 ); + + /* Verify the idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Verify all high priority tasks remain running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Resume the high priority task */ + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify all high priority tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-26 + * A task of equal priority will be created for each available CPU core. + * An additional task in the ready state shall be created. This test will + * verify that when a running task is suspended the ready task will move to + * the running state. When the suspended task is resumed, it shall enter the + * ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Ready + * + * Suspend tasks (T1) + * + * Task (T1) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Suspended State - Running (Core 0) + * + * Resume tasks (T1) + * + * Task (T1) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Ready State - Running (Core 0) + */ +void test_task_suspend_all_cores_equal_priority_suspend_running( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a task for each CPU core at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the remaining task is ready */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Suspend the task on core 0 */ + vTaskSuspend( xTaskHandles[ 0 ] ); + + /* Verify the last task is now running on core 0 */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); + + /* Resume the task on core 0 */ + vTaskResume( xTaskHandles[ 0 ] ); + + /* Verify task T0 is now in the ready state */ + verifySmpTask( &xTaskHandles[ 0 ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-27 + * A task of equal priority will be created for each available CPU core. This + * test will verify that when a task is blocked the CPU core will execute + * the idle task. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – N + * State - Running (Core N) + * + * Block task (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Blocked State - Running (Core N) + * + * Unblock task (T1) + * + * Task (TN) + * Priority – N + * State - Running (Core N) + */ +void test_task_blocked_all_cores_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Block task T0 */ + vTaskDelay( 10 ); + + /* Verify the task has been blocked */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + /* Verify all other tasks are running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Unblock task T0 */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-28 + * A single task of high priority will be created. A low priority task will be + * created for each remaining available CPU core. The test will first verify + * that when the high priority task is blocked the low priority tasks will + * enter the running state. When the high priority task is resumed, each low + * priority task will return to the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Block task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Blocked State - Running (Core N) + * + * Unblock task (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (First available core) State - Ready + */ +void test_task_blocked_all_cores_different_priority_block_high( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i, xCoreToRunTask; + + /* Create a single task at high priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ 0 ] ); + + /* Create all remaining tasks at low priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify the high priority task is running */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Verify the idle task is running on all other CPU cores */ + verifyIdleTask( i - 1, i ); + } + + /* Block task T0 */ + vTaskDelay( 10 ); + + /* Verify the task has been blocked */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the running state */ + verifySmpTask( &xTaskHandles[ i ], eRunning, i - 1 ); + } + + /* Unblock task T0 */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify the high priority task is running */ + xCoreToRunTask = 1; + + if( xCoreToRunTask == ( configNUMBER_OF_CORES - 1 ) ) + { + /* Core 1 is the last core. Since it is already running the idle task. It + * won't be request to yield. Core 0 will choose the task to run. */ + xCoreToRunTask = 0; + } + + verifySmpTask( &xTaskHandles[ 0 ], eRunning, xCoreToRunTask ); + + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + /* Verify all other tasks are in the idle state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Verify the idle task running status. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i == xCoreToRunTask ) + { + /* The core is running task. */ + } + else if( i == 0 ) + { + verifyIdleTask( ( configNUMBER_OF_CORES - 3 ), i ); + } + else if( i == ( configNUMBER_OF_CORES - 1 ) ) + { + verifyIdleTask( ( configNUMBER_OF_CORES - 1 ), ( configNUMBER_OF_CORES - 1 ) ); + } + else + { + verifyIdleTask( ( ( configNUMBER_OF_CORES + i - 2 ) % configNUMBER_OF_CORES ), i ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-30 + * A single task of high priority will be created for each available CPU core. + * An additional low priority task shall be created. This test will verify that + * when a high priority task is blocked the low priority task will remain in + * the ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + * + * Block tasks (T1) + * + * Task (T1) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Blocked State - Ready + * + * Unblocked tasks (T1) + * + * Task (T1) Task (TN) + * Priority – 2 Priority – 1 + * State - Running (Core 0) State - Ready + */ +void test_task_block_all_cores_high_priority_block( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a task for each CPU core at high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single task at low priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all high priority tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Block the high priority task T0 */ + vTaskDelay( 10 ); + + /* Verify the task is blocked */ + verifySmpTask( &xTaskHandles[ 0 ], eBlocked, -1 ); + + /* Verify the idle task is running on core 0 */ + verifyIdleTask( 0, 0 ); + + /* Verify all high priority tasks remain running */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Resume the high priority task */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify all high priority tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-31 + * A task of equal priority will be created for each available CPU core. + * An additional task in the ready state shall be created. This test will + * verify that when a running task is blocked the ready task will move to + * the running state. When the blocked task is resumed, it shall enter the + * ready state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores + * greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Ready + * + * Block tasks (T1) + * + * Task (T1) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Blocked State - Running (Core 0) + * + * Unblock tasks (T1) + * + * Task (T1) Task (TN) + * Priority – 1 Priority – 1 + * State - Ready State - Running (Core 0) + */ +void test_task_block_all_cores_equal_priority_block_running( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create a task for each CPU core at equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are running */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the remaining task is ready */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Block the task on core 0 */ + vTaskDelay( 10 ); + + /* Verify the last task is now running on core 0 */ + verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); + + /* Resume the task on core 0 */ + xTaskAbortDelay( xTaskHandles[ 0 ] ); + + /* Verify task T0 is now in the ready state */ + verifySmpTask( &xTaskHandles[ 0 ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-108 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priority task. + * The lower priority will be switched out when it disinherits higher priority task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Ready State – Ready State – Running + * uxMutexesHeld - 1 + * + * Task TN+1 disinherits task T1's priority. + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + * uxMutexesHeld - 0 + */ +void test_task_priority_inherit_disinherit( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + xTaskPriorityDisinherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the mutex held count is decreased. */ + TEST_ASSERT_EQUAL( 0U, xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld ); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-109 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priority task. + * The lower priority will be switched out when it is disinherited by higher priority + * task due to timeout. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Ready State – Ready State – Running + * + * Task TN+1 is disinherited by task T1 due to timeout + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + */ +void test_task_priority_inherit_disinherit_timeout( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + vTaskPriorityDisinheritAfterTimeout( xTaskHandles[ configNUMBER_OF_CORES ], 1 ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +} diff --git a/FreeRTOS/Test/CMock/smp/single_priority_timeslice/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/FreeRTOSConfig.h new file mode 100644 index 000000000..cd33a9e04 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/FreeRTOSConfig.h @@ -0,0 +1,158 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" +#include "fake_infiniteloop.h" + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* https://www.FreeRTOS.org/a00110.html +*----------------------------------------------------------*/ + +/* SMP test specific configuration */ +#define configRUN_MULTIPLE_PRIORITIES 0 +#define configNUMBER_OF_CORES 16 +#define configUSE_CORE_AFFINITY 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_TASK_PREEMPTION_DISABLE 0 +#define configTICK_CORE 0 + +/* OS Configuration */ +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configIDLE_TASK_NAME "idle short" +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 +#define portREMOVE_STATIC_QUALIFIER 1 +#define portCRITICAL_NESTING_IN_TCB 1 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_PASSIVE_IDLE_HOOK 1 + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configENABLE_MPU 0 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +#define configASSERT( x ) \ + do \ + { \ + if( x ) \ + { \ + vFakeAssert( true, __FILE__, __LINE__ ); \ + } \ + else \ + { \ + vFakeAssert( false, __FILE__, __LINE__ ); \ + } \ + } while( 0 ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) + extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); + #define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer ) +#endif /* configINCLUDE_MESSAGE_BUFFER_AMP_DEMO */ + +#define configCONTROL_INFINITE_LOOP vFakeInfiniteLoop + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/single_priority_timeslice/Makefile b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/Makefile new file mode 100644 index 000000000..b44994cbf --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/Makefile @@ -0,0 +1,46 @@ +# indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC := tasks.c + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +PROJECT_DEPS_SRC := list.c queue.c + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS := FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := single_priority_timeslice_utest.c covg_single_priority_timeslice_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +SUITE_SUPPORT_SRC := smp_utest_common.c + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_port.h +MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_infiniteloop.h + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS += + +# List any addiitonal flags needed by the compiler +CFLAGS += + +# Try not to edit beyond this line unless necessary. + +# Project is determined based on path: $(UT_ROOT_DIR)/$(PROJECT) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +# Make variables available to included makefile +export + +include ../../testdir.mk diff --git a/FreeRTOS/Test/CMock/smp/single_priority_timeslice/covg_single_priority_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/covg_single_priority_timeslice_utest.c new file mode 100644 index 000000000..eccab5352 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/covg_single_priority_timeslice_utest.c @@ -0,0 +1,673 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file covg_single_priority_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" +#include "mock_fake_infiniteloop.h" + +/* =========================== EXTERN VARIABLES =========================== */ +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile TCB_t * pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern UBaseType_t uxTopReadyPriority; +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; +extern BaseType_t xSchedulerRunning; +extern UBaseType_t uxCurrentNumberOfTasks; +extern volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; + +/* =========================== EXTERN FUNCTIONS =========================== */ +extern void prvIdleTask( void ); +extern void prvPassiveIdleTask( void ); +extern void prvSelectHighestPriorityTask( BaseType_t xCoreID ); + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================= HELPER FUNCTIONS ========================= */ +void vApplicationPassiveIdleHook( void ) +{ + /* Adding this function to pass compilation. */ +} + +/* ============================== Test Cases ============================== */ + +/* @brief prvIdleTask - no other idle priority task + * + * This test calls the prvPassiveIdleTask to cover the condition that no other idle + * priority task in the ready list. The task is still the running task on core 0. + * + * Coverage + * @code{c} + * if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) + * { + * taskYIELD(); + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) is false. + */ +void test_coverage_prvIdleTask_no_other_idle_priority_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Expectations. */ + vFakeInfiniteLoop_ExpectAndReturn( 1 ); + vFakeInfiniteLoop_ExpectAndReturn( 0 ); + + /* API calls. Runs the idle task function on core 0. */ + prvIdleTask(); + + /* Validations. xTaskTCBs[ 0 ] still runs on core 0. */ + configASSERT( pxCurrentTCBs[ 0 ] == &xTaskTCBs[ 0 ] ); +} + +/* @brief prvIdleTask - yield for idle priority task + * + * This test calls the prvPassiveIdleTask to cover the condition that there are more + * idle priority level tasks than configNUMBER_OF_CORES. Yield is called in prvPassiveIdleTask. + * + * Coverage + * @code{c} + * if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) + * { + * taskYIELD(); + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) is true. + */ +void test_coverage_prvIdleTask_yield_for_idle_priority_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Create idle tasks and add it into the ready list. Create one more idle priority level + * in the loop. */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1U ); i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i < configNUMBER_OF_CORES ) + { + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + } + else + { + xTaskTCBs[ i ].xTaskRunState = -1; /* Set run state to taskTASK_NOT_RUNNING. */ + } + + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Expectations. */ + vFakeInfiniteLoop_ExpectAndReturn( 1 ); + vFakeInfiniteLoop_ExpectAndReturn( 0 ); + + /* API calls. Runs the idle task function on core 0. */ + prvIdleTask(); + + /* Validations. xTaskTCBs[ i ] runs on core 0. */ + configASSERT( pxCurrentTCBs[ 0 ] == &xTaskTCBs[ i ] ); +} + +/* @brief prvPassiveIdleTask - no other idle priority task + * + * This test calls the prvPassiveIdleTask to cover the condition that no other idle + * priority task in the ready list. The task is still the running task on core 0. + * + * Coverage + * @code{c} + * if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) + * { + * taskYIELD(); + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) is false. + */ +void test_coverage_prvPassiveIdleTask_no_other_idle_priority_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Create idle tasks and add it into the ready list. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xTaskRunState = i; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Expectations. */ + vFakeInfiniteLoop_ExpectAndReturn( 1 ); + vFakeInfiniteLoop_ExpectAndReturn( 0 ); + + /* API calls. Runs the idle task function on core 0. */ + prvPassiveIdleTask(); + + /* Validations. xTaskTCBs[ 0 ] still runs on core 0. */ + configASSERT( pxCurrentTCBs[ 0 ] == &xTaskTCBs[ 0 ] ); +} + +/* @brief prvPassiveIdleTask - yield for idle priority task + * + * This test calls the prvPassiveIdleTask to cover the condition that there are more + * idle priority level tasks than configNUMBER_OF_CORES. Yield is called in prvPassiveIdleTask. + * + * Coverage + * @code{c} + * if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) + * { + * taskYIELD(); + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) is true. + */ +void test_coverage_prvPassiveIdleTask_yield_for_idle_priority_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { 0 }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Initialize the idle priority ready list and set top ready priority to idle priority. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY; + + /* Create idle tasks and add it into the ready list. Create one more idle priority level + * in the loop. */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1U ); i++ ) + { + xTaskTCBs[ i ].uxPriority = tskIDLE_PRIORITY; + xTaskTCBs[ i ].xStateListItem.pvOwner = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ tskIDLE_PRIORITY ]; + xTaskTCBs[ i ].uxCoreAffinityMask = ( ( 1U << configNUMBER_OF_CORES ) - 1U ); + + if( i < configNUMBER_OF_CORES ) + { + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + xTaskTCBs[ i ].xTaskRunState = i; + } + else + { + xTaskTCBs[ i ].xTaskRunState = -1; /* Set run state to taskTASK_NOT_RUNNING. */ + } + + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Expectations. */ + vFakeInfiniteLoop_ExpectAndReturn( 1 ); + vFakeInfiniteLoop_ExpectAndReturn( 0 ); + + /* API calls. Runs the idle task function on core 0. */ + prvPassiveIdleTask(); + + /* Validations. xTaskTCBs[ i ] runs on core 0. */ + configASSERT( pxCurrentTCBs[ 0 ] == &xTaskTCBs[ i ] ); +} + +/* @brief prvSelectHighestPriorityTask - not schedule none idle task. + * + * Verify that none idle task can't be scheduled when there is higher priority task + * running with single priority config. + * + * Coverage + * @code{c} + * if( uxCurrentPriority < uxTopReadyPriority ) + * { + * if( ( pxTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0 ) + * { + * continue; + * } + * } + * @endcode + * ( ( pxTCB->uxTaskAttributes & taskATTRIBUTE_IS_IDLE ) == 0 ) is true. + */ +void test_coverage_prvSelectHighestPriorityTask_not_schedule_none_idle_task( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 2U ] = { 0 }; + uint32_t i = 0; + + /* Setup the variables and structure. */ + + /* Initialize the idle priority ready list and set top ready priority to higher + * priority than idle. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxCurrentNumberOfTasks = 0; + + /* Create one normal task to be inserted at the beginning of ready list. */ + vCreateStaticTestTaskAffinity( &xTaskTCBs[ 0 ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + taskTASK_NOT_RUNNING, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ 0 ].xStateListItem ); + + /* Create core numbers running idle task. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + ( i - 1 ), + pdTRUE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create one higher priority normal task running on core one. */ + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY + 1, + 1, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCBs[ i ].xStateListItem ); + + /* The original core 1 idle task now is not running. */ + xTaskTCBs[ 2 ].xTaskRunState = taskTASK_NOT_RUNNING; + + /* The ready list has the following status. + * Ready list [ 0 ] : T0, T1(0), T2, ..., TN(N-1). + * Ready list [ 1 ] : TN+1(1). */ + + /* API calls. Select task for core 0. */ + prvSelectHighestPriorityTask( 0 ); + + /* Validations.*/ + + /* T0 won't be selected to run after calling prvSelectHighestPriorityTask since + * it is not an idle task and top priority is higher than idle. */ + TEST_ASSERT_NOT_EQUAL( &xTaskTCBs[ 0 ], pxCurrentTCBs[ 0 ] ); + /* T1 is not running since other idle task will be selected first. */ + TEST_ASSERT_EQUAL( taskTASK_NOT_RUNNING, xTaskTCBs[ 0 ].xTaskRunState ); + /* T2 is selected to run on core 0. */ + TEST_ASSERT_EQUAL( 0, xTaskTCBs[ 2 ].xTaskRunState ); +} + +/* @brief prvSelectHighestPriorityTask - yield for previous task with core affinity. + * + * prvSelectHighestPriorityTask selects a task to run on specified core. The scheduler + * also selects another core to yield for previous task if the condition is satisfied. + * This test verifies the coverage of taskTASK_YIELDING condition. + * + * Coverage + * @code{c} + * if( ( xTaskPriority < xLowestPriority ) && + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) && + * ( xYieldPendings[ uxCore ] == pdFALSE ) ) + * { + * #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + * if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) + * #endif + * { + * xLowestPriority = xTaskPriority; + * xLowestPriorityCore = uxCore; + * } + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) is false. + */ +void test_coverage_prvSelectHighestPriorityTask_affinity_task_yielding( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 2 ] = { 0 }; + uint32_t i = 0; + + /* Setup the variables and structure. */ + + /* Initialize the idle priority ready list and set top ready priority to higher + * priority than idle. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxCurrentNumberOfTasks = 0; + + /* Create core numbers running idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + i, + pdTRUE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create two higher priority normal task. */ + for( i = configNUMBER_OF_CORES; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY + 1, + taskTASK_NOT_RUNNING, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Core 0 runs task TN. The original core 0 idle task now is not running. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ configNUMBER_OF_CORES ]; + xTaskTCBs[ configNUMBER_OF_CORES ].xTaskRunState = 0; + + /* Idle task 1 is yielding. */ + xTaskTCBs[ 1 ].xTaskRunState = taskTASK_YIELDING; + + /* Setup the affinity mask for TN and TN+1. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxCoreAffinityMask = ( 1 << 0 ) | ( 1 << 1 ); + xTaskTCBs[ configNUMBER_OF_CORES + 1 ].uxCoreAffinityMask = ( 1 << 0 ); + + /* The ready list has the following status. + * Ready list [ 0 ] : T0, T1(yielding), T2(2), ..., TN-1(N-1). + * Ready list [ 1 ] : TN(0), TN+1. */ + + /* API calls. Select task for core 0. Task TN+1 will be selected. Scheduler + * tries to find another core to yield for TN. The affinity mask limited the + * core for TN to run on core 1 only ( core 0 is running TN+1 ). Idle task 1 is + * yielding. Therefore, no core will yield for TN. */ + prvSelectHighestPriorityTask( 0 ); + + /* Validations.*/ + + /* T0 won't be selected to run after calling prvSelectHighestPriorityTask since + * it can only runs on core 0 and core 1. Task on core 1 is yielding. */ + TEST_ASSERT_NOT_EQUAL( &xTaskTCBs[ 0 ], pxCurrentTCBs[ 0 ] ); + /* T1 is still running on core 1 since it is yielding. */ + TEST_ASSERT_EQUAL( &xTaskTCBs[ 1 ], pxCurrentTCBs[ 1 ] ); + /* TN+1 is selected to run on core 0. */ + TEST_ASSERT_EQUAL( 0, xTaskTCBs[ configNUMBER_OF_CORES + 1 ].xTaskRunState ); +} + +/* @brief prvSelectHighestPriorityTask - yield for previous task with core affinity. + * + * prvSelectHighestPriorityTask selects a task to run on specified core. The scheduler + * also selects another core to yield for previous task if the condition is satisfied. + * This test verifies the coverage of invalid run state condition. + * + * Coverage + * @code{c} + * if( ( xTaskPriority < xLowestPriority ) && + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) && + * ( xYieldPendings[ uxCore ] == pdFALSE ) ) + * { + * #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + * if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) + * #endif + * { + * xLowestPriority = xTaskPriority; + * xLowestPriorityCore = uxCore; + * } + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) is false. + */ +void test_coverage_prvSelectHighestPriorityTask_affinity_task_state_invalid( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 2 ] = { 0 }; + uint32_t i = 0; + + /* Setup the variables and structure. */ + + /* Initialize the idle priority ready list and set top ready priority to higher + * priority than idle. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxCurrentNumberOfTasks = 0; + + /* Create core numbers running idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + i, + pdTRUE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create two higher priority normal task. */ + for( i = configNUMBER_OF_CORES; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY + 1, + taskTASK_NOT_RUNNING, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Core 0 runs task TN. The original core 0 idle task now is not running. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ configNUMBER_OF_CORES ]; + xTaskTCBs[ configNUMBER_OF_CORES ].xTaskRunState = 0; + + /* Idle task 1 is of invalid run state. */ + xTaskTCBs[ 1 ].xTaskRunState = configNUMBER_OF_CORES; + + /* Setup the affinity mask for TN and TN+1. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxCoreAffinityMask = ( 1 << 0 ) | ( 1 << 1 ); + xTaskTCBs[ configNUMBER_OF_CORES + 1 ].uxCoreAffinityMask = ( 1 << 0 ); + + /* The ready list has the following status. + * Ready list [ 0 ] : T0, T1(yielding), T2(2), ..., TN-1(N-1). + * Ready list [ 1 ] : TN(0), TN+1. */ + + /* API calls. Select task for core 0. Task TN+1 will be selected. Scheduler + * tries to find another core to yield for TN. The affinity mask limited the + * core for TN to run on core 1 only ( core 0 is running TN+1 ). Idle task 1 has + * invalid run state. Therefore, no core will yield for TN. */ + prvSelectHighestPriorityTask( 0 ); + + /* Validations.*/ + + /* T0 won't be selected to run after calling prvSelectHighestPriorityTask since + * it can only runs on core 0 and core 1. */ + TEST_ASSERT_NOT_EQUAL( &xTaskTCBs[ 0 ], pxCurrentTCBs[ 0 ] ); + /* TN+1 is selected to run on core 0. */ + TEST_ASSERT_EQUAL( 0, xTaskTCBs[ configNUMBER_OF_CORES + 1 ].xTaskRunState ); +} + +/* @brief prvSelectHighestPriorityTask - yield for previous task with core affinity. + * + * prvSelectHighestPriorityTask selects a task to run on specified core. The scheduler + * also selects another core to yield for previous task if the condition is satisfied. + * This test verifies the coverage of yield pending condition. + * + * Coverage + * @code{c} + * if( ( xTaskPriority < xLowestPriority ) && + * ( taskTASK_IS_RUNNING( pxCurrentTCBs[ uxCore ] ) != pdFALSE ) && + * ( xYieldPendings[ uxCore ] == pdFALSE ) ) + * { + * #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + * if( pxCurrentTCBs[ uxCore ]->xPreemptionDisable == pdFALSE ) + * #endif + * { + * xLowestPriority = xTaskPriority; + * xLowestPriorityCore = uxCore; + * } + * } + * @endcode + * ( xYieldPendings[ uxCore ] == pdFALSE ) is false. + */ +void test_coverage_prvSelectHighestPriorityTask_affinity_task_yield_pending( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 2 ] = { 0 }; + uint32_t i = 0; + + /* Setup the variables and structure. */ + + /* Initialize the idle priority ready list and set top ready priority to higher + * priority than idle. */ + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ); + vListInitialise( &( pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ] ) ); + uxTopReadyPriority = tskIDLE_PRIORITY + 1; + uxCurrentNumberOfTasks = 0; + + /* Create core numbers running idle task. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY, + i, + pdTRUE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create two higher priority normal task. */ + for( i = configNUMBER_OF_CORES; i < ( configNUMBER_OF_CORES + 2 ); i++ ) + { + vCreateStaticTestTaskAffinity( &xTaskTCBs[ i ], + ( ( 1U << configNUMBER_OF_CORES ) - 1U ), + tskIDLE_PRIORITY + 1, + taskTASK_NOT_RUNNING, + pdFALSE ); + listINSERT_END( &pxReadyTasksLists[ tskIDLE_PRIORITY + 1 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Core 0 runs task TN. The original core 0 idle task now is not running. */ + xTaskTCBs[ 0 ].xTaskRunState = taskTASK_NOT_RUNNING; + pxCurrentTCBs[ 0 ] = &xTaskTCBs[ configNUMBER_OF_CORES ]; + xTaskTCBs[ configNUMBER_OF_CORES ].xTaskRunState = 0; + + /* Core 1 has yield pending. */ + xYieldPendings[ 1 ] = pdTRUE; + + /* Setup the affinity mask for TN and TN+1. */ + xTaskTCBs[ configNUMBER_OF_CORES ].uxCoreAffinityMask = ( 1 << 0 ) | ( 1 << 1 ); + xTaskTCBs[ configNUMBER_OF_CORES + 1 ].uxCoreAffinityMask = ( 1 << 0 ); + + /* The ready list has the following status. + * Ready list [ 0 ] : T0, T1(yielding), T2(2), ..., TN-1(N-1). + * Ready list [ 1 ] : TN(0), TN+1. */ + + /* API calls. Select task for core 0. Task TN+1 will be selected. Scheduler + * tries to find another core to yield for TN. The affinity mask limited the + * core for TN to run on core 1 only ( core 0 is running TN+1 ). Core 1 has yield + * pending. Therefore, no core will yield for TN. */ + prvSelectHighestPriorityTask( 0 ); + + /* Validations.*/ + + /* T0 won't be selected to run after calling prvSelectHighestPriorityTask since + * it can only runs on core 0 and core 1. Core 1 has yield pending. */ + TEST_ASSERT_NOT_EQUAL( &xTaskTCBs[ 0 ], pxCurrentTCBs[ 0 ] ); + /* T1 is still running on core 1 since it has yield pending. */ + TEST_ASSERT_EQUAL( &xTaskTCBs[ 1 ], pxCurrentTCBs[ 1 ] ); + /* TN+1 is selected to run on core 0. */ + TEST_ASSERT_EQUAL( 0, xTaskTCBs[ configNUMBER_OF_CORES + 1 ].xTaskRunState ); +} diff --git a/FreeRTOS/Test/CMock/smp/single_priority_timeslice/single_priority_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/single_priority_timeslice_utest.c new file mode 100644 index 000000000..6c7548b71 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/single_priority_timeslice/single_priority_timeslice_utest.c @@ -0,0 +1,1168 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file single_priority_timeslice_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_timers.h" +#include "mock_fake_assert.h" +#include "mock_fake_port.h" + +/* =========================== EXTERN VARIABLES =========================== */ + +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; + +/* ============================ Unity Fixtures ============================ */ +/*! called before each testcase */ +void setUp( void ) +{ + commonSetUp(); +} + +/*! called after each testcase */ +void tearDown( void ) +{ + commonTearDown(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ============================= HELPER FUNCTIONS ========================= */ +void vApplicationPassiveIdleHook( void ) +{ + /* Adding this function to pass compilation. */ +} + +/* ============================== Test Cases ============================== */ + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-75 + * A task of equal priority will be created for each available CPU core. An + * additional task will be created in the ready state. This test will verify + * that as OS ticks are generated the ready task will be made to run on each + * CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 1 Priority – 1 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + */ +void test_timeslice_verification_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES + 1 tasks of equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the last task is in the ready state */ + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + + /* Generate a tick for each configNUMBER_OF_CORES. This will cause each + * task to be either moved to the ready state or the running state */ + for( i = 0; i <= configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + if( i < configNUMBER_OF_CORES ) + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + else + { + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-76 + * A task of equal priority will be created for each available CPU core + * except for one. This will leave a CPU core running the idle task. This test + * will verify that as OS ticks are generated the tasks will remain on the same + * CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN - 1) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN - 1) + * Priority – 1 + * State - Running (Core N - 1) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN - 1) + * Priority – 1 + * State - Running (Core N - 1) + */ +void test_timeslice_verification_idle_core( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Create ( configNUMBER_OF_CORES - 1 ) tasks of equal priority */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state prior to incrementing a tick */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the idle task is running on the last CPU Core */ + verifyIdleTask( 0, ( configNUMBER_OF_CORES - 1 ) ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES - 1; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-77 + * A high priority task will be created for each available CPU core. An + * additional low priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all CPU cores will remain running + * their original tasks and the ready task never enters the running state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_timeslice_verification_different_priority_tasks( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + /* The low priority task should never enter the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-78 + * A high priority task will be created for each available CPU core. An + * additional low priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all CPU cores will remain running + * their original tasks and the ready task never enters the running state. The + * test will then increase the priority of the ready task and verify tasks now + * begin to run on each CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1. + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + * + * Raise the priority of task TN + 1 and verify on each tick it executes on a + * different CPU core + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + */ +void test_priority_change_tasks_different_priority_raise_to_equal( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of high priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + /* The low priority task should never enter the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } + + /* Raise the priority of the low priority task to match the running tasks */ + vTaskPrioritySet( xTaskHandles[ configNUMBER_OF_CORES ], 2 ); + + /* After the first tick the ready task will be running on the first CPU core */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the the last task has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-79 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. The test will then lower the priority of the last task and verify + * tasks now remain running on a dedicated CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Lower the priority of task TN + 1 + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_priority_change_tasks_equal_priority_lower_ready_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Lower the priority of the last task. + * Before ready list : [ 1(0), 2(1), ..., N(N-1), 0 ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1) ] + */ + vTaskPrioritySet( xTaskHandles[ configNUMBER_OF_CORES ], 1 ); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, ( j + configNUMBER_OF_CORES - 1 ) % configNUMBER_OF_CORES ); + } + + /* Verify the low priority task remains in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-80 + * A task will be created for each available CPU core. This test will verify that as + * OS ticks are generated all tasks will execute on a fixed CPU core. A new task + * will be created. The test will then verify tasks now execute on each + * available CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 1 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 1 + * State - Running (Core N) + * + * Create a new task + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + */ +void test_task_create_tasks_equal_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Create a new task of equal priority */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify the last created task runs on each core or enters the ready state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* + * Verify the the last task has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted + */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-81 + * A high priority task will be created for each available CPU core. This test + * will verify that as OS ticks are generated all tasks will execute on a fixed + * CPU core. A new low priority task will be created. The test will then verify + * the tasks remain executing on the original CPU cores and do not rotate. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) + * Priority – 2 + * State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Create a new low priority task + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 1 + * State - Running (Core N) State - Ready + */ +void test_task_create_tasks_lower_priority( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } + + /* Create a new low priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-82 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. A task will be deleted. The test will then verify the tasks remain + * executing on fixed CPU cores and do not rotate. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Delete the last created task + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 2 + * State - Running + */ +void test_task_delete_tasks_equal_priorities_delete_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Delete last task. + * Before ready list : [ 1(0), 2(1), ..., N(N-1), 0 ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1) ] + */ + vTaskDelete( xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, ( j + configNUMBER_OF_CORES - 1 ) % configNUMBER_OF_CORES ); + } + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-83 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. A task will be suspended. The test will then verify the tasks remain + * executing on fixed CPU cores and do not rotate. When the suspended task is + * resumed it will begin executing on each CPU core on each tick. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Suspend the last created task + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not change state. + * + * Task (TN) + * Priority – 2 + * State - Running (Core N) + * + * Resume the suspended task. The tasks will now rotate to each CPU on each tick. + */ +void test_task_suspend_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Suspend last task. + * Before ready list : [ 1(0), 2(1), ..., N(N-1), 0 ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1) ] + */ + vTaskSuspend( xTaskHandles[ configNUMBER_OF_CORES ] ); + + /* Verify all tasks remain in the running state each time a tick is incremented */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, ( j + configNUMBER_OF_CORES - 1 ) % configNUMBER_OF_CORES ); + } + } + + /* Resume suspended task. + * Before ready list : [ 1(0), 2(1), ..., 0(N-1) ] + * After ready list : [ 1(0), 2(1), ..., 0(N-1), N ] + */ + vTaskResume( xTaskHandles[ configNUMBER_OF_CORES ] ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the the last task has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted + */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-84 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. A task will be blocked. The test will then verify the tasks remain + * executing on fixed CPU cores and do not rotate. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * State - Running (Core N) State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (0) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Block the task running on core 0, which is task 1. + * + * Call xTaskIncrementTick() for each configured CPU core. The tasks will not + * change state. + * + * Task (TN) + * Priority – 2 + * State - Running + * + * After blocking the task, verify task 1 can be scheduled on each core. + */ +void test_task_block_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Block the first task on core 0, which is task 1. + * Before ready list : [ 0, 1(0), 2(1), ..., N(N-1) ] + * After ready list : [ 0(0), 2(1), ..., N(N-1) ] + */ + vTaskDelay( configNUMBER_OF_CORES + 1 ); + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + for( int j = 0; j < configNUMBER_OF_CORES; j++ ) + { + if( j == 0 ) + { + verifySmpTask( &xTaskHandles[ j ], eRunning, 0 ); + } + else if( j == 1 ) + { + /* Task 1 is currently been blocked. */ + verifySmpTask( &xTaskHandles[ j ], eBlocked, -1 ); + } + else + { + verifySmpTask( &xTaskHandles[ j ], eRunning, j - 1 ); + } + } + } + + /* After ( configNUMBER_OF_CORES + 1 ) ticks, the task 1 will be added back to + * the ready list. Verify that the task 1 can be scheduled on each core when + * xTaskIncrementTick is called. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* + * Verify the the task 1 has a increasing xTaskRunState as it will follow the cycle of 0,1,2,3... + * the last state of -1 is omitted + */ + verifySmpTask( &xTaskHandles[ 1 ], eRunning, i ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-85 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created with affinity for the largest + * numbered CPU core. This test will verify that as OS ticks are generated the + * task with CPU affinity will either be in the ready state or running on the + * specified CPU core. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – Last CPU Core + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – Last CPU Core + * State - Running State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 3 + * 2 -1 + * 3 3 + * 4 -1 + * + */ +void test_task_affinity_verification( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task with core affinity for the last CPU core */ + xTaskCreateAffinitySet( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, ( 1 << ( configNUMBER_OF_CORES - 1 ) ), &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the task is either in the ready state or running on the last CPU core */ + int32_t core = ( i % 2 == 0 ) ? ( configNUMBER_OF_CORES - 1 ) : -1; + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], ( core == -1 ) ? eReady : eRunning, core ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-86 + * A high priority task will be created for each available CPU core. An + * additional high priority task will be created in the ready state. This test + * will verify that as OS ticks are generated all tasks will execute on each + * CPU core. The test will then set the last task to have affinity for the last + * CPU core. The last task will only run on the last CPU core or be in the ready + * state. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 1 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater than 1 . + * + * Tasks are created prior to starting the scheduler. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – None + * State - Ready State - Ready + * + * After calling vTaskStartScheduler() + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – None + * State - Running State - Ready + * + * Call xTaskIncrementTick() for each configured CPU core. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 0 + * 2 1 + * 3 2 + * 4 3 + * + * Set affinity for the last task to the last CPU core. + * + * Task (TN) Task (TN + 1) + * Priority – 2 Priority – 2 + * Affinity – None Affinity – Last CPU Core + * State - Running State - Ready + * + * Verify the task only runs on the specified core or is in the ready state. + * + * Task (TN + 1) when configNUMBER_OF_CORES = 4 + * Tick Core + * 1 -1 + * 2 3 + * 3 -1 + * 4 3 + */ +void test_task_affinity_set_affinity_running_task( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Create configNUMBER_OF_CORES tasks of equal priority */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create a single equal priority task */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + + vTaskStartScheduler(); + + /* Verify all tasks are in the running state */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* The remaining task shall be in the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* After the first tick the ready task will be running on CPU core 1 */ + int32_t core = 1; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the last created task runs on each core or enters the ready state */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, i ); + } + + /* Set CPU core affinity on the last task for the last CPU core */ + vTaskCoreAffinitySet( xTaskHandles[ configNUMBER_OF_CORES ], 1 << ( configNUMBER_OF_CORES - 1 ) ); + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIncrementTick_helper(); + + /* Verify the task is either in the ready state or running on the last CPU core */ + core = ( i % 2 == 1 ) ? ( configNUMBER_OF_CORES - 1 ) : -1; + + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], ( core == -1 ) ? eReady : eRunning, core ); + } +} diff --git a/FreeRTOS/Test/CMock/smp/smp.yml b/FreeRTOS/Test/CMock/smp/smp.yml new file mode 100644 index 000000000..5f50def2f --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/smp.yml @@ -0,0 +1,32 @@ +:cmock: + :mock_prefix: mock_ + :when_no_prototypes: :warn + :treat_externs: :include + :enforce_strict_ordering: TRUE + :plugins: + - :ignore + - :ignore_arg + - :expect_any_args + - :array + - :callback + - :return_thru_ptr + - :cexception + :callback_include_count: true # include a count arg when calling the callback + :callback_after_arg_check: false # check arguments before calling the callback + :treat_as: + uint8: HEX8 + uint16: HEX16 + uint32: UINT32 + int8: INT8 + bool: UINT8 + :includes: # This will add these includes to each mock. + - + - "FreeRTOS.h" + :weak: __attribute__((weak)) + :verbosity: 3 + :attributes: + - PRIVILEGED_FUNCTION + :strippables: + - PRIVILEGED_FUNCTION + - portDONT_DISCARD + diff --git a/FreeRTOS/Test/CMock/smp/smp_utest_common.c b/FreeRTOS/Test/CMock/smp/smp_utest_common.c new file mode 100644 index 000000000..ebc4ec87e --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/smp_utest_common.c @@ -0,0 +1,449 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file smp_utest_common.c */ + +#include "smp_utest_common.h" + +/* C runtime includes. */ +#include +#include +#include + +/* Test includes */ +#include "task.h" +#include "global_vars.h" + +/* Unity includes. */ +#include "unity.h" +#include "unity_memory.h" + +/* Mock includes. */ +#include "mock_fake_assert.h" +#include "mock_fake_port.h" +#include "mock_timers.h" + +/* =========================== EXTERN VARIABLES =========================== */ + +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; +extern List_t xDelayedTaskList1; +extern List_t xDelayedTaskList2; +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern volatile UBaseType_t uxCurrentNumberOfTasks; +extern volatile TickType_t xTickCount; +extern volatile UBaseType_t uxTopReadyPriority; +extern volatile BaseType_t xSchedulerRunning; +extern volatile TickType_t xPendedTicks; +extern volatile BaseType_t xNumOfOverflows; +extern volatile TickType_t xNextTaskUnblockTime; +extern UBaseType_t uxTaskNumber; +extern TaskHandle_t xIdleTaskHandles[ configNUMBER_OF_CORES ]; +extern volatile UBaseType_t uxSchedulerSuspended; +extern volatile UBaseType_t uxDeletedTasksWaitingCleanUp; +extern List_t * volatile pxDelayedTaskList; +extern volatile TCB_t * pxCurrentTCBs[ configNUMBER_OF_CORES ]; +extern volatile BaseType_t xYieldPendings[ configNUMBER_OF_CORES ]; + +static BaseType_t xCoreYields[ configNUMBER_OF_CORES ] = { 0 }; + +/* portGET_CORE_ID() returns the xCurrentCoreId. The task choose order is dependent on + * which core calls the FreeRTOS APIs. Setup xCurrentCoreId is required before calling + * FreeRTOS APIs. The default core is 0. */ +static BaseType_t xCurrentCoreId = 0; + +/* Each core maintains it's lock count. However, only one core has lock count value > 0. + * In real world case, this value is read when interrupt disabled while increased when + * lock is acquired. */ +static BaseType_t xIsrLockCount[ configNUMBER_OF_CORES ] = { 0 }; +static BaseType_t xTaskLockCount[ configNUMBER_OF_CORES ] = { 0 }; + +/* ========================== EXTERN FUNCTIONS ========================== */ + +extern void vTaskEnterCritical( void ); +extern void vTaskExitCritical( void ); +extern UBaseType_t vTaskEnterCriticalFromISR( void ); +extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); + +/* ========================== CALLBACK FUNCTIONS ========================== */ + +void * pvPortMalloc( size_t xSize ) +{ + return unity_malloc( xSize ); +} + +void vPortFree( void * pv ) +{ + return unity_free( pv ); +} + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) +{ + return pxTopOfStack; +} + +BaseType_t xPortStartScheduler( void ) +{ + uint8_t i; + + /* Initialize each core with a task */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vTaskSwitchContext( i ); + } + + return pdTRUE; +} + +void vPortEndScheduler( void ) +{ +} + +void vFakePortYieldCoreStubCallback( int xCoreID, + int cmock_num_calls ) +{ + BaseType_t xCoreInCritical = pdFALSE; + BaseType_t xPreviousCoreId = xCurrentCoreId; + int i; + + /* Check if the lock is acquired by any core. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( ( xIsrLockCount[ i ] > 0 ) || ( xTaskLockCount[ i ] > 0 ) ) + { + xCoreInCritical = pdTRUE; + break; + } + } + + if( xCoreInCritical == pdTRUE ) + { + /* If a is in the critical section, pend the core yield until the + * task spinlock is released. */ + xCoreYields[ xCoreID ] = pdTRUE; + } + else + { + /* No task is in the critical section. We can yield this core. */ + xCurrentCoreId = xCoreID; + vTaskSwitchContext( xCurrentCoreId ); + xCurrentCoreId = xPreviousCoreId; + } +} + +void vFakePortYieldStubCallback( int cmock_num_calls ) +{ + vTaskSwitchContext( xCurrentCoreId ); +} + +void vFakePortEnterCriticalSectionCallback( int cmock_num_calls ) +{ + vTaskEnterCritical(); +} + +/* vTaskExitCritical release the lock then check if this task is requested to yield. + * The mock implementation assumes all the cores can be requested to yield immediately. + * If the core is requested to yield, it will yield in the following order. + * 1. core ID in accsending order if the core is requested to yield and is not xCurrentCoreId. + * 2. core ID which is requested to yield and the core ID equals xCurrentCoreId. + * core i : Core ID requested to yield in critical section in acesending order. + * .... + * core xCurrentCoreId : Core ID equals to xCurrentCoreId and is requested to yield in critical section. */ +void vFakePortExitCriticalSectionCallback( int cmock_num_calls ) +{ + vTaskExitCritical(); +} + +void vSetCurrentCore( BaseType_t xCoreID ) +{ + xCurrentCoreId = xCoreID; +} + +static void vYieldCores( void ) +{ + BaseType_t i; + BaseType_t xPreviousCoreId = xCurrentCoreId; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( xCoreYields[ i ] == pdTRUE ) + { + xCurrentCoreId = i; + xCoreYields[ i ] = pdFALSE; + vTaskSwitchContext( i ); + } + } + + xCurrentCoreId = xPreviousCoreId; +} + +unsigned int vFakePortGetCoreIDCallback( int cmock_num_calls ) +{ + return ( unsigned int ) xCurrentCoreId; +} + +void vFakePortGetISRLockCallback( int cmock_num_calls ) +{ + int i; + + ( void ) cmock_num_calls; + + /* Ensure that no other core is in the critical section. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i != xCurrentCoreId ) + { + TEST_ASSERT_MESSAGE( xIsrLockCount[ i ] == 0, "vFakePortGetISRLock xIsrLockCount[ i ] > 0" ); + TEST_ASSERT_MESSAGE( xTaskLockCount[ i ] == 0, "vFakePortGetISRLock xTaskLockCount[ i ] > 0" ); + } + } + + xIsrLockCount[ xCurrentCoreId ]++; +} + +void vFakePortReleaseISRLockCallback( int cmock_num_calls ) +{ + ( void ) cmock_num_calls; + + TEST_ASSERT_MESSAGE( xIsrLockCount[ xCurrentCoreId ] > 0, "xIsrLockCount[ xCurrentCoreId ] <= 0" ); + xIsrLockCount[ xCurrentCoreId ]--; +} + +void vFakePortGetTaskLockCallback( int cmock_num_calls ) +{ + int i; + + ( void ) cmock_num_calls; + + /* Ensure that no other core is in the critical section. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( i != xCurrentCoreId ) + { + TEST_ASSERT_MESSAGE( xIsrLockCount[ i ] == 0, "vFakePortGetTaskLock xIsrLockCount[ i ] > 0" ); + TEST_ASSERT_MESSAGE( xTaskLockCount[ i ] == 0, "vFakePortGetTaskLock xTaskLockCount[ i ] > 0" ); + } + } + + xTaskLockCount[ xCurrentCoreId ]++; +} + +void vFakePortReleaseTaskLockCallback( int cmock_num_calls ) +{ + ( void ) cmock_num_calls; + + TEST_ASSERT_MESSAGE( xTaskLockCount[ xCurrentCoreId ] > 0, "xTaskLockCount[ xCurrentCoreId ] <= 0" ); + xTaskLockCount[ xCurrentCoreId ]--; + + /* When releasing the ISR lock, check if any core is waiting to yield. */ + if( xTaskLockCount[ xCurrentCoreId ] == 0 ) + { + vYieldCores(); + } +} + +portBASE_TYPE vFakePortEnterCriticalFromISRCallback( int cmock_num_calls ) +{ + portBASE_TYPE xSavedInterruptState; + + xSavedInterruptState = vTaskEnterCriticalFromISR(); + return xSavedInterruptState; +} + +void vFakePortExitCriticalFromISRCallback( portBASE_TYPE xSavedInterruptState, + int cmock_num_calls ) +{ + vTaskExitCriticalFromISR( xSavedInterruptState ); + /* Simulate yield cores when leaving the critical section. */ + vYieldCores(); +} + +/* ============================= Unity Fixtures ============================= */ + +void commonSetUp( void ) +{ + vFakePortYieldCore_StubWithCallback( vFakePortYieldCoreStubCallback ); + vFakePortYield_StubWithCallback( vFakePortYieldStubCallback ); + + vFakePortEnterCriticalSection_StubWithCallback( vFakePortEnterCriticalSectionCallback ); + vFakePortExitCriticalSection_StubWithCallback( vFakePortExitCriticalSectionCallback ); + + vFakePortEnterCriticalFromISR_StubWithCallback( vFakePortEnterCriticalFromISRCallback ); + vFakePortExitCriticalFromISR_StubWithCallback( vFakePortExitCriticalFromISRCallback ); + + vFakePortGetCoreID_StubWithCallback( vFakePortGetCoreIDCallback ); + + vFakePortGetISRLock_StubWithCallback( vFakePortGetISRLockCallback ); + vFakePortGetTaskLock_StubWithCallback( vFakePortGetTaskLockCallback ); + vFakePortReleaseISRLock_StubWithCallback( vFakePortReleaseISRLockCallback ); + vFakePortReleaseTaskLock_StubWithCallback( vFakePortReleaseTaskLockCallback ); + + vFakeAssert_Ignore(); + vFakePortAssertIfISR_Ignore(); + vFakePortEnableInterrupts_Ignore(); + + ulFakePortSetInterruptMaskFromISR_IgnoreAndReturn( 0 ); + vFakePortClearInterruptMaskFromISR_Ignore(); + + vFakePortDisableInterrupts_IgnoreAndReturn( 1 ); + vFakePortRestoreInterrupts_Ignore(); + xTimerCreateTimerTask_IgnoreAndReturn( 1 ); + vFakePortCheckIfInISR_IgnoreAndReturn( 0 ); + vPortCurrentTaskDying_Ignore(); + portSetupTCB_CB_Ignore(); + ulFakePortSetInterruptMask_IgnoreAndReturn( 0 ); + vFakePortClearInterruptMask_Ignore(); + + memset( &pxReadyTasksLists, 0x00, configMAX_PRIORITIES * sizeof( List_t ) ); + memset( &xDelayedTaskList1, 0x00, sizeof( List_t ) ); + memset( &xDelayedTaskList2, 0x00, sizeof( List_t ) ); + memset( &xIdleTaskHandles, 0x00, ( configNUMBER_OF_CORES * sizeof( TaskHandle_t ) ) ); + memset( &pxCurrentTCBs, 0x00, ( configNUMBER_OF_CORES * sizeof( TCB_t * ) ) ); + memset( ( void * ) &xYieldPendings, 0x00, ( configNUMBER_OF_CORES * sizeof( BaseType_t ) ) ); + + uxDeletedTasksWaitingCleanUp = 0; + uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; + xTickCount = ( TickType_t ) 500; /* configINITIAL_TICK_COUNT */ + uxTopReadyPriority = tskIDLE_PRIORITY; + xSchedulerRunning = pdFALSE; + xPendedTicks = ( TickType_t ) 0U; + xNumOfOverflows = ( BaseType_t ) 0; + uxTaskNumber = ( UBaseType_t ) 0U; + xNextTaskUnblockTime = ( TickType_t ) 0U; + uxSchedulerSuspended = ( UBaseType_t ) 0; + uxDeletedTasksWaitingCleanUp = 0; + pxDelayedTaskList = NULL; + + xCurrentCoreId = 0; + memset( xTaskLockCount, 0x00, sizeof( xTaskLockCount ) ); + memset( xIsrLockCount, 0x00, sizeof( xIsrLockCount ) ); +} + +void commonTearDown( void ) +{ +} + +/* ========================== Helper functions =========================== */ + +void vSmpTestTask( void * pvParameters ) +{ +} + +void verifySmpTask( TaskHandle_t * xTaskHandle, + eTaskState eCurrentState, + TaskRunning_t xTaskRunState ) +{ + TaskStatus_t xTaskDetails; + + vTaskGetInfo( *xTaskHandle, &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL_INT_MESSAGE( xTaskRunState, xTaskDetails.xHandle->xTaskRunState, "Task Verification Failed: Incorrect xTaskRunState" ); + TEST_ASSERT_EQUAL_INT_MESSAGE( eCurrentState, xTaskDetails.eCurrentState, "Task Verification Failed: Incorrect eCurrentState" ); +} + +void verifyIdleTask( BaseType_t index, + TaskRunning_t xTaskRunState ) +{ + TaskStatus_t xTaskDetails; + int ret; + + vTaskGetInfo( xIdleTaskHandles[ index ], &xTaskDetails, pdTRUE, eInvalid ); + #ifdef configIDLE_TASK_NAME + ret = strncmp( xTaskDetails.xHandle->pcTaskName, configIDLE_TASK_NAME, strlen( configIDLE_TASK_NAME ) ); + #else + ret = strncmp( xTaskDetails.xHandle->pcTaskName, "IDLE", 4 ); + #endif + TEST_ASSERT_EQUAL_INT_MESSAGE( 0, ret, "Idle Task Verification Failed: Incorrect task name" ); + TEST_ASSERT_EQUAL_INT_MESSAGE( pdTRUE, xTaskDetails.xHandle->uxTaskAttributes, "Idle Task Verification Failed: Incorrect xIsIdle" ); + TEST_ASSERT_EQUAL_INT_MESSAGE( xTaskRunState, xTaskDetails.xHandle->xTaskRunState, "Idle Task Verification Failed: Incorrect xTaskRunState" ); + TEST_ASSERT_EQUAL_INT_MESSAGE( eRunning, xTaskDetails.eCurrentState, "Idle Task Verification Failed: Incorrect eCurrentState" ); +} + +/* Helper function to simulate calling xTaskIncrementTick in critical section. */ +void xTaskIncrementTick_helper( void ) +{ + BaseType_t xSwitchRequired; + UBaseType_t uxSavedInterruptState; + + /* xTaskIncrementTick is called in ISR context. Use taskENTER/EXIT_CRITICAL_FROM_ISR + * here. */ + uxSavedInterruptState = taskENTER_CRITICAL_FROM_ISR(); + + xSwitchRequired = xTaskIncrementTick(); + + /* Simulate context switch on the core which calls xTaskIncrementTick. */ + if( xSwitchRequired == pdTRUE ) + { + portYIELD_CORE( configTICK_CORE ); + } + + taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptState ); +} + +void vCreateStaticTestTask( TaskHandle_t xTaskHandle, + UBaseType_t uxPriority, + BaseType_t xTaskRunState, + BaseType_t xTaskIsIdle ) +{ + TCB_t * pxTaskTCB = ( TCB_t * ) xTaskHandle; + + pxTaskTCB->xStateListItem.pvOwner = pxTaskTCB; + pxTaskTCB->uxPriority = uxPriority; + + /* Also assign pxCurrentTCBs to the created task. */ + if( ( xTaskRunState >= 0 ) && ( xTaskRunState < configNUMBER_OF_CORES ) ) + { + pxCurrentTCBs[ xTaskRunState ] = pxTaskTCB; + } + + pxTaskTCB->xTaskRunState = xTaskRunState; + + /* Set idle task attribute. */ + if( xTaskIsIdle == pdTRUE ) + { + pxTaskTCB->uxTaskAttributes = taskATTRIBUTE_IS_IDLE; + } + else + { + pxTaskTCB->uxTaskAttributes = 0; + } + + /* Increase the uxCurrentNumberOfTasks. */ + uxCurrentNumberOfTasks = uxCurrentNumberOfTasks + 1; +} + +#if ( configUSE_CORE_AFFINITY == 1 ) + void vCreateStaticTestTaskAffinity( TaskHandle_t xTaskHandle, + UBaseType_t uxCoreAffinityMask, + UBaseType_t uxPriority, + BaseType_t xTaskRunState, + BaseType_t xTaskIsIdle ) + { + TCB_t * pxTaskTCB = ( TCB_t * ) xTaskHandle; + + vCreateStaticTestTask( xTaskHandle, uxPriority, xTaskRunState, xTaskIsIdle ); + pxTaskTCB->uxCoreAffinityMask = uxCoreAffinityMask; + } +#endif /* if ( configUSE_CORE_AFFINITY == 1 ) */ diff --git a/FreeRTOS/Test/CMock/smp/smp_utest_common.h b/FreeRTOS/Test/CMock/smp/smp_utest_common.h new file mode 100644 index 000000000..8a05c1268 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/smp_utest_common.h @@ -0,0 +1,118 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file smp_utest_common.h */ + +#ifndef SMP_UTEST_COMMON_H +#define SMP_UTEST_COMMON_H + +/* C runtime includes. */ +#include +#include +#include + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" + +/* FreeRTOS includes */ +#include "FreeRTOS.h" +#include "task.h" +#include "global_vars.h" + +/* ========================== CALLBACK FUNCTIONS =========================== */ + +/** + * @brief defines malloc() for this test and redirects it to unity_malloc + * @param xSize size of memory block to be allocated + * @return pointer to the allocated memory on success. + * @return NULL if the memory could not be allocated. + */ +void * pvPortMalloc( size_t xSize ); + +/** + * @brief defines free() for this test and redirects it to unity_free + * @param pv pointer to the block to be freed + */ +void vPortFree( void * pv ); + +/* ========================== Helper functions =========================== */ + +/** + * @brief Common test case setup function for SMP tests. + */ +void commonSetUp( void ); + +/** + * @brief Common test case teardown function for SMP tests. + */ +void commonTearDown( void ); + +/** + * @brief Verify task current and run states + */ +void verifySmpTask( TaskHandle_t * xTaskHandle, + eTaskState eCurrentState, + TaskRunning_t xTaskRunState ); + +/** + * @brief Verify the Idle task is executing on a specific core + */ +void verifyIdleTask( BaseType_t index, + TaskRunning_t xTaskRunState ); + +/** + * @brief Dummy task for test execution + */ +void vSmpTestTask( void * pvParameters ); + +/** + * @brief Helper function to simulate calling xTaskIncrementTick in critical section. + */ +void xTaskIncrementTick_helper( void ); + +/** + * @brief Set the core ID returned by portGET_CORE_ID() + */ +void vSetCurrentCore( BaseType_t xCoreID ); + +/** + * @brief Helper function to create static test task. + */ +void vCreateStaticTestTask( TaskHandle_t xTaskHandle, + UBaseType_t uxPriority, + BaseType_t xTaskRunState, + BaseType_t xTaskIsIdle ); + +#if ( configUSE_CORE_AFFINITY == 1 ) + void vCreateStaticTestTaskAffinity( TaskHandle_t xTaskHandle, + UBaseType_t uxCoreAffinityMask, + UBaseType_t uxPriority, + BaseType_t xTaskRunState, + BaseType_t xTaskIsIdle ); +#endif + + +#endif /* SMP_UTEST_COMMON_H */ diff --git a/FreeRTOS/Test/CMock/stream_buffer/api/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/stream_buffer/api/FreeRTOSConfig.h index 271dffd17..58952c502 100644 --- a/FreeRTOS/Test/CMock/stream_buffer/api/FreeRTOSConfig.h +++ b/FreeRTOS/Test/CMock/stream_buffer/api/FreeRTOSConfig.h @@ -128,8 +128,6 @@ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that in } \ } while( 0 ) -#define mtCOVERAGE_TEST_MARKER() __asm volatile ( "NOP" ) - #define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 #if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) extern void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer ); diff --git a/FreeRTOS/Test/CMock/stream_buffer/callback/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/stream_buffer/callback/FreeRTOSConfig.h index f6f5ad5d0..1ceb40ccb 100644 --- a/FreeRTOS/Test/CMock/stream_buffer/callback/FreeRTOSConfig.h +++ b/FreeRTOS/Test/CMock/stream_buffer/callback/FreeRTOSConfig.h @@ -129,8 +129,6 @@ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that in } \ } while( 0 ) -#define mtCOVERAGE_TEST_MARKER() __asm volatile ( "NOP" ) - extern void vDefaultSendCompletedStub( void * xStreamBuffer ); #define sbSEND_COMPLETED( pxStreamBuffer ) vDefaultSendCompletedStub( pxStreamBuffer ) diff --git a/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_1.h b/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_1.h index a1bac1f09..1a73445d8 100644 --- a/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_1.h +++ b/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_1.h @@ -27,6 +27,9 @@ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H +#include "fake_assert.h" +#include "fake_infiniteloop.h" + /* XXX: this file will be processed by unifdef to generate new header files * that can be mocked according to the configurations desired * it has a few limitations on the format of this file such as: @@ -131,10 +134,18 @@ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that in /* It is a good idea to define configASSERT() while developing. configASSERT() * uses the same semantics as the standard C assert() macro. */ -#define configASSERT( x ) +/* *INDENT-OFF* */ +#define configASSERT( x ) do { if( x ) { vFakeAssert( true, __FILE__, __LINE__ ); } else { vFakeAssert( false, __FILE__, __LINE__ ); } } while( 0 ) +/* *INDENT-ON* */ + #define portREMOVE_STATIC_QUALIFIER 1 #define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) +#define portALLOCATE_SECURE_CONTEXT vFakePortAllocateSecureContext + +#define configCONTROL_INFINITE_LOOP vFakeInfiniteLoop + #endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_2.h b/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_2.h index 3dfcc5103..6e9933bf5 100644 --- a/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_2.h +++ b/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_2.h @@ -27,6 +27,8 @@ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H +#include "fake_assert.h" + /* XXX: this file will be processed by unifdef to generate new header files * that can be mocked according to the configurations desired * it has a few limitations on the format of this file such as: @@ -126,7 +128,10 @@ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that in /* It is a good idea to define configASSERT() while developing. configASSERT() * uses the same semantics as the standard C assert() macro. */ -#define configASSERT( x ) +/* *INDENT-OFF* */ +#define configASSERT( x ) do { if( x ) { vFakeAssert( true, __FILE__, __LINE__ ); } else { vFakeAssert( false, __FILE__, __LINE__ ); } } while( 0 ) +/* *INDENT-ON* */ + #define portREMOVE_STATIC_QUALIFIER 1 #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 diff --git a/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_assert.h b/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_assert.h new file mode 100644 index 000000000..93d72b227 --- /dev/null +++ b/FreeRTOS/Test/CMock/tasks/FreeRTOSConfig_assert.h @@ -0,0 +1,144 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/* XXX: this file will be processed by unifdef to generate new header files + * that can be mocked according to the configurations desired + * it has a few limitations on the format of this file such as: + * no config that spans more than one line + * no strings in config names + * for more info please check the man file with $ man unifdef + */ + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* http://www.freertos.org/a00110.html +*----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_TICKLESS_IDLE 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) /* For test. */ +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 /* As there are a lot of tasks running. */ + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 9 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define configENABLE_MPU 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +#define portSTACK_GROWTH ( -1 ) +#define configRECORD_STACK_HIGH_ADDRESS 1 + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +/* *INDENT-OFF* */ +#define configASSERT( x ) do { if( x ) { vFakeAssert( true, __FILE__, __LINE__ ); } else { vFakeAssert( false, __FILE__, __LINE__ ); } } while( 0 ) +/* *INDENT-ON* */ + +#define portREMOVE_STATIC_QUALIFIER 1 + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/tasks/Makefile b/FreeRTOS/Test/CMock/tasks/Makefile index 94a9ad834..bedde5ffd 100644 --- a/FreeRTOS/Test/CMock/tasks/Makefile +++ b/FreeRTOS/Test/CMock/tasks/Makefile @@ -6,17 +6,20 @@ include ../makefile.in -PROJECT := tasks +PROJECT := tasks +# SUITES lists the suites contained in subdirectories of this directory # # Test/CMock/tasks -PROJECT_DIR := $(abspath .) -PROJ_DIR := $(abspath .) +PROJECT_DIR := $(abspath .) +PROJ_DIR := $(abspath .) # List the dependency files you wish to mock MOCK_FILES_FP := $(KERNEL_DIR)/include/timers.h MOCK_FILES_FP += $(KERNEL_DIR)/include/list.h MOCK_FILES_FP += $(KERNEL_DIR)/include/portable.h MOCK_FILES_FP += $(PROJECT_DIR)/list_macros.h +MOCK_FILES_FP += $(PROJECT_DIR)/../config/fake_assert.h +MOCK_FILES_FP += $(PROJECT_DIR)/../config/fake_infiniteloop.h UNDEF_MOCKED_HEADER_MACROS := -UlistLIST_IS_EMPTY -UlistGET_OWNER_OF_HEAD_ENTRY\ -UlistIS_CONTAINED_WITHIN -UlistGET_LIST_ITEM_VALUE \ @@ -24,7 +27,7 @@ UNDEF_MOCKED_HEADER_MACROS := -UlistLIST_IS_EMPTY -UlistGET_OWNER_OF_HEAD_ENTRY\ -UlistLIST_ITEM_CONTAINER -UlistCURRENT_LIST_LENGTH # List special compilation flags for this module -CFLAGS += -Wno-unused-function +CFLAGS += -Wno-unused-function # List special preprocessing flags for this module CPPFLAGS += @@ -37,7 +40,7 @@ LDFLAGS += # Try not to edit beyond this line -COVERAGE_OPTS := -fprofile-arcs -ftest-coverage -fprofile-generate +COVERAGE_OPTS := -fprofile-arcs -ftest-coverage -fprofile-generate # build/generated/queue SCRATCH_DIR := $(GENERATED_DIR)/$(PROJECT) @@ -66,10 +69,13 @@ DISCRIMINATOR := $(subst _utest,,$(subst .c,,$(subst $(PROJECT)_,,$(PROJ_SR # tasks/1/mocks tasks/2/mocks MOCK_DIRS := $(addsuffix /mocks,$(addprefix $(SCRATCH_DIR)/,$(DISCRIMINATOR))) + # queue/1/cpp queue/2/cpp CPP_DIRS := $(addsuffix /cpp,$(addprefix $(SCRATCH_DIR)/,$(DISCRIMINATOR))) + # tasks/1/include tasks/2/include INCLUDE_DIRS := $(addsuffix /include,$(addprefix $(SCRATCH_DIR)/,$(DISCRIMINATOR))) + #list/1 list/2 .... CONFIG_DIRS := $(addprefix $(SCRATCH_DIR)/,$(DISCRIMINATOR)) @@ -84,8 +90,7 @@ PROJ_OBJ_LIST := $(EXEC_LIST) .PHONY: all Makefile directories -.SECONDARY: -all : directories $(EXEC_LIST) +all : directories $(EXEC_LIST) run # Build the executables 1 per configuration $(EXEC_PATH) : $(MOCK_OBJS) \ @@ -112,6 +117,7 @@ $(CPP_FILES) : | directories sed -i '/#ifndef FREERTOS_CONFIG_H/d' $(SCRATCH_DIR)/$*/include/FreeRTOSConfig.def sed -i '/#define FREERTOS_CONFIG_H/d' $(SCRATCH_DIR)/$*/include/FreeRTOSConfig.def sed -i '/#endif/d' $(SCRATCH_DIR)/$*/include/FreeRTOSConfig.def + sed -i '/#include/d' $(SCRATCH_DIR)/$*/include/FreeRTOSConfig.def for h_file in $(MOCK_FILES_FP) ; do \ unifdef -f $(SCRATCH_DIR)/$*/include/FreeRTOSConfig.def $$h_file \ > $(SCRATCH_DIR)/$*/cpp/$$(basename $$h_file) ; \ @@ -179,3 +185,18 @@ directories : EXEC_PREFIX := $(PROJECT) include ../coverage.mk + + +# Indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) + +SUITES += tasks_freertos +# run each suite and leave gcda / gcov files in place +run: + $(foreach suite,$(SUITES),make -C $(suite) run;) + +#bin: $(EXEC_LIST) + +#include ../subdir.mk diff --git a/FreeRTOS/Test/CMock/tasks/tasks_1_utest.c b/FreeRTOS/Test/CMock/tasks/tasks_1_utest.c index 901dc26cf..e3f29d108 100644 --- a/FreeRTOS/Test/CMock/tasks/tasks_1_utest.c +++ b/FreeRTOS/Test/CMock/tasks/tasks_1_utest.c @@ -32,13 +32,17 @@ #include "fake_port.h" #include "task.h" +/* Mock includes. */ #include "mock_list.h" #include "mock_list_macros.h" #include "mock_timers.h" #include "mock_portable.h" +#include "mock_fake_assert.h" +#include "mock_fake_infiniteloop.h" /* Test includes. */ #include "unity.h" +#include "CException.h" #include "global_vars.h" /* C runtime includes. */ @@ -65,7 +69,6 @@ extern volatile TickType_t xTickCount; extern volatile UBaseType_t uxTopReadyPriority; extern volatile BaseType_t xSchedulerRunning; extern volatile TickType_t xPendedTicks; - #ifdef configNUMBER_OF_CORES extern volatile BaseType_t xYieldPendings[]; #define xYieldPending xYieldPendings[ 0 ] @@ -75,7 +78,6 @@ extern volatile TickType_t xPendedTicks; extern volatile BaseType_t xNumOfOverflows; extern UBaseType_t uxTaskNumber; extern volatile TickType_t xNextTaskUnblockTime; - #ifdef configNUMBER_OF_CORES extern TaskHandle_t xIdleTaskHandles[]; #define xIdleTaskHandle xIdleTaskHandles[ 0 ] @@ -118,6 +120,11 @@ extern volatile UBaseType_t uxSchedulerSuspended; #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) #define TCB_ARRAY 10 /* simulate up to 10 tasks: add more if needed */ +/** + * @brief CException code for when a configASSERT should be intercepted. + */ +#define configASSERT_E 0xAA101 + /* =========================== GLOBAL VARIABLES =========================== */ static StaticTask_t xIdleTaskTCB; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; @@ -151,6 +158,18 @@ static bool port_allocate_secure_context_called = false; static bool port_assert_if_in_isr_called = false; static bool vApplicationMallocFailedHook_called = false; +/** + * @brief Global counter for the number of assertions in code. + */ +static int assertionFailed = 0; + +/** + * @brief Flag which denotes if test need to abort on assertion. + */ +static BaseType_t shouldAbortOnAssertion = pdFALSE; + +/* ============================ EXTERN FUNCTIONS ========================== */ +extern void prvCheckTasksWaitingTermination( void ); /* ============================ HOOK FUNCTIONS ============================ */ static void dummy_operation() @@ -163,7 +182,7 @@ void vFakePortAssertIfISR( void ) HOOK_DIAG(); } -void port_allocate_secure_context( BaseType_t stackSize ) +void vFakePortAllocateSecureContext( BaseType_t stackSize ) { HOOK_DIAG(); port_allocate_secure_context_called = true; @@ -259,10 +278,11 @@ void vFakePortYieldFromISR() HOOK_DIAG(); } -void vFakePortDisableInterrupts() +uint32_t vFakePortDisableInterrupts() { port_disable_interrupts_called = true; HOOK_DIAG(); + return 0; } void vFakePortEnableInterrupts() @@ -323,10 +343,53 @@ void vApplicationStackOverflowHook( TaskHandle_t xTask, vApplicationStackOverflowHook_called = true; } +unsigned int vFakePortGetCoreID( void ) +{ + HOOK_DIAG(); + return 0; +} + +void vFakePortReleaseTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetISRLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortReleaseISRLock( void ) +{ + HOOK_DIAG(); +} + +static void vFakeAssertStub( bool x, + char * file, + int line, + int cmock_num_calls ) +{ + if( !x ) + { + assertionFailed++; + + if( shouldAbortOnAssertion == pdTRUE ) + { + Throw( configASSERT_E ); + } + } +} + /* ============================ Unity Fixtures ============================ */ /*! called before each testcase */ void setUp( void ) { + vFakeAssert_StubWithCallback( vFakeAssertStub ); RESET_ALL_HOOKS(); pxCurrentTCB = NULL; memset( &tcb, 0x00, sizeof( TCB_t ) * TCB_ARRAY ); @@ -335,10 +398,6 @@ void setUp( void ) memset( &xDelayedTaskList1, 0x00, sizeof( List_t ) ); memset( &xDelayedTaskList2, 0x00, sizeof( List_t ) ); - /* - * pxDelayedTaskList = NULL; - * pxOverflowDelayedTaskList = NULL; - */ memset( &xPendingReadyList, 0x00, sizeof( List_t ) ); memset( &xTasksWaitingTermination, 0x00, sizeof( List_t ) ); @@ -944,6 +1003,71 @@ void test_vTaskDelete_success_not_current_task_no_yield( void ) ASSERT_PORT_YIELD_WITHIN_API_NOT_CALLED(); } +/** + * @brief prvCheckTasksWaitingTermination - no waiting task. + * + * No task is waiting to be deleted. This test show it's result in the coverage + * report. + * + * Coverage + * @code{c} + * while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + * { + * ... + * } + * @endcode + * ( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) is false. + */ +void test_prvCheckTasksWaitingTermination_no_waiting_task( void ) +{ + /* Setup the variables and structure. */ + uxDeletedTasksWaitingCleanUp = 0; + + /* API Call. */ + prvCheckTasksWaitingTermination(); + + /* Validation. */ + + /* No task is waiting to be cleaned up. Nothing will be updated in this API. This + * test case shows its result in the coverage report. */ +} + +/** + * @brief prvCheckTasksWaitingTermination - delete waiting task. + * + * A task is waiting to be deleted. The number of tasks and number of tasks waiting to + * be deleted are verified in this test case. + * + * Coverage + * @code{c} + * while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + * { + * ... + * } + * @endcode + * ( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) is true. + */ +void test_prvCheckTasksWaitingTermination_delete_waiting_task( void ) +{ + ptcb = ( TCB_t * ) create_task(); + + /* Setup the variables and structure. */ + uxDeletedTasksWaitingCleanUp = 1; + uxCurrentNumberOfTasks = 1; + + /* Expectations. */ + listGET_OWNER_OF_HEAD_ENTRY_ExpectAnyArgsAndReturn( ptcb ); + uxListRemove_ExpectAndReturn( &ptcb->xStateListItem, 0 ); + vPortFree_Expect( stack ); + vPortFree_Expect( ptcb ); + + /* API Call. */ + prvCheckTasksWaitingTermination(); + + /* Validation. */ + TEST_ASSERT_EQUAL( uxDeletedTasksWaitingCleanUp, 0 ); + TEST_ASSERT_EQUAL( uxCurrentNumberOfTasks, 0 ); +} void test_vTaskStartScheduler_success( void ) { @@ -2934,6 +3058,7 @@ void test_pcTaskGetName_success_null_handle( void ) ret_task_name = pcTaskGetName( NULL ); TEST_ASSERT_EQUAL_STRING( "create_task", ret_task_name ); } + void test_xTaskCatchUpTicks( void ) { BaseType_t ret_taskCatchUpTicks; @@ -2941,11 +3066,18 @@ void test_xTaskCatchUpTicks( void ) task_handle = create_task(); ptcb = task_handle; - uxSchedulerSuspended = pdTRUE; + uxSchedulerSuspended = pdFALSE; + + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdTRUE ); + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); + /* API Call */ - ret_taskCatchUpTicks = xTaskCatchUpTicks( 500 ); + ret_taskCatchUpTicks = xTaskCatchUpTicks( 1 ); /* Validations */ TEST_ASSERT_EQUAL( pdFALSE, ret_taskCatchUpTicks ); + /*TEST_ASSERT_EQUAL( pdTRUE, ret_taskCatchUpTicks ); */ + uxSchedulerSuspended = pdTRUE; } void test_xTaskIncrementTick_success_sched_suspended_no_switch( void ) @@ -2975,11 +3107,11 @@ void test_xTaskIncrementTick_success_tickCount_overlow( void ) overflow = pxOverflowDelayedTaskList; xTickCount = UINT32_MAX; /* overflowed */ create_task(); - /* Expectations */ - /* prvResetNextTaskUnblockTime */ + /* taskSWITCH_DELAYED_LISTS */ listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); /* back */ + listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ pxCurrentTCB->uxPriority ], 2 ); /* API Call */ @@ -3030,6 +3162,8 @@ void test_xTaskIncrementTick_success_switch( void ) xTickCount = UINT32_MAX; /* Expectations */ + /* taskSWITCH_DELAYED_LISTS(); */ + listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ ptcb->uxPriority ], 3 ); @@ -3167,6 +3301,71 @@ void test_xTaskIncrementTick_success_unblock_tasks2( void ) TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); } +/** + * @brief xTaskIncrementTick - Ready a higher priority delayed task. + * + * Ready a higher priority delayed task. Verify the return value is pdTRUE. + * + * Coverage + * @code{c} + * if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + * { + * xSwitchRequired = pdTRUE; + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * @endcode + * ( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) is true. + */ +void test_xTaskIncrementTick_success_unblock_higher_prio_task( void ) +{ + BaseType_t ret_task_incrementtick; + TaskHandle_t task_handle; + TaskHandle_t task_handle2; + + /* setup */ + create_task_priority = 2; + task_handle = create_task(); + create_task_priority = 1; + task_handle2 = create_task(); + + /* task_handle 2 will be added to pxDelayedTaskList later. To wakeup a higher priority + * task, uxPriority is set higher than current task, which is 2. */ + task_handle2->uxPriority = 3; + ptcb = task_handle; + xPendedTicks = 0; + xTickCount = 50; + xNextTaskUnblockTime = 49; /* tasks due unblocking */ + uxSchedulerSuspended = pdFALSE; + + /* Expectations */ + listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdFALSE ); + listGET_OWNER_OF_HEAD_ENTRY_ExpectAndReturn( pxDelayedTaskList, task_handle2 ); + listGET_LIST_ITEM_VALUE_ExpectAndReturn( &task_handle2->xStateListItem, + xTickCount - 5 ); + listREMOVE_ITEM_Expect( &( task_handle2->xStateListItem ) ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &task_handle2->xEventListItem, + &xPendingReadyList ); + listREMOVE_ITEM_Expect( &( task_handle2->xEventListItem ) ); + /* prvAddTaskToReadyList */ + listINSERT_END_Expect( &pxReadyTasksLists[ task_handle2->uxPriority ], + &task_handle2->xStateListItem ); + listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); + /* back */ + listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ ptcb->uxPriority ], + 1 ); + + /* API Call */ + ret_task_incrementtick = xTaskIncrementTick(); + + /* Validations */ + TEST_ASSERT_EQUAL( pdTRUE, ret_task_incrementtick ); + ASSERT_APP_TICK_HOOK_CALLED(); + TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); +} + /* Tests the scenario when a task with priority higher than the * currently executing task is unblocked as a result of the * xTaskIncrementTick call. Also, xPendedTicks is set to @@ -3483,6 +3682,7 @@ void test_vTaskSwitchContext( void ) pxCurrentTCB->pxTopOfStack = pxCurrentTCB->pxStack + 4; \ /* Expectations */ + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); /* API Call */ vTaskSwitchContext(); @@ -3517,6 +3717,7 @@ void test_vTaskSwitchContext_detect_overflow( void ) uxSchedulerSuspended = pdFALSE; pxCurrentTCB->pxTopOfStack = pxCurrentTCB->pxStack; /* Expectations */ + listCURRENT_LIST_LENGTH_ExpectAnyArgsAndReturn( 0 ); /* API Call */ vTaskSwitchContext(); @@ -3558,6 +3759,8 @@ void test_vTaskPlaceOnUnorderedEventList( void ) ptcb = task_handle; xNextTaskUnblockTime = 600; + uxSchedulerSuspended = pdTRUE; + /* Expectations */ listSET_LIST_ITEM_VALUE_Expect( &ptcb->xEventListItem, 32 | 0x80000000UL ); listINSERT_END_Expect( &eventList, &ptcb->xEventListItem ); @@ -3886,8 +4089,30 @@ void test_vTaskMissedYield( void ) TEST_ASSERT_TRUE( xYieldPending ); } -/* TODO: find a way to fix the idle task UnitTest as it is an infinite loop */ -void ignore_test_prvIdleTask_yield( void ) +/** + * @brief prvIdleTask - yield + * + * Test prvIdleTask yield for other idle level priority task. + * + * Coverage + * @code{c} + * #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + * { + * ... + * if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) + * { + * taskYIELD(); + * } + * else + * { + * mtCOVERAGE_TEST_MARKER(); + * } + * } + * #endif + * @endcode + * ( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) is true. + */ +void test_prvIdleTask_yield( void ) { int i = 8; void * args = &i; @@ -3895,25 +4120,92 @@ void ignore_test_prvIdleTask_yield( void ) create_task_priority = 3; create_task(); - /* Setup */ + /* Setup. */ uxDeletedTasksWaitingCleanUp = 0; portTASK_FUNCTION( prvIdleTask, args ); ( void ) fool_static2; - /* Expectations */ + + /* Expectations. */ + /* INFINITE_LOOP in prvIdleTask. */ + vFakeInfiniteLoop_ExpectAndReturn( 1 ); + + /* List function in prvIdleTask. */ listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 2 ); - listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 0 ); - /* prvGetExpectedIdleTime */ - listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 0 ); - listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 0 ); - listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 0 ); - listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 0 ); - /* API Call */ + + /* INFINITE_LOOP in prvIdleTask. */ + vFakeInfiniteLoop_ExpectAndReturn( 0 ); + + /* API Call. */ prvIdleTask( args ); - /* Validations */ + + /* Validations. */ ASSERT_PORT_ALLOCATE_SECURE_CONTEXT_CALLED(); ASSERT_PORT_YIELD_CALLED(); ASSERT_APPLICATION_IDLE_HOOK_CALLED(); } + +/** + * @brief prvIdleTask - tickless expected idle time + * + * Test prvIdleTask expected idle time condition. + * + * Coverage + * @code{c} + * #if ( configUSE_TICKLESS_IDLE != 0 ) + * { + * TickType_t xExpectedIdleTime; + * ... + * xExpectedIdleTime = prvGetExpectedIdleTime(); + * + * if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + * { + * vTaskSuspendAll(); + * { + * #endif + * @endcode + * ( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) is true. + */ +void test_prvIdleTask_tickless_expected_idle_time( void ) +{ + int i = 8; + void * args = &i; + + create_task_priority = 0; + create_task(); + + /* Setup. */ + uxTopReadyPriority = 0; + xTickCount = 0; + xNextTaskUnblockTime = configEXPECTED_IDLE_TIME_BEFORE_SLEEP + 1; + uxDeletedTasksWaitingCleanUp = 0; + portTASK_FUNCTION( prvIdleTask, args ); + ( void ) fool_static2; + + /* Expectations. */ + /* INFINITE_LOOP in prvIdleTask. */ + vFakeInfiniteLoop_ExpectAndReturn( 1 ); + + /* List function in prvIdleTask. */ + listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 1 ); + + /* List functions in prvGetExpectedIdleTime. */ + listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 1 ); + listCURRENT_LIST_LENGTH_ExpectAndReturn( &pxReadyTasksLists[ 0 ], 1 ); + + /* List functions in xTaskResumeAll */ + listLIST_IS_EMPTY_ExpectAndReturn( &xPendingReadyList, pdTRUE ); + + /* INFINITE_LOOP in prvIdleTask. */ + vFakeInfiniteLoop_ExpectAndReturn( 0 ); + + /* API Call. */ + prvIdleTask( args ); + + /* Validations. */ + ASSERT_PORT_ALLOCATE_SECURE_CONTEXT_CALLED(); + ASSERT_APPLICATION_IDLE_HOOK_CALLED(); +} + /* implement */ /*configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); */ @@ -4683,8 +4975,11 @@ void test_xTaskGenericNotify_success_null_pull( void ) /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], &ptcb->xStateListItem ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); /* prvResetNextTaskUnblockTime */ listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); + /* API Call */ ret_task_notify = xTaskGenericNotify( ptcb, uxIndexToNotify, @@ -4715,6 +5010,8 @@ void test_xTaskGenericNotify_success_eIncrement( void ) /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], &ptcb->xStateListItem ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); /* prvResetNextTaskUnblockTime */ listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); /* API Call */ @@ -4747,6 +5044,8 @@ void test_xTaskGenericNotify_success_eSetValueWithOverwrite( void ) /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], &ptcb->xStateListItem ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); /* prvResetNextTaskUnblockTime */ listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); /* API Call */ @@ -4779,6 +5078,8 @@ void test_xTaskGenericNotify_success_eSetValueWithoutOverwrite( void ) /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], &ptcb->xStateListItem ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); /* prvResetNextTaskUnblockTime */ listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); /* API Call */ @@ -4869,6 +5170,8 @@ void test_xTaskGenericNotify_success_default( void ) /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], &ptcb->xStateListItem ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); /* prvResetNextTaskUnblockTime */ listLIST_IS_EMPTY_ExpectAndReturn( pxDelayedTaskList, pdTRUE ); /* API Call */ @@ -4931,7 +5234,10 @@ void test_xTaskGenericNotify_success_null_pull_ISR( void ) ptcb = task_to_notify; vTaskSuspendAll(); /* Expectations */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listINSERT_END_Expect( &xPendingReadyList, &ptcb->xEventListItem ); + /* API Call */ ret_task_notify = xTaskGenericNotifyFromISR( ptcb, uxIndexToNotify, @@ -4963,10 +5269,14 @@ void test_xTaskGenericNotify_success_eIncrement_ISR( void ) task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; ptcb = task_to_notify; /* Expectations */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listREMOVE_ITEM_Expect( &( ptcb->xStateListItem ) ); + /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], &ptcb->xStateListItem ); + /* API Call */ ret_task_notify = xTaskGenericNotifyFromISR( ptcb, uxIndexToNotify, @@ -4998,6 +5308,8 @@ void test_xTaskGenericNotify_success_eSetValueWithOverwrite_ISR( void ) task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; ptcb = task_to_notify; /* Expectations */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listREMOVE_ITEM_Expect( &( ptcb->xStateListItem ) ); /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], @@ -5033,6 +5345,8 @@ void test_xTaskGenericNotify_success_eSetValueWithoutOverwrite_ISR( void ) task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; ptcb = task_to_notify; /* Expectations */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listREMOVE_ITEM_Expect( &( ptcb->xStateListItem ) ); /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], @@ -5140,6 +5454,8 @@ void test_xTaskGenericNotify_success_default_ISR( void ) task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; ptcb = task_to_notify; /* Expectations */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listREMOVE_ITEM_Expect( &( ptcb->xStateListItem ) ); /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], @@ -5183,6 +5499,8 @@ void test_xTaskGenericNotify_success_default_ISR_task_woken_null( void ) task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; ptcb = task_to_notify; /* Expectations */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listREMOVE_ITEM_Expect( &( ptcb->xStateListItem ) ); /* prvAddTaskToReadyList */ listINSERT_END_Expect( &pxReadyTasksLists[ ptcb->uxPriority ], @@ -5365,11 +5683,16 @@ void test_vTaskGenericNotifyGiveFromISR_success( void ) /* Setup */ task_to_notify = create_task(); task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + ptcb = task_to_notify; /* Expectations */ + /* configASSERT statement */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); /*uxListRemove_ExpectAndReturn( &task_to_notify->xStateListItem, pdTRUE ); */ listREMOVE_ITEM_Expect( &( task_to_notify->xStateListItem ) ); /* prvAddTaskToReadyList */ listINSERT_END_Expect( &xPendingReadyList, &task_to_notify->xEventListItem ); + /* API Call */ vTaskGenericNotifyGiveFromISR( task_to_notify, uxIndexToNotify, @@ -5391,8 +5714,12 @@ void test_vTaskGenericNotifyGiveFromISR_success_scheduler_suspended( void ) /* Setup */ task_to_notify = create_task(); task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; + ptcb = task_to_notify; vTaskSuspendAll(); /* Expectations */ + /* configASSERT statement */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listINSERT_END_Expect( &xPendingReadyList, &task_to_notify->xEventListItem ); /* API Call */ @@ -5425,7 +5752,11 @@ void test_vTaskGenericNotifyGiveFromISR_success_yield_pending( void ) task_to_notify->ucNotifyState[ uxIndexToNotify ] = taskWAITING_NOTIFICATION; ptcb = task_to_notify; vTaskSuspendAll(); + /* Expectations */ + /* configASSERT statement */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listINSERT_END_Expect( &xPendingReadyList, &task_to_notify->xEventListItem ); /* API Call */ @@ -5458,6 +5789,9 @@ void test_vTaskGenericNotifyGiveFromISR_success_null_higherpriority_task( void ) ptcb = task_to_notify; vTaskSuspendAll(); /* Expectations */ + /* configASSERT statement */ + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, + &xSuspendedTaskList ); listINSERT_END_Expect( &xPendingReadyList, &task_to_notify->xEventListItem ); /* API Call */ diff --git a/FreeRTOS/Test/CMock/tasks/tasks_2_utest.c b/FreeRTOS/Test/CMock/tasks/tasks_2_utest.c index 5ee618abd..2a9d38cce 100644 --- a/FreeRTOS/Test/CMock/tasks/tasks_2_utest.c +++ b/FreeRTOS/Test/CMock/tasks/tasks_2_utest.c @@ -35,9 +35,11 @@ #include "mock_list_macros.h" #include "mock_timers.h" #include "mock_portable.h" +#include "mock_fake_assert.h" /* Test includes. */ #include "unity.h" +#include "CException.h" #include "global_vars.h" /* C runtime includes. */ @@ -64,7 +66,6 @@ extern volatile TickType_t xTickCount; extern volatile UBaseType_t uxTopReadyPriority; extern volatile BaseType_t xSchedulerRunning; extern volatile TickType_t xPendedTicks; - #ifdef configNUMBER_OF_CORES extern volatile BaseType_t xYieldPendings[]; #define xYieldPending xYieldPendings[ 0 ] @@ -75,16 +76,19 @@ extern volatile TickType_t xPendedTicks; extern volatile BaseType_t xNumOfOverflows; extern UBaseType_t uxTaskNumber; extern volatile TickType_t xNextTaskUnblockTime; - #ifdef configNUMBER_OF_CORES extern TaskHandle_t xIdleTaskHandles[]; #define xIdleTaskHandle xIdleTaskHandles[ 0 ] #else extern TaskHandle_t xIdleTaskHandle; #endif - extern volatile UBaseType_t uxSchedulerSuspended; +/** + * @brief CException code for when a configASSERT should be intercepted. + */ +#define configASSERT_E 0xAA101 + /* =========================== GLOBAL VARIABLES =========================== */ static StaticTask_t xIdleTaskTCB; @@ -119,6 +123,16 @@ static bool port_assert_if_in_isr_called = false; static bool vApplicationMallocFailedHook_called = false; +/** + * @brief Global counter for the number of assertions in code. + */ +static int assertionFailed = 0; + +/** + * @brief Flag which denotes if test need to abort on assertion. + */ +static BaseType_t shouldAbortOnAssertion = pdFALSE; + /* =========================== Static Functions =========================== */ static void start_scheduler() { @@ -325,10 +339,11 @@ void vFakePortYieldFromISR() HOOK_DIAG(); } -void vFakePortDisableInterrupts() +uint32_t vFakePortDisableInterrupts() { port_disable_interrupts_called = true; HOOK_DIAG(); + return 0; } void vFakePortEnableInterrupts() @@ -389,6 +404,48 @@ void vApplicationStackOverflowHook( TaskHandle_t xTask, vApplicationStackOverflowHook_called = true; } +unsigned int vFakePortGetCoreID( void ) +{ + HOOK_DIAG(); + return 0; +} + +void vFakePortReleaseTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetISRLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortReleaseISRLock( void ) +{ + HOOK_DIAG(); +} + +static void vFakeAssertStub( bool x, + char * file, + int line, + int cmock_num_calls ) +{ + if( !x ) + { + assertionFailed++; + + if( shouldAbortOnAssertion == pdTRUE ) + { + Throw( configASSERT_E ); + } + } +} + /* ============================ Unity Fixtures ============================ */ /*! called before each testcase */ void setUp( void ) @@ -427,8 +484,9 @@ void setUp( void ) /*ulTotalRunTime = 0UL; */ is_first_task = true; created_tasks = 0; - py_operation = dummy_operation; + + vFakeAssert_StubWithCallback( vFakeAssertStub ); } /*! called after each testcase */ diff --git a/FreeRTOS/Test/CMock/tasks/tasks_assert_utest.c b/FreeRTOS/Test/CMock/tasks/tasks_assert_utest.c new file mode 100644 index 000000000..aabc5461d --- /dev/null +++ b/FreeRTOS/Test/CMock/tasks/tasks_assert_utest.c @@ -0,0 +1,1139 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file tasks_assert_utest.c */ + +/* =============================== INCLUDES =============================== */ +/* Tasks includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "fake_port.h" +#include "task.h" + +/* C runtime includes. */ +#include +#include +#include + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "CException.h" +#include "global_vars.h" + +/* Mock includes. */ +#include "mock_fake_assert.h" +#include "mock_portable.h" +#include "mock_list_macros.h" +#include "mock_list.h" +#include "mock_timers.h" + +/* ================================= MACROS =============================== */ + +/** + * @brief CException code for when a configASSERT should be intercepted. + */ +#define configASSERT_E 0xAA101 + +/** + * @brief simulate up to 10 tasks: add more if needed + * */ +#define TCB_ARRAY 10 + +/** + * @brief Expect a configASSERT from the function called. + * Break out of the called function when this occurs. + * @details Use this macro when the call passed in as a parameter is expected + * to cause invalid memory access. + */ +#define EXPECT_ASSERT_BREAK( call ) \ + do \ + { \ + shouldAbortOnAssertion = true; \ + CEXCEPTION_T e = CEXCEPTION_NONE; \ + Try \ + { \ + call; \ + TEST_FAIL(); \ + } \ + Catch( e ) \ + { \ + TEST_ASSERT_EQUAL( configASSERT_E, e ); \ + } \ + } while( 0 ) + +/* ============================ GLOBAL VARIABLES =========================== */ + +/** + * @brief Global counter for the number of assertions in code. + */ +static int assertionFailed = 0; + +/** + * @brief Flag which denotes if test need to abort on assertion. + */ +static BaseType_t shouldAbortOnAssertion; + +/** + * @brief counts entries to critical sections then subtracts from the variable + * when exiting, value should be zero at the end + */ +static uint32_t critical_section_counter = 0; + +static bool port_yield_within_api_called = false; +static port_yield_operation py_operation; +static bool port_disable_interrupts_called = false; +static bool port_enable_interrupts_called = false; +static bool port_yield_called = false; +static bool port_setup_tcb_called = false; +static bool portClear_Interrupt_called = false; +static bool portSet_Interrupt_called = false; +static bool portClear_Interrupt_from_isr_called = false; +static bool portSet_Interrupt_from_isr_called = false; +static bool port_invalid_interrupt_called = false; +static bool vApplicationStackOverflowHook_called = false; +static bool getIdleTaskMemoryValid = false; +static StaticTask_t xIdleTaskTCB; +static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; +static bool getIdleTaskMemory_called = false; +static bool vTaskDeletePre_called = false; +static bool vApplicationIdleHook_called = false; +static bool vApplicationTickHook_called = false; + +static uint32_t created_tasks = 0; +static TCB_t tcb[ TCB_ARRAY ]; +static uint32_t create_task_priority = 3; +static StackType_t stack[ ( ( size_t ) 300 ) * sizeof( StackType_t ) ]; +static bool is_first_task = true; + +/* ========================== EXTERN VARIABLES ============================ */ +extern volatile BaseType_t xSchedulerRunning; +extern volatile TickType_t xTickCount; +extern volatile TickType_t xNextTaskUnblockTime; +extern TCB_t * volatile pxCurrentTCB; +extern List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; + +extern List_t xSuspendedTaskList; +extern List_t xPendingReadyList; +extern List_t xDelayedTaskList1; +extern List_t xDelayedTaskList2; +extern List_t xTasksWaitingTermination; +extern List_t * volatile pxOverflowDelayedTaskList; + +extern volatile UBaseType_t uxSchedulerSuspended; + +extern volatile UBaseType_t uxCurrentNumberOfTasks; + +#if ( defined( configNUMBER_OF_CORES ) && ( configNUMBER_OF_CORES == 1 ) ) + extern TaskHandle_t xIdleTaskHandles[]; + #define xIdleTaskHandle xIdleTaskHandles[ 0 ] +#else + extern TaskHandle_t xIdleTaskHandle; +#endif + +/* ========================== CALLBACK FUNCTIONS ========================== */ +static void vFakeAssertStub( bool x, + char * file, + int line, + int cmock_num_calls ) +{ + if( !x ) + { + assertionFailed++; + + if( shouldAbortOnAssertion == pdTRUE ) + { + Throw( configASSERT_E ); + } + } +} + +/* ========================== STATIC FUNCTIONS ============================ */ +static void validate_and_clear_assertions( void ) +{ + TEST_ASSERT_EQUAL( 1, assertionFailed ); + assertionFailed = 0; +} + +static TaskHandle_t create_task() +{ + TaskFunction_t pxTaskCode = NULL; + const char * const pcName = { __FUNCTION__ }; + const uint32_t usStackDepth = 300; + void * const pvParameters = NULL; + UBaseType_t uxPriority = create_task_priority; + TaskHandle_t taskHandle; + BaseType_t ret; + + pvPortMalloc_ExpectAndReturn( usStackDepth * sizeof( StackType_t ), stack ); + pvPortMalloc_ExpectAndReturn( sizeof( TCB_t ), &tcb[ created_tasks ] ); + + vListInitialiseItem_Expect( &( tcb[ created_tasks ].xStateListItem ) ); + vListInitialiseItem_Expect( &( tcb[ created_tasks ].xEventListItem ) ); + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + + pxPortInitialiseStack_ExpectAnyArgsAndReturn( stack ); + + if( is_first_task ) + { + for( int i = ( UBaseType_t ) 0U; i < ( UBaseType_t ) configMAX_PRIORITIES; i++ ) + { + vListInitialise_ExpectAnyArgs(); + } + + /* Delayed Task List 1 */ + vListInitialise_ExpectAnyArgs(); + /* Delayed Task List 2 */ + vListInitialise_ExpectAnyArgs(); + /* Pending Ready List */ + vListInitialise_ExpectAnyArgs(); + /* INCLUDE_vTaskDelete */ + vListInitialise_ExpectAnyArgs(); + /* INCLUDE_vTaskSuspend */ + vListInitialise_ExpectAnyArgs(); + is_first_task = false; + } + + listINSERT_END_ExpectAnyArgs(); + + ret = xTaskCreate( pxTaskCode, + pcName, + usStackDepth, + pvParameters, + uxPriority, + &taskHandle ); + TEST_ASSERT_EQUAL( pdPASS, ret ); + ASSERT_SETUP_TCB_CALLED(); + created_tasks++; + return taskHandle; +} + +static void start_scheduler() +{ + vListInitialiseItem_ExpectAnyArgs(); + vListInitialiseItem_ExpectAnyArgs(); + /* set owner */ + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + /* set owner */ + + pxPortInitialiseStack_ExpectAnyArgsAndReturn( uxIdleTaskStack ); + + if( is_first_task ) + { + is_first_task = false; + + for( int i = ( UBaseType_t ) 0U; i < ( UBaseType_t ) configMAX_PRIORITIES; i++ ) + { + vListInitialise_ExpectAnyArgs(); + } + + /* Delayed Task List 1 */ + vListInitialise_ExpectAnyArgs(); + /* Delayed Task List 2 */ + vListInitialise_ExpectAnyArgs(); + /* Pending Ready List */ + vListInitialise_ExpectAnyArgs(); + /* INCLUDE_vTaskDelete */ + vListInitialise_ExpectAnyArgs(); + /* INCLUDE_vTaskSuspend */ + vListInitialise_ExpectAnyArgs(); + } + + listINSERT_END_ExpectAnyArgs(); + + xTimerCreateTimerTask_ExpectAndReturn( pdPASS ); + xPortStartScheduler_ExpectAndReturn( pdTRUE ); + getIdleTaskMemoryValid = true; + vTaskStartScheduler(); + ASSERT_GET_IDLE_TASK_MEMORY_CALLED(); + TEST_ASSERT_TRUE( xSchedulerRunning ); + TEST_ASSERT_EQUAL( configINITIAL_TICK_COUNT, xTickCount ); + TEST_ASSERT_EQUAL( portMAX_DELAY, xNextTaskUnblockTime ); +} + + + +/* ======================== HOOK FUNCTIONS =================================*/ +void vApplicationTickHook() +{ + HOOK_DIAG(); + vApplicationTickHook_called = true; +} + +void vApplicationIdleHook( void ) +{ + HOOK_DIAG(); + vApplicationIdleHook_called = true; +} + +void vConfigureTimerForRunTimeStats( void ) +{ + HOOK_DIAG(); +} + +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) +{ + HOOK_DIAG(); + + if( getIdleTaskMemoryValid == true ) + { + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + * state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + } + else + { + *ppxIdleTaskTCBBuffer = NULL; + *ppxIdleTaskStackBuffer = NULL; + *pulIdleTaskStackSize = 0; + } + + getIdleTaskMemory_called = true; +} + +void vPortCurrentTaskDying( void * pvTaskToDelete, + volatile BaseType_t * pxPendYield ) +{ + HOOK_DIAG(); + vTaskDeletePre_called = true; +} + +void vFakePortEnterCriticalSection( void ) +{ + HOOK_DIAG(); + critical_section_counter++; +} + +void vFakePortExitCriticalSection( void ) +{ + HOOK_DIAG(); + critical_section_counter--; +} + +void vFakePortYieldWithinAPI() +{ + HOOK_DIAG(); + port_yield_within_api_called = true; + py_operation(); +} + +void vFakePortYieldFromISR() +{ + HOOK_DIAG(); +} + +uint32_t vFakePortDisableInterrupts() +{ + port_disable_interrupts_called = true; + HOOK_DIAG(); + return 0; +} + +void vFakePortEnableInterrupts() +{ + port_enable_interrupts_called = true; + HOOK_DIAG(); +} + +void vFakePortYield() +{ + HOOK_DIAG(); + port_yield_called = true; + py_operation(); +} + +void portSetupTCB_CB( void * tcb ) +{ + HOOK_DIAG(); + port_setup_tcb_called = true; +} + +void vFakePortClearInterruptMask( UBaseType_t bt ) +{ + HOOK_DIAG(); + portClear_Interrupt_called = true; +} + +UBaseType_t ulFakePortSetInterruptMask( void ) +{ + HOOK_DIAG(); + portSet_Interrupt_called = true; + return 1; +} + +void vFakePortClearInterruptMaskFromISR( UBaseType_t bt ) +{ + HOOK_DIAG(); + portClear_Interrupt_from_isr_called = true; +} + +UBaseType_t ulFakePortSetInterruptMaskFromISR( void ) +{ + HOOK_DIAG(); + portSet_Interrupt_from_isr_called = true; + return 1; +} + +void vFakePortAssertIfInterruptPriorityInvalid( void ) +{ + HOOK_DIAG(); + port_invalid_interrupt_called = true; +} + +void vApplicationStackOverflowHook( TaskHandle_t xTask, + char * stack ) +{ + HOOK_DIAG(); + vApplicationStackOverflowHook_called = true; +} + +unsigned int vFakePortGetCoreID( void ) +{ + HOOK_DIAG(); + return 0; +} + +void vFakePortReleaseTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetISRLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortReleaseISRLock( void ) +{ + HOOK_DIAG(); +} + +/* =========================== UNITY FIXTURES ============================= */ +/*! called before each test case */ +void setUp( void ) +{ + assertionFailed = 0; + shouldAbortOnAssertion = pdTRUE; + created_tasks = 0; + is_first_task = true; + pxCurrentTCB = NULL; + memset( &pxReadyTasksLists, 0x00, configMAX_PRIORITIES * sizeof( List_t ) ); + memset( &xDelayedTaskList1, 0x00, sizeof( List_t ) ); + memset( &xDelayedTaskList2, 0x00, sizeof( List_t ) ); + memset( &xSuspendedTaskList, 0x00, sizeof( List_t ) ); + memset( &xPendingReadyList, 0x00, sizeof( List_t ) ); + memset( &xTasksWaitingTermination, 0x00, sizeof( List_t ) ); + uxCurrentNumberOfTasks = 0; + uxSchedulerSuspended = pdFALSE; + vFakeAssert_StubWithCallback( vFakeAssertStub ); +} + +/*! called after each test case */ +void tearDown( void ) +{ + TEST_ASSERT_EQUAL_MESSAGE( 0, assertionFailed, "Assertion check failed in code." ); + + mock_fake_assert_Verify(); + mock_fake_assert_Destroy(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ======================== TEST CASES ===================================== */ + +/*! + * @brief This function ensures that the code asserts if the handle name is + * greater than configMAX_TASK_NAME_LEN + */ +void test_xTaskGetHandle_assert_large_handle_name( void ) +{ + int bigSize = configMAX_TASK_NAME_LEN + 5; + char handleName[ bigSize ]; + int i; + + for( i = 0; i < bigSize; ++i ) + { + handleName[ i ] = 'a'; + } + + handleName[ bigSize - 1 ] = '\0'; + + EXPECT_ASSERT_BREAK( ( void ) xTaskGetHandle( handleName ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief this function ensures that the code asserts if the value of + * uxSchedulerSuspended is 1 + */ +void test_xTaskResumeAll_assert_scheduler_not_started( void ) +{ + EXPECT_ASSERT_BREAK( ( void ) xTaskResumeAll() ); + + validate_and_clear_assertions(); +} + +void test_vTaskGenericNotifyGiveFromISR_assert_xTaskNotify_NULL( void ) +{ + BaseType_t pxHigherPriorityTaskWoken; + + EXPECT_ASSERT_BREAK( vTaskGenericNotifyGiveFromISR( NULL, + 1, + &pxHigherPriorityTaskWoken ) ); + + validate_and_clear_assertions(); +} + +void test_vTaskGenericNotifyGiveFromISR_assert_uxIndexToNotify_out_of_bound( void ) +{ + BaseType_t pxHigherPriorityTaskWoken; + + TaskHandle_t xTaskToNotify = ( TaskHandle_t ) 0x1234; + + EXPECT_ASSERT_BREAK( vTaskGenericNotifyGiveFromISR( xTaskToNotify, + configTASK_NOTIFICATION_ARRAY_ENTRIES + 1, + &pxHigherPriorityTaskWoken ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if the scheduler is running, + * the current TCB is the TCB to delete and the scheduler is not + * suspended + */ +void test_vTaskDelete_assert_schedulerSuspended( void ) +{ + TCB_t * ptcb = create_task(); + + start_scheduler(); + + uxListRemove_ExpectAndReturn( &ptcb->xStateListItem, pdPASS ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, NULL ); + vListInsertEnd_ExpectAnyArgs(); + + vTaskSuspendAll(); + + EXPECT_ASSERT_BREAK( vTaskDelete( ptcb ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if pxPreviousWakeTime is equal + * to NULL + */ +void test_vTaskDelayUntil_assert_pxPreviousWakeTime_NULL( void ) +{ + EXPECT_ASSERT_BREAK( xTaskDelayUntil( NULL, 23 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if xTimeIncrement is less than + * or equal to zero + */ +void test_vTaskDelayUntil_assert_xTimeIncrement_lte_zero( void ) +{ + TickType_t xPreviousWakeTime; + + EXPECT_ASSERT_BREAK( xTaskDelayUntil( &xPreviousWakeTime, 0 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if uxSchedulerSuspended is not + * equal to 1 + */ +void test_vTaskDelayUntil_assert_uxSchedulerSuspended_neq_1( void ) +{ + TickType_t xPreviousWakeTime; + + vTaskSuspendAll(); + + EXPECT_ASSERT_BREAK( xTaskDelayUntil( &xPreviousWakeTime, 6 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if uxSchedulerSuspended is not + * equal to 1 + */ +void test_vTaskDelay_assert_uxSchedulerSuspended_neq_1( void ) +{ + vTaskSuspendAll(); + + EXPECT_ASSERT_BREAK( vTaskDelay( 23 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if uxSchedulerSuspended is not + * equal to 1 + */ +void test_eTaskGetState_assert_TCB_ne_NULL( void ) +{ + EXPECT_ASSERT_BREAK( eTaskGetState( NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if uxSchedulerSuspended is not + * equal to 1 + */ +void test_vTaskSuspend_assert_scheduler_suspended_neq_zero( void ) +{ + TCB_t * ptcb = create_task(); + + uxSchedulerSuspended = 1; + uxListRemove_ExpectAnyArgsAndReturn( 1 ); + listLIST_ITEM_CONTAINER_ExpectAndReturn( &ptcb->xEventListItem, NULL ); + vListInsertEnd_ExpectAnyArgs(); + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdTRUE ); + + EXPECT_ASSERT_BREAK( vTaskSuspend( ptcb ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if we pass NULL as a parameter + * to vTaskResume + */ +void test_vTaskResume_assert_null_xTaskToResume_handle( void ) +{ + EXPECT_ASSERT_BREAK( vTaskResume( NULL ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts if we pass NULL as a parameter + * to xTaskResumeFromISR + */ +void test_xTaskResumeFromISR_assert_null_xTaskToResume_handle( void ) +{ + EXPECT_ASSERT_BREAK( xTaskResumeFromISR( NULL ) ); + + validate_and_clear_assertions(); +} + + +/*! + * @brief This test ensures that the code asserts when vTaskStartScheduler + * is creating a new idle task or timer task and + * it returns errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY + */ +void test_vTaskStartScheduler_assert_could_not_allocate_memory( void ) +{ + vListInitialiseItem_ExpectAnyArgs(); + vListInitialiseItem_ExpectAnyArgs(); + /* set owner */ + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + /* set owner */ + + pxPortInitialiseStack_ExpectAnyArgsAndReturn( uxIdleTaskStack ); + + if( is_first_task ) + { + is_first_task = false; + + for( int i = ( UBaseType_t ) 0U; i < ( UBaseType_t ) configMAX_PRIORITIES; i++ ) + { + vListInitialise_ExpectAnyArgs(); + } + + /* Delayed Task List 1 */ + vListInitialise_ExpectAnyArgs(); + /* Delayed Task List 2 */ + vListInitialise_ExpectAnyArgs(); + /* Pending Ready List */ + vListInitialise_ExpectAnyArgs(); + /* INCLUDE_vTaskDelete */ + vListInitialise_ExpectAnyArgs(); + /* INCLUDE_vTaskSuspend */ + vListInitialise_ExpectAnyArgs(); + } + + listINSERT_END_ExpectAnyArgs(); + + xTimerCreateTimerTask_ExpectAndReturn( errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ); + EXPECT_ASSERT_BREAK( vTaskStartScheduler() ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when we pass NULL as a task + * handle to pcTaskGetName + */ +void test_pcTaskGetName_assert_xTaskToQuery_is_null( void ) +{ + EXPECT_ASSERT_BREAK( pcTaskGetName( NULL ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the idle task + * could not be created (handle = NULL) and then + * we call xTaskGetIdleTaskHandle + */ +void test_xTaskGetIdleTaskHandle_assert_xIdleTaskHandles_0_is_null( void ) +{ + xIdleTaskHandles[ 0 ] = NULL; /* idle task is not created */ + + EXPECT_ASSERT_BREAK( xTaskGetIdleTaskHandle() ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when xTaskCatchUpTicks is + * called and the scheduler is suspended + */ +void test_xTaskCatchUpTicks_assert_scheduler_suspended( void ) +{ + uxSchedulerSuspended = 1; + EXPECT_ASSERT_BREAK( xTaskCatchUpTicks( 23 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when we call xTaskAbortDelay + * with xTask equals to NULL + */ +void test_xTaskAbortDelay_assert_xTask_null( void ) +{ + EXPECT_ASSERT_BREAK( xTaskAbortDelay( NULL ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when vTaskPlaceOnEventList is + * called with pxEventList equals to NULL + */ +void test_vTaskPlaceOnEventList_assert_pxEventList_null( void ) +{ + EXPECT_ASSERT_BREAK( vTaskPlaceOnEventList( NULL, 2 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when we call + * vTaskPlaceOnEventList with pxEventList equals to NULL + */ +void test_vTaskPlaceOnUnorderedEventList_assert_pxEventList_null( void ) +{ + EXPECT_ASSERT_BREAK( vTaskPlaceOnUnorderedEventList( NULL, 2, 3 ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when + * vTaskPlaceOnUnorderedEventList is called while the scheduler is + * not suspended + */ +void test_vTaskPlaceOnUnorderedEventList_assert_scheduler_suspended_eq_zero( void ) +{ + List_t xEventList; + + EXPECT_ASSERT_BREAK( vTaskPlaceOnUnorderedEventList( &xEventList, 2, 3 ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when + * vTaskPlaceOnEventListRestricted is called with pxEventList is equal to NULL + */ +void test_vTaskPlaceOnEventListRestricted_assert_pxEventList_eq_NULL( void ) +{ + EXPECT_ASSERT_BREAK( vTaskPlaceOnEventListRestricted( NULL, 2, 3 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the list head entry for + * xEventList is NULL + */ +void test_xTaskRemoveFromEventList_assert_event_list_head_entry_null( void ) +{ + List_t xEventList; + + listGET_OWNER_OF_HEAD_ENTRY_ExpectAnyArgsAndReturn( NULL ); + + EXPECT_ASSERT_BREAK( xTaskRemoveFromEventList( &xEventList ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when + * vTaskRemoveFromUnorderedEventList and the scheduler is not suspended + */ +void test_vTaskRemoveFromUnorderedEventList_assert_scheduler_running( void ) +{ + ListItem_t xEventListItem; + + uxSchedulerSuspended = pdFALSE; + + EXPECT_ASSERT_BREAK( vTaskRemoveFromUnorderedEventList( &xEventListItem, 2 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when pxUnblockedTCB is null + */ +void test_vTaskRemoveFromUnorderedEventList_assert_( void ) +{ + ListItem_t xEventListItem; + + uxSchedulerSuspended = pdTRUE; + + listSET_LIST_ITEM_VALUE_ExpectAnyArgs(); + listGET_LIST_ITEM_OWNER_ExpectAnyArgsAndReturn( NULL ); + + EXPECT_ASSERT_BREAK( vTaskRemoveFromUnorderedEventList( &xEventListItem, 2 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when vTaskSettimeOutState is + * called with a timeout of zero + */ +void test_vTaskSetTimeOutState_assert_timeout_zero( void ) +{ + EXPECT_ASSERT_BREAK( vTaskSetTimeOutState( 0 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when pxTimeout is NULL + */ +void test_xTaskCheckForTimeOut_assert_pxTimeOut_null( void ) +{ + TickType_t pxTicksToWait; + + EXPECT_ASSERT_BREAK( xTaskCheckForTimeOut( NULL, &pxTicksToWait ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when pxTicksToWait is NULL + */ +void test_xTaskCheckForTimeOut_assert_pxTicksToWait_null( void ) +{ + TimeOut_t xTimeOut; + + EXPECT_ASSERT_BREAK( xTaskCheckForTimeOut( &xTimeOut, NULL ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the passed tcb is not + * equal to the current tcb + */ +void test_xTaskPriorityDisinherit_assert_tcp_neq_current_tcb( void ) +{ + create_task(); + TCB_t * ptcb2 = create_task(); + + EXPECT_ASSERT_BREAK( xTaskPriorityDisinherit( ptcb2 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when xTaskPriorityDisinherit + * is called with no help mutexes + */ +void test_xTaskPriorityDisinherit_assert_no_mutexes_are_held( void ) +{ + TCB_t * ptcb = create_task(); + + EXPECT_ASSERT_BREAK( xTaskPriorityDisinherit( ptcb ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the tcb belinging to the + * handle is null, or just the handle itself is null + */ +void test_vTaskSetThreadLocalStoragePointer_assert_task_handle_null( void ) +{ + EXPECT_ASSERT_BREAK( vTaskSetThreadLocalStoragePointer( NULL, 1, NULL ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when a value that is not + * defined is assigned to TCB_t -> uxStaticallyAllocated + */ +void test_prvCheckTasksWaitingTermination_assert_out_of_bound_ucStaticallyAllocated( void ) + +{ + create_task(); + TCB_t * ptcb = create_task(); + + ptcb->ucStaticallyAllocated = 3; /* out of range value */ + + uxListRemove_ExpectAnyArgsAndReturn( pdTRUE ); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( NULL ); + listLIST_IS_EMPTY_ExpectAnyArgsAndReturn( pdTRUE ); + + EXPECT_ASSERT_BREAK( vTaskDelete( ptcb ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when no mutexes are help byt + * the tcb + */ +void test_vTaskPriorityDisinheritAfterTimeout_assert_no_held_mutexes( void ) +{ + TCB_t * ptcb = create_task(); + + EXPECT_ASSERT_BREAK( vTaskPriorityDisinheritAfterTimeout( ptcb, 3 ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when tcb is the current tcb + */ +void test_vTaskPriorityDisinheritAfterTimeout_assert_tcb_eq_currentTCB( void ) +{ + TCB_t * ptcb = create_task(); + + pxCurrentTCB = ptcb; + + pvTaskIncrementMutexHeldCount(); + + EXPECT_ASSERT_BREAK( vTaskPriorityDisinheritAfterTimeout( ptcb, 5 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when uxIndexToWait is greater + * than of equal to configTASK_NOTIFICATION_ARRAY_ENTRIES + */ +void test_ulTaskGenericNotifyTake_assert_index_gte_config_array_entries( void ) +{ + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES + 2; + + EXPECT_ASSERT_BREAK( ulTaskGenericNotifyTake( uxIndex, 23, 22 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when uxIndexToWait is greater + * than of equal to configTASK_NOTIFICATION_ARRAY_ENTRIES + */ +void test_xTaskGenericNotifyWait_assert_index_gte_config_array_entries( void ) +{ + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES + 2; + + EXPECT_ASSERT_BREAK( xTaskGenericNotifyWait( uxIndex, 23, 22, NULL, 23 ) ); + + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when uxIndexToNotify is + * greater than of equal to configTASK_NOTIFICATION_ARRAY_ENTRIES + */ +void test_xTaskGenericNotify_assert_index_gte_config_array_entries( void ) +{ + TCB_t * ptcb = create_task(); + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES + 2; + + EXPECT_ASSERT_BREAK( xTaskGenericNotify( ptcb, uxIndex, 23, + eSetBits, NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the task to notify is + * null + */ +void test_xTaskGenericNotify_assert_null_task_to_notify( void ) +{ + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES - 1; + + EXPECT_ASSERT_BREAK( xTaskGenericNotify( NULL, uxIndex, + 23, eSetBits, NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the default action is + * reached which we should never get there + */ +void test_xTaskGenericNotify_assert_default_action_tickcount_ne_zero( void ) +{ + TCB_t * ptcb = create_task(); + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES - 1; + + xTickCount = 3; + EXPECT_ASSERT_BREAK( xTaskGenericNotify( ptcb, uxIndex, 3, + eSetValueWithoutOverwrite + 1, + NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the task state is + * taskWAITING_NOTIFICATION and the task is on an event list + */ +void test_xTaskGenericNotify_assert( void ) +{ + TCB_t * ptcb = create_task(); + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES - 1; + + ptcb->ucNotifyState[ uxIndex ] = 1; /* taskWAITING_NOTIFICATION */ + xTickCount = 0; + + listREMOVE_ITEM_ExpectAnyArgs(); + listINSERT_END_ExpectAnyArgs(); + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( ( void * ) 1 ); + EXPECT_ASSERT_BREAK( xTaskGenericNotify( ptcb, uxIndex, 3, + eSetValueWithoutOverwrite + 1, + NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when uxIndexToNotify is + * greater than of equal to configTASK_NOTIFICATION_ARRAY_ENTRIES + */ +void test_xTaskGenericNotifyFromISR_assert_index_gte_config_array_entries( void ) +{ + TCB_t * ptcb = create_task(); + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES + 2; + + EXPECT_ASSERT_BREAK( xTaskGenericNotifyFromISR( ptcb, uxIndex, 23, + eSetBits, NULL, NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the task to notify is + * null + */ +void test_xTaskGenericNotifyFromISR_assert_null_task_to_notify( void ) +{ + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES - 1; + + EXPECT_ASSERT_BREAK( xTaskGenericNotifyFromISR( NULL, uxIndex, + 23, eSetBits, NULL, NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the default action is + * reached which we should never get there + */ +void test_xTaskGenericNotifyFromISR_assert_default_action_should_not_get( void ) +{ + TCB_t * ptcb = create_task(); + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES - 1; + + xTickCount = 3; + EXPECT_ASSERT_BREAK( xTaskGenericNotifyFromISR( ptcb, uxIndex, 3, + eSetValueWithoutOverwrite + 1, + NULL, NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the task state is + * taskWAITING_NOTIFICATION and the task is on an event list + */ +void test_xTaskGenericNotifyFromISR_assert( void ) +{ + UBaseType_t uxIndex = configTASK_NOTIFICATION_ARRAY_ENTRIES - 1; + TCB_t * ptcb = create_task(); + + ptcb->ucNotifyState[ uxIndex ] = 1; /* taskWAITING_NOTIFICATION */ + xTickCount = 0; + + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( ( void * ) 1 ); + EXPECT_ASSERT_BREAK( xTaskGenericNotifyFromISR( ptcb, uxIndex, 3, + eSetValueWithoutOverwrite + 1, + NULL, NULL ) ); + validate_and_clear_assertions(); +} + +/*! + * @brief This test ensures that the code asserts when the index passed is + * greater than or equal to configTASK_NOTIFICATION_ARRAY_ENTRIES + */ +void test_xTaskGenericNotifyStateClear_assert_index_gte_array_entries( void ) +{ + EXPECT_ASSERT_BREAK( xTaskGenericNotifyStateClear( NULL, + configTASK_NOTIFICATION_ARRAY_ENTRIES + 2 ) ); + validate_and_clear_assertions(); +} diff --git a/FreeRTOS/Test/CMock/tasks/tasks_freertos/FreeRTOS.h b/FreeRTOS/Test/CMock/tasks/tasks_freertos/FreeRTOS.h new file mode 100644 index 000000000..62477578a --- /dev/null +++ b/FreeRTOS/Test/CMock/tasks/tasks_freertos/FreeRTOS.h @@ -0,0 +1,3239 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* + * If stdint.h cannot be located then: + * + If using GCC ensure the -nostdint options is *not* being used. + * + Ensure the project's include path includes the directory in which your + * compiler stores stdint.h. + * + Set any compiler options necessary for it to support C99, as technically + * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any + * other way). + * + The FreeRTOS download includes a simple stdint.h definition that can be + * used in cases where none is provided by the compiler. The files only + * contains the typedefs required to build FreeRTOS. Read the instructions + * in FreeRTOS/source/stdint.readme for more information. + */ +#include /* READ COMMENT ABOVE. */ + +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ + +/* Acceptable values for configTICK_TYPE_WIDTH_IN_BITS. */ +#define TICK_TYPE_WIDTH_16_BITS 0 +#define TICK_TYPE_WIDTH_32_BITS 1 +#define TICK_TYPE_WIDTH_64_BITS 2 + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +#if !defined( configUSE_16_BIT_TICKS ) && !defined( configTICK_TYPE_WIDTH_IN_BITS ) + #error Missing definition: One of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if defined( configUSE_16_BIT_TICKS ) && defined( configTICK_TYPE_WIDTH_IN_BITS ) + #error Only one of configUSE_16_BIT_TICKS and configTICK_TYPE_WIDTH_IN_BITS must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +/* Define configTICK_TYPE_WIDTH_IN_BITS according to the + * value of configUSE_16_BIT_TICKS for backward compatibility. */ +#ifndef configTICK_TYPE_WIDTH_IN_BITS + #if ( configUSE_16_BIT_TICKS == 1 ) + #define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_16_BITS + #else + #define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS + #endif +#endif + +/* Set configUSE_MPU_WRAPPERS_V1 to 1 to use MPU wrappers v1. */ +#ifndef configUSE_MPU_WRAPPERS_V1 + #define configUSE_MPU_WRAPPERS_V1 0 +#endif + +/* Set configENABLE_ACCESS_CONTROL_LIST to 1 to enable access control list support. */ +#ifndef configENABLE_ACCESS_CONTROL_LIST + #define configENABLE_ACCESS_CONTROL_LIST 0 +#endif + +/* Set default value of configNUMBER_OF_CORES to 1 to use single core FreeRTOS. */ +#ifndef configNUMBER_OF_CORES + #define configNUMBER_OF_CORES 1 +#endif + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + +/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ +#ifndef configUSE_NEWLIB_REENTRANT + #define configUSE_NEWLIB_REENTRANT 0 +#endif + +/* Required if struct _reent is used. */ +#if ( configUSE_NEWLIB_REENTRANT == 1 ) + + #include "newlib-freertos.h" + +#endif /* if ( configUSE_NEWLIB_REENTRANT == 1 ) */ + +/* Must be defaulted before configUSE_PICOLIBC_TLS is used below. */ +#ifndef configUSE_PICOLIBC_TLS + #define configUSE_PICOLIBC_TLS 0 +#endif + +#if ( configUSE_PICOLIBC_TLS == 1 ) + + #include "picolibc-freertos.h" + +#endif /* if ( configUSE_PICOLIBC_TLS == 1 ) */ + +#ifndef configUSE_C_RUNTIME_TLS_SUPPORT + #define configUSE_C_RUNTIME_TLS_SUPPORT 0 +#endif + +#if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + + #ifndef configTLS_BLOCK_TYPE + #error Missing definition: configTLS_BLOCK_TYPE must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif + + #ifndef configINIT_TLS_BLOCK + #error Missing definition: configINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif + + #ifndef configSET_TLS_BLOCK + #error Missing definition: configSET_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif + + #ifndef configDEINIT_TLS_BLOCK + #error Missing definition: configDEINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1. + #endif +#endif /* if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) */ + +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configMINIMAL_STACK_SIZE + #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. +#endif + +#ifndef configMAX_PRIORITIES + #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if configMAX_PRIORITIES < 1 + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if ( configNUMBER_OF_CORES > 1 ) + #ifndef configUSE_PASSIVE_IDLE_HOOK + #error Missing definition: configUSE_PASSIVE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #endif +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if ( ( configTICK_TYPE_WIDTH_IN_BITS != TICK_TYPE_WIDTH_16_BITS ) && \ + ( configTICK_TYPE_WIDTH_IN_BITS != TICK_TYPE_WIDTH_32_BITS ) && \ + ( configTICK_TYPE_WIDTH_IN_BITS != TICK_TYPE_WIDTH_64_BITS ) ) + #error Macro configTICK_TYPE_WIDTH_IN_BITS is defined to incorrect value. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_CO_ROUTINES + #define configUSE_CO_ROUTINES 0 +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #define INCLUDE_vTaskPrioritySet 0 +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #define INCLUDE_uxTaskPriorityGet 0 +#endif + +#ifndef INCLUDE_vTaskDelete + #define INCLUDE_vTaskDelete 0 +#endif + +#ifndef INCLUDE_vTaskSuspend + #define INCLUDE_vTaskSuspend 0 +#endif + +#ifdef INCLUDE_xTaskDelayUntil + #ifdef INCLUDE_vTaskDelayUntil + +/* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward + * compatibility is maintained if only one or the other is defined, but + * there is a conflict if both are defined. */ + #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed + #endif +#endif + +#ifndef INCLUDE_xTaskDelayUntil + #ifdef INCLUDE_vTaskDelayUntil + +/* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then + * the project's FreeRTOSConfig.h probably pre-dates the introduction of + * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever + * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility. + */ + #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil + #endif +#endif + +#ifndef INCLUDE_xTaskDelayUntil + #define INCLUDE_xTaskDelayUntil 0 +#endif + +#ifndef INCLUDE_vTaskDelay + #define INCLUDE_vTaskDelay 0 +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle + #define INCLUDE_xTaskGetIdleTaskHandle 0 +#endif + +#ifndef INCLUDE_xTaskAbortDelay + #define INCLUDE_xTaskAbortDelay 0 +#endif + +#ifndef INCLUDE_xQueueGetMutexHolder + #define INCLUDE_xQueueGetMutexHolder 0 +#endif + +#ifndef INCLUDE_xSemaphoreGetMutexHolder + #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder +#endif + +#ifndef INCLUDE_xTaskGetHandle + #define INCLUDE_xTaskGetHandle 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark2 + #define INCLUDE_uxTaskGetStackHighWaterMark2 0 +#endif + +#ifndef INCLUDE_eTaskGetState + #define INCLUDE_eTaskGetState 0 +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xTimerPendFunctionCall + #define INCLUDE_xTimerPendFunctionCall 0 +#endif + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 1 +#endif + +#if configUSE_CO_ROUTINES != 0 + #ifndef configMAX_CO_ROUTINE_PRIORITIES + #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. + #endif +#endif + +#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK + #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS + #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS + #define configUSE_TIMERS 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_TASK_PREEMPTION_DISABLE + #define configUSE_TASK_PREEMPTION_DISABLE 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef configASSERT + #define configASSERT( x ) + #define configASSERT_DEFINED 0 +#else + #define configASSERT_DEFINED 1 +#endif + +/* configPRECONDITION should be defined as configASSERT. + * The CBMC proofs need a way to track assumptions and assertions. + * A configPRECONDITION statement should express an implicit invariant or + * assumption made. A configASSERT statement should express an invariant that must + * hold explicit before calling the code. */ +#ifndef configPRECONDITION + #define configPRECONDITION( X ) configASSERT( X ) + #define configPRECONDITION_DEFINED 0 +#else + #define configPRECONDITION_DEFINED 1 +#endif + +#ifndef portMEMORY_BARRIER + #define portMEMORY_BARRIER() +#endif + +#ifndef portSOFTWARE_BARRIER + #define portSOFTWARE_BARRIER() +#endif + +#ifndef configRUN_MULTIPLE_PRIORITIES + #define configRUN_MULTIPLE_PRIORITIES 0 +#endif + +#ifndef portGET_CORE_ID + + #if ( configNUMBER_OF_CORES == 1 ) + #define portGET_CORE_ID() 0 + #else + #error configNUMBER_OF_CORES is set to more than 1 then portGET_CORE_ID must also be defined. + #endif /* configNUMBER_OF_CORES */ + +#endif /* portGET_CORE_ID */ + +#ifndef portYIELD_CORE + + #if ( configNUMBER_OF_CORES == 1 ) + #define portYIELD_CORE( x ) portYIELD() + #else + #error configNUMBER_OF_CORES is set to more than 1 then portYIELD_CORE must also be defined. + #endif /* configNUMBER_OF_CORES */ + +#endif /* portYIELD_CORE */ + +#ifndef portSET_INTERRUPT_MASK + + #if ( configNUMBER_OF_CORES > 1 ) + #error portSET_INTERRUPT_MASK is required in SMP + #endif + +#endif /* portSET_INTERRUPT_MASK */ + +#ifndef portCLEAR_INTERRUPT_MASK + + #if ( configNUMBER_OF_CORES > 1 ) + #error portCLEAR_INTERRUPT_MASK is required in SMP + #endif + +#endif /* portCLEAR_INTERRUPT_MASK */ + +#ifndef portRELEASE_TASK_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portRELEASE_TASK_LOCK() + #else + #error portRELEASE_TASK_LOCK is required in SMP + #endif + +#endif /* portRELEASE_TASK_LOCK */ + +#ifndef portGET_TASK_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portGET_TASK_LOCK() + #else + #error portGET_TASK_LOCK is required in SMP + #endif + +#endif /* portGET_TASK_LOCK */ + +#ifndef portRELEASE_ISR_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portRELEASE_ISR_LOCK() + #else + #error portRELEASE_ISR_LOCK is required in SMP + #endif + +#endif /* portRELEASE_ISR_LOCK */ + +#ifndef portGET_ISR_LOCK + + #if ( configNUMBER_OF_CORES == 1 ) + #define portGET_ISR_LOCK() + #else + #error portGET_ISR_LOCK is required in SMP + #endif + +#endif /* portGET_ISR_LOCK */ + +#ifndef portENTER_CRITICAL_FROM_ISR + + #if ( configNUMBER_OF_CORES > 1 ) + #error portENTER_CRITICAL_FROM_ISR is required in SMP + #endif + +#endif + +#ifndef portEXIT_CRITICAL_FROM_ISR + + #if ( configNUMBER_OF_CORES > 1 ) + #error portEXIT_CRITICAL_FROM_ISR is required in SMP + #endif + +#endif + +#ifndef configUSE_CORE_AFFINITY + #define configUSE_CORE_AFFINITY 0 +#endif /* configUSE_CORE_AFFINITY */ + +#ifndef configUSE_PASSIVE_IDLE_HOOK + #define configUSE_PASSIVE_IDLE_HOOK 0 +#endif /* configUSE_PASSIVE_IDLE_HOOK */ + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + + #ifndef configTIMER_TASK_PRIORITY + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ + + #ifndef configTIMER_QUEUE_LENGTH + #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #endif /* configTIMER_QUEUE_LENGTH */ + + #ifndef configTIMER_TASK_STACK_DEPTH + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ + + #ifndef portTIMER_CALLBACK_ATTRIBUTE + #define portTIMER_CALLBACK_ATTRIBUTE + #endif /* portTIMER_CALLBACK_ATTRIBUTE */ + +#endif /* configUSE_TIMERS */ + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) ( uxSavedStatusValue ) +#endif + +#ifndef portCLEAN_UP_TCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) ( pxTCB ) +#endif + +#ifndef portPRE_TASK_DELETE_HOOK + #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) +#endif + +#ifndef portSETUP_TCB + #define portSETUP_TCB( pxTCB ) ( void ) ( pxTCB ) +#endif + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) + #define pcQueueGetName( xQueue ) +#endif + +#ifndef configUSE_MINI_LIST_ITEM + #define configUSE_MINI_LIST_ITEM 1 +#endif + +#ifndef portPOINTER_SIZE_TYPE + #define portPOINTER_SIZE_TYPE uint32_t +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART + +/* Used to perform any necessary initialisation - for example, open a file + * into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + +/* Use to close a trace, for example close a file into which trace has been + * written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + +/* Called after a task has been selected to run. pxCurrentTCB holds a pointer + * to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceINCREASE_TICK_COUNT + +/* Called before stepping the tick count after waking from tickless idle + * sleep. */ + #define traceINCREASE_TICK_COUNT( x ) +#endif + +#ifndef traceLOW_POWER_IDLE_BEGIN + /* Called immediately before entering tickless idle. */ + #define traceLOW_POWER_IDLE_BEGIN() +#endif + +#ifndef traceLOW_POWER_IDLE_END + /* Called when returning to the Idle task after a tickless idle. */ + #define traceLOW_POWER_IDLE_END() +#endif + +#ifndef traceTASK_SWITCHED_OUT + +/* Called before a task has been selected to run. pxCurrentTCB holds a pointer + * to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceTASK_PRIORITY_INHERIT + +/* Called when a task attempts to take a mutex that is already held by a + * lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task + * that holds the mutex. uxInheritedPriority is the priority the mutex holder + * will inherit (the priority of the task that is attempting to obtain the + * muted. */ + #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) +#endif + +#ifndef traceTASK_PRIORITY_DISINHERIT + +/* Called when a task releases a mutex, the holding of which had resulted in + * the task inheriting the priority of a higher priority task. + * pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the + * mutex. uxOriginalPriority is the task's configured (base) priority. */ + #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + +/* Task is about to block because it cannot read from a + * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + * upon which the read was attempted. pxCurrentTCB points to the TCB of the + * task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_PEEK + +/* Task is about to block because it cannot read from a + * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + * upon which the read was attempted. pxCurrentTCB points to the TCB of the + * task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + +/* Task is about to block because it cannot write to a + * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + * upon which the write was attempted. pxCurrentTCB points to the TCB of the + * task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +#ifndef configRECORD_STACK_HIGH_ADDRESS + #define configRECORD_STACK_HIGH_ADDRESS 0 +#endif + +#ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H + #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceMOVED_TASK_TO_READY_STATE + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef tracePOST_MOVED_TASK_TO_READY_STATE + #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef traceMOVED_TASK_TO_DELAYED_LIST + #define traceMOVED_TASK_TO_DELAYED_LIST() +#endif + +#ifndef traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST + #define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST() +#endif + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED( ucQueueType ) +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SET_SEND + #define traceQUEUE_SET_SEND traceQUEUE_SEND +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FAILED + #define traceQUEUE_PEEK_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL( x ) +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE + #define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED + #define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED + #define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef traceMALLOC + #define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE + #define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef traceEVENT_GROUP_CREATE + #define traceEVENT_GROUP_CREATE( xEventGroup ) +#endif + +#ifndef traceEVENT_GROUP_CREATE_FAILED + #define traceEVENT_GROUP_CREATE_FAILED() +#endif + +#ifndef traceEVENT_GROUP_SYNC_BLOCK + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_SYNC_END + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) ( xTimeoutOccurred ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_END + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) ( xTimeoutOccurred ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS + #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR + #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS + #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_DELETE + #define traceEVENT_GROUP_DELETE( xEventGroup ) +#endif + +#ifndef tracePEND_FUNC_CALL + #define tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, ret ) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR + #define tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, ret ) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD + #define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ) +#endif + +#ifndef traceTASK_NOTIFY_TAKE_BLOCK + #define traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ) +#endif + +#ifndef traceTASK_NOTIFY_TAKE + #define traceTASK_NOTIFY_TAKE( uxIndexToWait ) +#endif + +#ifndef traceTASK_NOTIFY_WAIT_BLOCK + #define traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ) +#endif + +#ifndef traceTASK_NOTIFY_WAIT + #define traceTASK_NOTIFY_WAIT( uxIndexToWait ) +#endif + +#ifndef traceTASK_NOTIFY + #define traceTASK_NOTIFY( uxIndexToNotify ) +#endif + +#ifndef traceTASK_NOTIFY_FROM_ISR + #define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify ) +#endif + +#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR + #define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ) +#endif + +#ifndef traceISR_EXIT_TO_SCHEDULER + #define traceISR_EXIT_TO_SCHEDULER() +#endif + +#ifndef traceISR_EXIT + #define traceISR_EXIT() +#endif + +#ifndef traceISR_ENTER + #define traceISR_ENTER() +#endif + +#ifndef traceSTREAM_BUFFER_CREATE_FAILED + #define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_CREATE_STATIC_FAILED + #define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_CREATE + #define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_DELETE + #define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_RESET + #define traceSTREAM_BUFFER_RESET( xStreamBuffer ) +#endif + +#ifndef traceBLOCKING_ON_STREAM_BUFFER_SEND + #define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_SEND + #define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent ) +#endif + +#ifndef traceSTREAM_BUFFER_SEND_FAILED + #define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_SEND_FROM_ISR + #define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent ) +#endif + +#ifndef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE + #define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_RECEIVE + #define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) +#endif + +#ifndef traceSTREAM_BUFFER_RECEIVE_FAILED + #define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) +#endif + +#ifndef traceSTREAM_BUFFER_RECEIVE_FROM_ISR + #define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) +#endif + +#ifndef traceENTER_xEventGroupCreateStatic + #define traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer ) +#endif + +#ifndef traceRETURN_xEventGroupCreateStatic + #define traceRETURN_xEventGroupCreateStatic( pxEventBits ) +#endif + +#ifndef traceENTER_xEventGroupCreate + #define traceENTER_xEventGroupCreate() +#endif + +#ifndef traceRETURN_xEventGroupCreate + #define traceRETURN_xEventGroupCreate( pxEventBits ) +#endif + +#ifndef traceENTER_xEventGroupSync + #define traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ) +#endif + +#ifndef traceRETURN_xEventGroupSync + #define traceRETURN_xEventGroupSync( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupWaitBits + #define traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ) +#endif + +#ifndef traceRETURN_xEventGroupWaitBits + #define traceRETURN_xEventGroupWaitBits( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupClearBits + #define traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceRETURN_xEventGroupClearBits + #define traceRETURN_xEventGroupClearBits( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupClearBitsFromISR + #define traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceRETURN_xEventGroupClearBitsFromISR + #define traceRETURN_xEventGroupClearBitsFromISR( xReturn ) +#endif + +#ifndef traceENTER_xEventGroupGetBitsFromISR + #define traceENTER_xEventGroupGetBitsFromISR( xEventGroup ) +#endif + +#ifndef traceRETURN_xEventGroupGetBitsFromISR + #define traceRETURN_xEventGroupGetBitsFromISR( uxReturn ) +#endif + +#ifndef traceENTER_xEventGroupSetBits + #define traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceRETURN_xEventGroupSetBits + #define traceRETURN_xEventGroupSetBits( uxEventBits ) +#endif + +#ifndef traceENTER_vEventGroupDelete + #define traceENTER_vEventGroupDelete( xEventGroup ) +#endif + +#ifndef traceRETURN_vEventGroupDelete + #define traceRETURN_vEventGroupDelete() +#endif + +#ifndef traceENTER_xEventGroupGetStaticBuffer + #define traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer ) +#endif + +#ifndef traceRETURN_xEventGroupGetStaticBuffer + #define traceRETURN_xEventGroupGetStaticBuffer( xReturn ) +#endif + +#ifndef traceENTER_vEventGroupSetBitsCallback + #define traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet ) +#endif + +#ifndef traceRETURN_vEventGroupSetBitsCallback + #define traceRETURN_vEventGroupSetBitsCallback() +#endif + +#ifndef traceENTER_vEventGroupClearBitsCallback + #define traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear ) +#endif + +#ifndef traceRETURN_vEventGroupClearBitsCallback + #define traceRETURN_vEventGroupClearBitsCallback() +#endif + +#ifndef traceENTER_xEventGroupSetBitsFromISR + #define traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xEventGroupSetBitsFromISR + #define traceRETURN_xEventGroupSetBitsFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxEventGroupGetNumber + #define traceENTER_uxEventGroupGetNumber( xEventGroup ) +#endif + +#ifndef traceRETURN_uxEventGroupGetNumber + #define traceRETURN_uxEventGroupGetNumber( xReturn ) +#endif + +#ifndef traceENTER_vEventGroupSetNumber + #define traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber ) +#endif + +#ifndef traceRETURN_vEventGroupSetNumber + #define traceRETURN_vEventGroupSetNumber() +#endif + +#ifndef traceENTER_xQueueGenericReset + #define traceENTER_xQueueGenericReset( xQueue, xNewQueue ) +#endif + +#ifndef traceRETURN_xQueueGenericReset + #define traceRETURN_xQueueGenericReset( xReturn ) +#endif + +#ifndef traceENTER_xQueueGenericCreateStatic + #define traceENTER_xQueueGenericCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue, ucQueueType ) +#endif + +#ifndef traceRETURN_xQueueGenericCreateStatic + #define traceRETURN_xQueueGenericCreateStatic( pxNewQueue ) +#endif + +#ifndef traceENTER_xQueueGenericGetStaticBuffers + #define traceENTER_xQueueGenericGetStaticBuffers( xQueue, ppucQueueStorage, ppxStaticQueue ) +#endif + +#ifndef traceRETURN_xQueueGenericGetStaticBuffers + #define traceRETURN_xQueueGenericGetStaticBuffers( xReturn ) +#endif + +#ifndef traceENTER_xQueueGenericCreate + #define traceENTER_xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType ) +#endif + +#ifndef traceRETURN_xQueueGenericCreate + #define traceRETURN_xQueueGenericCreate( pxNewQueue ) +#endif + +#ifndef traceENTER_xQueueCreateMutex + #define traceENTER_xQueueCreateMutex( ucQueueType ) +#endif + +#ifndef traceRETURN_xQueueCreateMutex + #define traceRETURN_xQueueCreateMutex( xNewQueue ) +#endif + +#ifndef traceENTER_xQueueCreateMutexStatic + #define traceENTER_xQueueCreateMutexStatic( ucQueueType, pxStaticQueue ) +#endif + +#ifndef traceRETURN_xQueueCreateMutexStatic + #define traceRETURN_xQueueCreateMutexStatic( xNewQueue ) +#endif + +#ifndef traceENTER_xQueueGetMutexHolder + #define traceENTER_xQueueGetMutexHolder( xSemaphore ) +#endif + +#ifndef traceRETURN_xQueueGetMutexHolder + #define traceRETURN_xQueueGetMutexHolder( pxReturn ) +#endif + +#ifndef traceENTER_xQueueGetMutexHolderFromISR + #define traceENTER_xQueueGetMutexHolderFromISR( xSemaphore ) +#endif + +#ifndef traceRETURN_xQueueGetMutexHolderFromISR + #define traceRETURN_xQueueGetMutexHolderFromISR( pxReturn ) +#endif + +#ifndef traceENTER_xQueueGiveMutexRecursive + #define traceENTER_xQueueGiveMutexRecursive( xMutex ) +#endif + +#ifndef traceRETURN_xQueueGiveMutexRecursive + #define traceRETURN_xQueueGiveMutexRecursive( xReturn ) +#endif + +#ifndef traceENTER_xQueueTakeMutexRecursive + #define traceENTER_xQueueTakeMutexRecursive( xMutex, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueTakeMutexRecursive + #define traceRETURN_xQueueTakeMutexRecursive( xReturn ) +#endif + +#ifndef traceENTER_xQueueCreateCountingSemaphoreStatic + #define traceENTER_xQueueCreateCountingSemaphoreStatic( uxMaxCount, uxInitialCount, pxStaticQueue ) +#endif + +#ifndef traceRETURN_xQueueCreateCountingSemaphoreStatic + #define traceRETURN_xQueueCreateCountingSemaphoreStatic( xHandle ) +#endif + +#ifndef traceENTER_xQueueCreateCountingSemaphore + #define traceENTER_xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount ) +#endif + +#ifndef traceRETURN_xQueueCreateCountingSemaphore + #define traceRETURN_xQueueCreateCountingSemaphore( xHandle ) +#endif + +#ifndef traceENTER_xQueueGenericSend + #define traceENTER_xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ) +#endif + +#ifndef traceRETURN_xQueueGenericSend + #define traceRETURN_xQueueGenericSend( xReturn ) +#endif + +#ifndef traceENTER_xQueueGenericSendFromISR + #define traceENTER_xQueueGenericSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken, xCopyPosition ) +#endif + +#ifndef traceRETURN_xQueueGenericSendFromISR + #define traceRETURN_xQueueGenericSendFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueGiveFromISR + #define traceENTER_xQueueGiveFromISR( xQueue, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xQueueGiveFromISR + #define traceRETURN_xQueueGiveFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueReceive + #define traceENTER_xQueueReceive( xQueue, pvBuffer, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueReceive + #define traceRETURN_xQueueReceive( xReturn ) +#endif + +#ifndef traceENTER_xQueueSemaphoreTake + #define traceENTER_xQueueSemaphoreTake( xQueue, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueSemaphoreTake + #define traceRETURN_xQueueSemaphoreTake( xReturn ) +#endif + +#ifndef traceENTER_xQueuePeek + #define traceENTER_xQueuePeek( xQueue, pvBuffer, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueuePeek + #define traceRETURN_xQueuePeek( xReturn ) +#endif + +#ifndef traceENTER_xQueueReceiveFromISR + #define traceENTER_xQueueReceiveFromISR( xQueue, pvBuffer, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xQueueReceiveFromISR + #define traceRETURN_xQueueReceiveFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueuePeekFromISR + #define traceENTER_xQueuePeekFromISR( xQueue, pvBuffer ) +#endif + +#ifndef traceRETURN_xQueuePeekFromISR + #define traceRETURN_xQueuePeekFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxQueueMessagesWaiting + #define traceENTER_uxQueueMessagesWaiting( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueMessagesWaiting + #define traceRETURN_uxQueueMessagesWaiting( uxReturn ) +#endif + +#ifndef traceENTER_uxQueueSpacesAvailable + #define traceENTER_uxQueueSpacesAvailable( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueSpacesAvailable + #define traceRETURN_uxQueueSpacesAvailable( uxReturn ) +#endif + +#ifndef traceENTER_uxQueueMessagesWaitingFromISR + #define traceENTER_uxQueueMessagesWaitingFromISR( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueMessagesWaitingFromISR + #define traceRETURN_uxQueueMessagesWaitingFromISR( uxReturn ) +#endif + +#ifndef traceENTER_vQueueDelete + #define traceENTER_vQueueDelete( xQueue ) +#endif + +#ifndef traceRETURN_vQueueDelete + #define traceRETURN_vQueueDelete() +#endif + +#ifndef traceENTER_uxQueueGetQueueNumber + #define traceENTER_uxQueueGetQueueNumber( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueGetQueueNumber + #define traceRETURN_uxQueueGetQueueNumber( uxQueueNumber ) +#endif + +#ifndef traceENTER_vQueueSetQueueNumber + #define traceENTER_vQueueSetQueueNumber( xQueue, uxQueueNumber ) +#endif + +#ifndef traceRETURN_vQueueSetQueueNumber + #define traceRETURN_vQueueSetQueueNumber() +#endif + +#ifndef traceENTER_ucQueueGetQueueType + #define traceENTER_ucQueueGetQueueType( xQueue ) +#endif + +#ifndef traceRETURN_ucQueueGetQueueType + #define traceRETURN_ucQueueGetQueueType( ucQueueType ) +#endif + +#ifndef traceENTER_uxQueueGetQueueItemSize + #define traceENTER_uxQueueGetQueueItemSize( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueGetQueueItemSize + #define traceRETURN_uxQueueGetQueueItemSize( uxItemSize ) +#endif + +#ifndef traceENTER_uxQueueGetQueueLength + #define traceENTER_uxQueueGetQueueLength( xQueue ) +#endif + +#ifndef traceRETURN_uxQueueGetQueueLength + #define traceRETURN_uxQueueGetQueueLength( uxLength ) +#endif + +#ifndef traceENTER_xQueueIsQueueEmptyFromISR + #define traceENTER_xQueueIsQueueEmptyFromISR( xQueue ) +#endif + +#ifndef traceRETURN_xQueueIsQueueEmptyFromISR + #define traceRETURN_xQueueIsQueueEmptyFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueIsQueueFullFromISR + #define traceENTER_xQueueIsQueueFullFromISR( xQueue ) +#endif + +#ifndef traceRETURN_xQueueIsQueueFullFromISR + #define traceRETURN_xQueueIsQueueFullFromISR( xReturn ) +#endif + +#ifndef traceENTER_xQueueCRSend + #define traceENTER_xQueueCRSend( xQueue, pvItemToQueue, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueCRSend + #define traceRETURN_xQueueCRSend( xReturn ) +#endif + +#ifndef traceENTER_xQueueCRReceive + #define traceENTER_xQueueCRReceive( xQueue, pvBuffer, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueCRReceive + #define traceRETURN_xQueueCRReceive( xReturn ) +#endif + +#ifndef traceENTER_xQueueCRSendFromISR + #define traceENTER_xQueueCRSendFromISR( xQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) +#endif + +#ifndef traceRETURN_xQueueCRSendFromISR + #define traceRETURN_xQueueCRSendFromISR( xCoRoutinePreviouslyWoken ) +#endif + +#ifndef traceENTER_xQueueCRReceiveFromISR + #define traceENTER_xQueueCRReceiveFromISR( xQueue, pvBuffer, pxCoRoutineWoken ) +#endif + +#ifndef traceRETURN_xQueueCRReceiveFromISR + #define traceRETURN_xQueueCRReceiveFromISR( xReturn ) +#endif + +#ifndef traceENTER_vQueueAddToRegistry + #define traceENTER_vQueueAddToRegistry( xQueue, pcQueueName ) +#endif + +#ifndef traceRETURN_vQueueAddToRegistry + #define traceRETURN_vQueueAddToRegistry() +#endif + +#ifndef traceENTER_pcQueueGetName + #define traceENTER_pcQueueGetName( xQueue ) +#endif + +#ifndef traceRETURN_pcQueueGetName + #define traceRETURN_pcQueueGetName( pcReturn ) +#endif + +#ifndef traceENTER_vQueueUnregisterQueue + #define traceENTER_vQueueUnregisterQueue( xQueue ) +#endif + +#ifndef traceRETURN_vQueueUnregisterQueue + #define traceRETURN_vQueueUnregisterQueue() +#endif + +#ifndef traceENTER_vQueueWaitForMessageRestricted + #define traceENTER_vQueueWaitForMessageRestricted( xQueue, xTicksToWait, xWaitIndefinitely ) +#endif + +#ifndef traceRETURN_vQueueWaitForMessageRestricted + #define traceRETURN_vQueueWaitForMessageRestricted() +#endif + +#ifndef traceENTER_xQueueCreateSet + #define traceENTER_xQueueCreateSet( uxEventQueueLength ) +#endif + +#ifndef traceRETURN_xQueueCreateSet + #define traceRETURN_xQueueCreateSet( pxQueue ) +#endif + +#ifndef traceENTER_xQueueAddToSet + #define traceENTER_xQueueAddToSet( xQueueOrSemaphore, xQueueSet ) +#endif + +#ifndef traceRETURN_xQueueAddToSet + #define traceRETURN_xQueueAddToSet( xReturn ) +#endif + +#ifndef traceENTER_xQueueRemoveFromSet + #define traceENTER_xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ) +#endif + +#ifndef traceRETURN_xQueueRemoveFromSet + #define traceRETURN_xQueueRemoveFromSet( xReturn ) +#endif + +#ifndef traceENTER_xQueueSelectFromSet + #define traceENTER_xQueueSelectFromSet( xQueueSet, xTicksToWait ) +#endif + +#ifndef traceRETURN_xQueueSelectFromSet + #define traceRETURN_xQueueSelectFromSet( xReturn ) +#endif + +#ifndef traceENTER_xQueueSelectFromSetFromISR + #define traceENTER_xQueueSelectFromSetFromISR( xQueueSet ) +#endif + +#ifndef traceRETURN_xQueueSelectFromSetFromISR + #define traceRETURN_xQueueSelectFromSetFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTimerCreateTimerTask + #define traceENTER_xTimerCreateTimerTask() +#endif + +#ifndef traceRETURN_xTimerCreateTimerTask + #define traceRETURN_xTimerCreateTimerTask( xReturn ) +#endif + +#ifndef traceENTER_xTimerCreate + #define traceENTER_xTimerCreate( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction ) +#endif + +#ifndef traceRETURN_xTimerCreate + #define traceRETURN_xTimerCreate( pxNewTimer ) +#endif + +#ifndef traceENTER_xTimerCreateStatic + #define traceENTER_xTimerCreateStatic( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxTimerBuffer ) +#endif + +#ifndef traceRETURN_xTimerCreateStatic + #define traceRETURN_xTimerCreateStatic( pxNewTimer ) +#endif + +#ifndef traceENTER_xTimerGenericCommandFromTask + #define traceENTER_xTimerGenericCommandFromTask( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTimerGenericCommandFromTask + #define traceRETURN_xTimerGenericCommandFromTask( xReturn ) +#endif + +#ifndef traceENTER_xTimerGenericCommandFromISR + #define traceENTER_xTimerGenericCommandFromISR( xTimer, xCommandID, xOptionalValue, pxHigherPriorityTaskWoken, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTimerGenericCommandFromISR + #define traceRETURN_xTimerGenericCommandFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTimerGetTimerDaemonTaskHandle + #define traceENTER_xTimerGetTimerDaemonTaskHandle() +#endif + +#ifndef traceRETURN_xTimerGetTimerDaemonTaskHandle + #define traceRETURN_xTimerGetTimerDaemonTaskHandle( xTimerTaskHandle ) +#endif + +#ifndef traceENTER_xTimerGetPeriod + #define traceENTER_xTimerGetPeriod( xTimer ) +#endif + +#ifndef traceRETURN_xTimerGetPeriod + #define traceRETURN_xTimerGetPeriod( xTimerPeriodInTicks ) +#endif + +#ifndef traceENTER_vTimerSetReloadMode + #define traceENTER_vTimerSetReloadMode( xTimer, xAutoReload ) +#endif + +#ifndef traceRETURN_vTimerSetReloadMode + #define traceRETURN_vTimerSetReloadMode() +#endif + +#ifndef traceENTER_xTimerGetReloadMode + #define traceENTER_xTimerGetReloadMode( xTimer ) +#endif + +#ifndef traceRETURN_xTimerGetReloadMode + #define traceRETURN_xTimerGetReloadMode( xReturn ) +#endif + +#ifndef traceENTER_uxTimerGetReloadMode + #define traceENTER_uxTimerGetReloadMode( xTimer ) +#endif + +#ifndef traceRETURN_uxTimerGetReloadMode + #define traceRETURN_uxTimerGetReloadMode( uxReturn ) +#endif + +#ifndef traceENTER_xTimerGetExpiryTime + #define traceENTER_xTimerGetExpiryTime( xTimer ) +#endif + +#ifndef traceRETURN_xTimerGetExpiryTime + #define traceRETURN_xTimerGetExpiryTime( xReturn ) +#endif + +#ifndef traceENTER_xTimerGetStaticBuffer + #define traceENTER_xTimerGetStaticBuffer( xTimer, ppxTimerBuffer ) +#endif + +#ifndef traceRETURN_xTimerGetStaticBuffer + #define traceRETURN_xTimerGetStaticBuffer( xReturn ) +#endif + +#ifndef traceENTER_pcTimerGetName + #define traceENTER_pcTimerGetName( xTimer ) +#endif + +#ifndef traceRETURN_pcTimerGetName + #define traceRETURN_pcTimerGetName( pcTimerName ) +#endif + +#ifndef traceENTER_xTimerIsTimerActive + #define traceENTER_xTimerIsTimerActive( xTimer ) +#endif + +#ifndef traceRETURN_xTimerIsTimerActive + #define traceRETURN_xTimerIsTimerActive( xReturn ) +#endif + +#ifndef traceENTER_pvTimerGetTimerID + #define traceENTER_pvTimerGetTimerID( xTimer ) +#endif + +#ifndef traceRETURN_pvTimerGetTimerID + #define traceRETURN_pvTimerGetTimerID( pvReturn ) +#endif + +#ifndef traceENTER_vTimerSetTimerID + #define traceENTER_vTimerSetTimerID( xTimer, pvNewID ) +#endif + +#ifndef traceRETURN_vTimerSetTimerID + #define traceRETURN_vTimerSetTimerID() +#endif + +#ifndef traceENTER_xTimerPendFunctionCallFromISR + #define traceENTER_xTimerPendFunctionCallFromISR( xFunctionToPend, pvParameter1, ulParameter2, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xTimerPendFunctionCallFromISR + #define traceRETURN_xTimerPendFunctionCallFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTimerPendFunctionCall + #define traceENTER_xTimerPendFunctionCall( xFunctionToPend, pvParameter1, ulParameter2, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTimerPendFunctionCall + #define traceRETURN_xTimerPendFunctionCall( xReturn ) +#endif + +#ifndef traceENTER_uxTimerGetTimerNumber + #define traceENTER_uxTimerGetTimerNumber( xTimer ) +#endif + +#ifndef traceRETURN_uxTimerGetTimerNumber + #define traceRETURN_uxTimerGetTimerNumber( uxTimerNumber ) +#endif + +#ifndef traceENTER_vTimerSetTimerNumber + #define traceENTER_vTimerSetTimerNumber( xTimer, uxTimerNumber ) +#endif + +#ifndef traceRETURN_vTimerSetTimerNumber + #define traceRETURN_vTimerSetTimerNumber() +#endif + +#ifndef traceENTER_xTaskCreateStatic + #define traceENTER_xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer ) +#endif + +#ifndef traceRETURN_xTaskCreateStatic + #define traceRETURN_xTaskCreateStatic( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateStaticAffinitySet + #define traceENTER_xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask ) +#endif + +#ifndef traceRETURN_xTaskCreateStaticAffinitySet + #define traceRETURN_xTaskCreateStaticAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestrictedStatic + #define traceENTER_xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestrictedStatic + #define traceRETURN_xTaskCreateRestrictedStatic( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestrictedStaticAffinitySet + #define traceENTER_xTaskCreateRestrictedStaticAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestrictedStaticAffinitySet + #define traceRETURN_xTaskCreateRestrictedStaticAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestricted + #define traceENTER_xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestricted + #define traceRETURN_xTaskCreateRestricted( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateRestrictedAffinitySet + #define traceENTER_xTaskCreateRestrictedAffinitySet( pxTaskDefinition, uxCoreAffinityMask, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateRestrictedAffinitySet + #define traceRETURN_xTaskCreateRestrictedAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreate + #define traceENTER_xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreate + #define traceRETURN_xTaskCreate( xReturn ) +#endif + +#ifndef traceENTER_xTaskCreateAffinitySet + #define traceENTER_xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask ) +#endif + +#ifndef traceRETURN_xTaskCreateAffinitySet + #define traceRETURN_xTaskCreateAffinitySet( xReturn ) +#endif + +#ifndef traceENTER_vTaskDelete + #define traceENTER_vTaskDelete( xTaskToDelete ) +#endif + +#ifndef traceRETURN_vTaskDelete + #define traceRETURN_vTaskDelete() +#endif + +#ifndef traceENTER_xTaskDelayUntil + #define traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) +#endif + +#ifndef traceRETURN_xTaskDelayUntil + #define traceRETURN_xTaskDelayUntil( xShouldDelay ) +#endif + +#ifndef traceENTER_vTaskDelay + #define traceENTER_vTaskDelay( xTicksToDelay ) +#endif + +#ifndef traceRETURN_vTaskDelay + #define traceRETURN_vTaskDelay() +#endif + +#ifndef traceENTER_eTaskGetState + #define traceENTER_eTaskGetState( xTask ) +#endif + +#ifndef traceRETURN_eTaskGetState + #define traceRETURN_eTaskGetState( eReturn ) +#endif + +#ifndef traceENTER_uxTaskPriorityGet + #define traceENTER_uxTaskPriorityGet( xTask ) +#endif + +#ifndef traceRETURN_uxTaskPriorityGet + #define traceRETURN_uxTaskPriorityGet( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskPriorityGetFromISR + #define traceENTER_uxTaskPriorityGetFromISR( xTask ) +#endif + +#ifndef traceRETURN_uxTaskPriorityGetFromISR + #define traceRETURN_uxTaskPriorityGetFromISR( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskBasePriorityGet + #define traceENTER_uxTaskBasePriorityGet( xTask ) +#endif + +#ifndef traceRETURN_uxTaskBasePriorityGet + #define traceRETURN_uxTaskBasePriorityGet( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskBasePriorityGetFromISR + #define traceENTER_uxTaskBasePriorityGetFromISR( xTask ) +#endif + +#ifndef traceRETURN_uxTaskBasePriorityGetFromISR + #define traceRETURN_uxTaskBasePriorityGetFromISR( uxReturn ) +#endif + +#ifndef traceENTER_vTaskPrioritySet + #define traceENTER_vTaskPrioritySet( xTask, uxNewPriority ) +#endif + +#ifndef traceRETURN_vTaskPrioritySet + #define traceRETURN_vTaskPrioritySet() +#endif + +#ifndef traceENTER_vTaskCoreAffinitySet + #define traceENTER_vTaskCoreAffinitySet( xTask, uxCoreAffinityMask ) +#endif + +#ifndef traceRETURN_vTaskCoreAffinitySet + #define traceRETURN_vTaskCoreAffinitySet() +#endif + +#ifndef traceENTER_vTaskCoreAffinityGet + #define traceENTER_vTaskCoreAffinityGet( xTask ) +#endif + +#ifndef traceRETURN_vTaskCoreAffinityGet + #define traceRETURN_vTaskCoreAffinityGet( uxCoreAffinityMask ) +#endif + +#ifndef traceENTER_vTaskPreemptionDisable + #define traceENTER_vTaskPreemptionDisable( xTask ) +#endif + +#ifndef traceRETURN_vTaskPreemptionDisable + #define traceRETURN_vTaskPreemptionDisable() +#endif + +#ifndef traceENTER_vTaskPreemptionEnable + #define traceENTER_vTaskPreemptionEnable( xTask ) +#endif + +#ifndef traceRETURN_vTaskPreemptionEnable + #define traceRETURN_vTaskPreemptionEnable() +#endif + +#ifndef traceENTER_vTaskSuspend + #define traceENTER_vTaskSuspend( xTaskToSuspend ) +#endif + +#ifndef traceRETURN_vTaskSuspend + #define traceRETURN_vTaskSuspend() +#endif + +#ifndef traceENTER_vTaskResume + #define traceENTER_vTaskResume( xTaskToResume ) +#endif + +#ifndef traceRETURN_vTaskResume + #define traceRETURN_vTaskResume() +#endif + +#ifndef traceENTER_xTaskResumeFromISR + #define traceENTER_xTaskResumeFromISR( xTaskToResume ) +#endif + +#ifndef traceRETURN_xTaskResumeFromISR + #define traceRETURN_xTaskResumeFromISR( xYieldRequired ) +#endif + +#ifndef traceENTER_vTaskStartScheduler + #define traceENTER_vTaskStartScheduler() +#endif + +#ifndef traceRETURN_vTaskStartScheduler + #define traceRETURN_vTaskStartScheduler() +#endif + +#ifndef traceENTER_vTaskEndScheduler + #define traceENTER_vTaskEndScheduler() +#endif + +#ifndef traceRETURN_vTaskEndScheduler + #define traceRETURN_vTaskEndScheduler() +#endif + +#ifndef traceENTER_vTaskSuspendAll + #define traceENTER_vTaskSuspendAll() +#endif + +#ifndef traceRETURN_vTaskSuspendAll + #define traceRETURN_vTaskSuspendAll() +#endif + +#ifndef traceENTER_xTaskResumeAll + #define traceENTER_xTaskResumeAll() +#endif + +#ifndef traceRETURN_xTaskResumeAll + #define traceRETURN_xTaskResumeAll( xAlreadyYielded ) +#endif + +#ifndef traceENTER_xTaskGetTickCount + #define traceENTER_xTaskGetTickCount() +#endif + +#ifndef traceRETURN_xTaskGetTickCount + #define traceRETURN_xTaskGetTickCount( xTicks ) +#endif + +#ifndef traceENTER_xTaskGetTickCountFromISR + #define traceENTER_xTaskGetTickCountFromISR() +#endif + +#ifndef traceRETURN_xTaskGetTickCountFromISR + #define traceRETURN_xTaskGetTickCountFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxTaskGetNumberOfTasks + #define traceENTER_uxTaskGetNumberOfTasks() +#endif + +#ifndef traceRETURN_uxTaskGetNumberOfTasks + #define traceRETURN_uxTaskGetNumberOfTasks( uxCurrentNumberOfTasks ) +#endif + +#ifndef traceENTER_pcTaskGetName + #define traceENTER_pcTaskGetName( xTaskToQuery ) +#endif + +#ifndef traceRETURN_pcTaskGetName + #define traceRETURN_pcTaskGetName( pcTaskName ) +#endif + +#ifndef traceENTER_xTaskGetHandle + #define traceENTER_xTaskGetHandle( pcNameToQuery ) +#endif + +#ifndef traceRETURN_xTaskGetHandle + #define traceRETURN_xTaskGetHandle( pxTCB ) +#endif + +#ifndef traceENTER_xTaskGetStaticBuffers + #define traceENTER_xTaskGetStaticBuffers( xTask, ppuxStackBuffer, ppxTaskBuffer ) +#endif + +#ifndef traceRETURN_xTaskGetStaticBuffers + #define traceRETURN_xTaskGetStaticBuffers( xReturn ) +#endif + +#ifndef traceENTER_uxTaskGetSystemState + #define traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ) +#endif + +#ifndef traceRETURN_uxTaskGetSystemState + #define traceRETURN_uxTaskGetSystemState( uxTask ) +#endif + +#if ( configNUMBER_OF_CORES == 1 ) + #ifndef traceENTER_xTaskGetIdleTaskHandle + #define traceENTER_xTaskGetIdleTaskHandle() + #endif +#else + #ifndef traceENTER_xTaskGetIdleTaskHandle + #define traceENTER_xTaskGetIdleTaskHandle( xCoreID ) + #endif +#endif + +#ifndef traceRETURN_xTaskGetIdleTaskHandle + #define traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandle ) +#endif + +#ifndef traceENTER_vTaskStepTick + #define traceENTER_vTaskStepTick( xTicksToJump ) +#endif + +#ifndef traceRETURN_vTaskStepTick + #define traceRETURN_vTaskStepTick() +#endif + +#ifndef traceENTER_xTaskCatchUpTicks + #define traceENTER_xTaskCatchUpTicks( xTicksToCatchUp ) +#endif + +#ifndef traceRETURN_xTaskCatchUpTicks + #define traceRETURN_xTaskCatchUpTicks( xYieldOccurred ) +#endif + +#ifndef traceENTER_xTaskAbortDelay + #define traceENTER_xTaskAbortDelay( xTask ) +#endif + +#ifndef traceRETURN_xTaskAbortDelay + #define traceRETURN_xTaskAbortDelay( xReturn ) +#endif + +#ifndef traceENTER_xTaskIncrementTick + #define traceENTER_xTaskIncrementTick() +#endif + +#ifndef traceRETURN_xTaskIncrementTick + #define traceRETURN_xTaskIncrementTick( xSwitchRequired ) +#endif + +#ifndef traceENTER_vTaskSetApplicationTaskTag + #define traceENTER_vTaskSetApplicationTaskTag( xTask, pxHookFunction ) +#endif + +#ifndef traceRETURN_vTaskSetApplicationTaskTag + #define traceRETURN_vTaskSetApplicationTaskTag() +#endif + +#ifndef traceENTER_xTaskGetApplicationTaskTag + #define traceENTER_xTaskGetApplicationTaskTag( xTask ) +#endif + +#ifndef traceRETURN_xTaskGetApplicationTaskTag + #define traceRETURN_xTaskGetApplicationTaskTag( xReturn ) +#endif + +#ifndef traceENTER_xTaskGetApplicationTaskTagFromISR + #define traceENTER_xTaskGetApplicationTaskTagFromISR( xTask ) +#endif + +#ifndef traceRETURN_xTaskGetApplicationTaskTagFromISR + #define traceRETURN_xTaskGetApplicationTaskTagFromISR( xReturn ) +#endif + +#ifndef traceENTER_xTaskCallApplicationTaskHook + #define traceENTER_xTaskCallApplicationTaskHook( xTask, pvParameter ) +#endif + +#ifndef traceRETURN_xTaskCallApplicationTaskHook + #define traceRETURN_xTaskCallApplicationTaskHook( xReturn ) +#endif + +#ifndef traceENTER_vTaskSwitchContext + #define traceENTER_vTaskSwitchContext() +#endif + +#ifndef traceRETURN_vTaskSwitchContext + #define traceRETURN_vTaskSwitchContext() +#endif + +#ifndef traceENTER_vTaskPlaceOnEventList + #define traceENTER_vTaskPlaceOnEventList( pxEventList, xTicksToWait ) +#endif + +#ifndef traceRETURN_vTaskPlaceOnEventList + #define traceRETURN_vTaskPlaceOnEventList() +#endif + +#ifndef traceENTER_vTaskPlaceOnUnorderedEventList + #define traceENTER_vTaskPlaceOnUnorderedEventList( pxEventList, xItemValue, xTicksToWait ) +#endif + +#ifndef traceRETURN_vTaskPlaceOnUnorderedEventList + #define traceRETURN_vTaskPlaceOnUnorderedEventList() +#endif + +#ifndef traceENTER_vTaskPlaceOnEventListRestricted + #define traceENTER_vTaskPlaceOnEventListRestricted( pxEventList, xTicksToWait, xWaitIndefinitely ) +#endif + +#ifndef traceRETURN_vTaskPlaceOnEventListRestricted + #define traceRETURN_vTaskPlaceOnEventListRestricted() +#endif + +#ifndef traceENTER_xTaskRemoveFromEventList + #define traceENTER_xTaskRemoveFromEventList( pxEventList ) +#endif + +#ifndef traceRETURN_xTaskRemoveFromEventList + #define traceRETURN_xTaskRemoveFromEventList( xReturn ) +#endif + +#ifndef traceENTER_vTaskRemoveFromUnorderedEventList + #define traceENTER_vTaskRemoveFromUnorderedEventList( pxEventListItem, xItemValue ) +#endif + +#ifndef traceRETURN_vTaskRemoveFromUnorderedEventList + #define traceRETURN_vTaskRemoveFromUnorderedEventList() +#endif + +#ifndef traceENTER_vTaskSetTimeOutState + #define traceENTER_vTaskSetTimeOutState( pxTimeOut ) +#endif + +#ifndef traceRETURN_vTaskSetTimeOutState + #define traceRETURN_vTaskSetTimeOutState() +#endif + +#ifndef traceENTER_vTaskInternalSetTimeOutState + #define traceENTER_vTaskInternalSetTimeOutState( pxTimeOut ) +#endif + +#ifndef traceRETURN_vTaskInternalSetTimeOutState + #define traceRETURN_vTaskInternalSetTimeOutState() +#endif + +#ifndef traceENTER_xTaskCheckForTimeOut + #define traceENTER_xTaskCheckForTimeOut( pxTimeOut, pxTicksToWait ) +#endif + +#ifndef traceRETURN_xTaskCheckForTimeOut + #define traceRETURN_xTaskCheckForTimeOut( xReturn ) +#endif + +#ifndef traceENTER_vTaskMissedYield + #define traceENTER_vTaskMissedYield() +#endif + +#ifndef traceRETURN_vTaskMissedYield + #define traceRETURN_vTaskMissedYield() +#endif + +#ifndef traceENTER_uxTaskGetTaskNumber + #define traceENTER_uxTaskGetTaskNumber( xTask ) +#endif + +#ifndef traceRETURN_uxTaskGetTaskNumber + #define traceRETURN_uxTaskGetTaskNumber( uxReturn ) +#endif + +#ifndef traceENTER_vTaskSetTaskNumber + #define traceENTER_vTaskSetTaskNumber( xTask, uxHandle ) +#endif + +#ifndef traceRETURN_vTaskSetTaskNumber + #define traceRETURN_vTaskSetTaskNumber() +#endif + +#ifndef traceENTER_eTaskConfirmSleepModeStatus + #define traceENTER_eTaskConfirmSleepModeStatus() +#endif + +#ifndef traceRETURN_eTaskConfirmSleepModeStatus + #define traceRETURN_eTaskConfirmSleepModeStatus( eReturn ) +#endif + +#ifndef traceENTER_vTaskSetThreadLocalStoragePointer + #define traceENTER_vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue ) +#endif + +#ifndef traceRETURN_vTaskSetThreadLocalStoragePointer + #define traceRETURN_vTaskSetThreadLocalStoragePointer() +#endif + +#ifndef traceENTER_pvTaskGetThreadLocalStoragePointer + #define traceENTER_pvTaskGetThreadLocalStoragePointer( xTaskToQuery, xIndex ) +#endif + +#ifndef traceRETURN_pvTaskGetThreadLocalStoragePointer + #define traceRETURN_pvTaskGetThreadLocalStoragePointer( pvReturn ) +#endif + +#ifndef traceENTER_vTaskAllocateMPURegions + #define traceENTER_vTaskAllocateMPURegions( xTaskToModify, pxRegions ) +#endif + +#ifndef traceRETURN_vTaskAllocateMPURegions + #define traceRETURN_vTaskAllocateMPURegions() +#endif + +#ifndef traceENTER_vTaskGetInfo + #define traceENTER_vTaskGetInfo( xTask, pxTaskStatus, xGetFreeStackSpace, eState ) +#endif + +#ifndef traceRETURN_vTaskGetInfo + #define traceRETURN_vTaskGetInfo() +#endif + +#ifndef traceENTER_uxTaskGetStackHighWaterMark2 + #define traceENTER_uxTaskGetStackHighWaterMark2( xTask ) +#endif + +#ifndef traceRETURN_uxTaskGetStackHighWaterMark2 + #define traceRETURN_uxTaskGetStackHighWaterMark2( uxReturn ) +#endif + +#ifndef traceENTER_uxTaskGetStackHighWaterMark + #define traceENTER_uxTaskGetStackHighWaterMark( xTask ) +#endif + +#ifndef traceRETURN_uxTaskGetStackHighWaterMark + #define traceRETURN_uxTaskGetStackHighWaterMark( uxReturn ) +#endif + +#ifndef traceENTER_xTaskGetCurrentTaskHandle + #define traceENTER_xTaskGetCurrentTaskHandle() +#endif + +#ifndef traceRETURN_xTaskGetCurrentTaskHandle + #define traceRETURN_xTaskGetCurrentTaskHandle( xReturn ) +#endif + +#ifndef traceENTER_xTaskGetCurrentTaskHandleCPU + #define traceENTER_xTaskGetCurrentTaskHandleCPU( xCoreID ) +#endif + +#ifndef traceRETURN_xTaskGetCurrentTaskHandleCPU + #define traceRETURN_xTaskGetCurrentTaskHandleCPU( xReturn ) +#endif + +#ifndef traceENTER_xTaskGetSchedulerState + #define traceENTER_xTaskGetSchedulerState() +#endif + +#ifndef traceRETURN_xTaskGetSchedulerState + #define traceRETURN_xTaskGetSchedulerState( xReturn ) +#endif + +#ifndef traceENTER_xTaskPriorityInherit + #define traceENTER_xTaskPriorityInherit( pxMutexHolder ) +#endif + +#ifndef traceRETURN_xTaskPriorityInherit + #define traceRETURN_xTaskPriorityInherit( xReturn ) +#endif + +#ifndef traceENTER_xTaskPriorityDisinherit + #define traceENTER_xTaskPriorityDisinherit( pxMutexHolder ) +#endif + +#ifndef traceRETURN_xTaskPriorityDisinherit + #define traceRETURN_xTaskPriorityDisinherit( xReturn ) +#endif + +#ifndef traceENTER_vTaskPriorityDisinheritAfterTimeout + #define traceENTER_vTaskPriorityDisinheritAfterTimeout( pxMutexHolder, uxHighestPriorityWaitingTask ) +#endif + +#ifndef traceRETURN_vTaskPriorityDisinheritAfterTimeout + #define traceRETURN_vTaskPriorityDisinheritAfterTimeout() +#endif + +#ifndef traceENTER_vTaskYieldWithinAPI + #define traceENTER_vTaskYieldWithinAPI() +#endif + +#ifndef traceRETURN_vTaskYieldWithinAPI + #define traceRETURN_vTaskYieldWithinAPI() +#endif + +#ifndef traceENTER_vTaskEnterCritical + #define traceENTER_vTaskEnterCritical() +#endif + +#ifndef traceRETURN_vTaskEnterCritical + #define traceRETURN_vTaskEnterCritical() +#endif + +#ifndef traceENTER_vTaskEnterCriticalFromISR + #define traceENTER_vTaskEnterCriticalFromISR() +#endif + +#ifndef traceRETURN_vTaskEnterCriticalFromISR + #define traceRETURN_vTaskEnterCriticalFromISR( uxSavedInterruptStatus ) +#endif + +#ifndef traceENTER_vTaskExitCritical + #define traceENTER_vTaskExitCritical() +#endif + +#ifndef traceRETURN_vTaskExitCritical + #define traceRETURN_vTaskExitCritical() +#endif + +#ifndef traceENTER_vTaskExitCriticalFromISR + #define traceENTER_vTaskExitCriticalFromISR( uxSavedInterruptStatus ) +#endif + +#ifndef traceRETURN_vTaskExitCriticalFromISR + #define traceRETURN_vTaskExitCriticalFromISR() +#endif + +#ifndef traceENTER_vTaskListTasks + #define traceENTER_vTaskListTasks( pcWriteBuffer, uxBufferLength ) +#endif + +#ifndef traceRETURN_vTaskListTasks + #define traceRETURN_vTaskListTasks() +#endif + +#ifndef traceENTER_vTaskGetRunTimeStatistics + #define traceENTER_vTaskGetRunTimeStatistics( pcWriteBuffer, uxBufferLength ) +#endif + +#ifndef traceRETURN_vTaskGetRunTimeStatistics + #define traceRETURN_vTaskGetRunTimeStatistics() +#endif + +#ifndef traceENTER_uxTaskResetEventItemValue + #define traceENTER_uxTaskResetEventItemValue() +#endif + +#ifndef traceRETURN_uxTaskResetEventItemValue + #define traceRETURN_uxTaskResetEventItemValue( uxReturn ) +#endif + +#ifndef traceENTER_pvTaskIncrementMutexHeldCount + #define traceENTER_pvTaskIncrementMutexHeldCount() +#endif + +#ifndef traceRETURN_pvTaskIncrementMutexHeldCount + #define traceRETURN_pvTaskIncrementMutexHeldCount( pxTCB ) +#endif + +#ifndef traceENTER_ulTaskGenericNotifyTake + #define traceENTER_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) +#endif + +#ifndef traceRETURN_ulTaskGenericNotifyTake + #define traceRETURN_ulTaskGenericNotifyTake( ulReturn ) +#endif + +#ifndef traceENTER_xTaskGenericNotifyWait + #define traceENTER_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) +#endif + +#ifndef traceRETURN_xTaskGenericNotifyWait + #define traceRETURN_xTaskGenericNotifyWait( xReturn ) +#endif + +#ifndef traceENTER_xTaskGenericNotify + #define traceENTER_xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue ) +#endif + +#ifndef traceRETURN_xTaskGenericNotify + #define traceRETURN_xTaskGenericNotify( xReturn ) +#endif + +#ifndef traceENTER_xTaskGenericNotifyFromISR + #define traceENTER_xTaskGenericNotifyFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xTaskGenericNotifyFromISR + #define traceRETURN_xTaskGenericNotifyFromISR( xReturn ) +#endif + +#ifndef traceENTER_vTaskGenericNotifyGiveFromISR + #define traceENTER_vTaskGenericNotifyGiveFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_vTaskGenericNotifyGiveFromISR + #define traceRETURN_vTaskGenericNotifyGiveFromISR() +#endif + +#ifndef traceENTER_xTaskGenericNotifyStateClear + #define traceENTER_xTaskGenericNotifyStateClear( xTask, uxIndexToClear ) +#endif + +#ifndef traceRETURN_xTaskGenericNotifyStateClear + #define traceRETURN_xTaskGenericNotifyStateClear( xReturn ) +#endif + +#ifndef traceENTER_ulTaskGenericNotifyValueClear + #define traceENTER_ulTaskGenericNotifyValueClear( xTask, uxIndexToClear, ulBitsToClear ) +#endif + +#ifndef traceRETURN_ulTaskGenericNotifyValueClear + #define traceRETURN_ulTaskGenericNotifyValueClear( ulReturn ) +#endif + +#ifndef traceENTER_ulTaskGetRunTimeCounter + #define traceENTER_ulTaskGetRunTimeCounter( xTask ) +#endif + +#ifndef traceRETURN_ulTaskGetRunTimeCounter + #define traceRETURN_ulTaskGetRunTimeCounter( ulRunTimeCounter ) +#endif + +#ifndef traceENTER_ulTaskGetRunTimePercent + #define traceENTER_ulTaskGetRunTimePercent( xTask ) +#endif + +#ifndef traceRETURN_ulTaskGetRunTimePercent + #define traceRETURN_ulTaskGetRunTimePercent( ulReturn ) +#endif + +#ifndef traceENTER_ulTaskGetIdleRunTimeCounter + #define traceENTER_ulTaskGetIdleRunTimeCounter() +#endif + +#ifndef traceRETURN_ulTaskGetIdleRunTimeCounter + #define traceRETURN_ulTaskGetIdleRunTimeCounter( ulReturn ) +#endif + +#ifndef traceENTER_ulTaskGetIdleRunTimePercent + #define traceENTER_ulTaskGetIdleRunTimePercent() +#endif + +#ifndef traceRETURN_ulTaskGetIdleRunTimePercent + #define traceRETURN_ulTaskGetIdleRunTimePercent( ulReturn ) +#endif + +#ifndef traceENTER_xTaskGetMPUSettings + #define traceENTER_xTaskGetMPUSettings( xTask ) +#endif + +#ifndef traceRETURN_xTaskGetMPUSettings + #define traceRETURN_xTaskGetMPUSettings( xMPUSettings ) +#endif + +#ifndef traceENTER_xStreamBufferGenericCreate + #define traceENTER_xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) +#endif + +#ifndef traceRETURN_xStreamBufferGenericCreate + #define traceRETURN_xStreamBufferGenericCreate( pvAllocatedMemory ) +#endif + +#ifndef traceENTER_xStreamBufferGenericCreateStatic + #define traceENTER_xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, xIsMessageBuffer, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) +#endif + +#ifndef traceRETURN_xStreamBufferGenericCreateStatic + #define traceRETURN_xStreamBufferGenericCreateStatic( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferGetStaticBuffers + #define traceENTER_xStreamBufferGetStaticBuffers( xStreamBuffer, ppucStreamBufferStorageArea, ppxStaticStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferGetStaticBuffers + #define traceRETURN_xStreamBufferGetStaticBuffers( xReturn ) +#endif + +#ifndef traceENTER_vStreamBufferDelete + #define traceENTER_vStreamBufferDelete( xStreamBuffer ) +#endif + +#ifndef traceRETURN_vStreamBufferDelete + #define traceRETURN_vStreamBufferDelete() +#endif + +#ifndef traceENTER_xStreamBufferReset + #define traceENTER_xStreamBufferReset( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferReset + #define traceRETURN_xStreamBufferReset( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSetTriggerLevel + #define traceENTER_xStreamBufferSetTriggerLevel( xStreamBuffer, xTriggerLevel ) +#endif + +#ifndef traceRETURN_xStreamBufferSetTriggerLevel + #define traceRETURN_xStreamBufferSetTriggerLevel( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSpacesAvailable + #define traceENTER_xStreamBufferSpacesAvailable( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferSpacesAvailable + #define traceRETURN_xStreamBufferSpacesAvailable( xSpace ) +#endif + +#ifndef traceENTER_xStreamBufferBytesAvailable + #define traceENTER_xStreamBufferBytesAvailable( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferBytesAvailable + #define traceRETURN_xStreamBufferBytesAvailable( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSend + #define traceENTER_xStreamBufferSend( xStreamBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) +#endif + +#ifndef traceRETURN_xStreamBufferSend + #define traceRETURN_xStreamBufferSend( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSendFromISR + #define traceENTER_xStreamBufferSendFromISR( xStreamBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferSendFromISR + #define traceRETURN_xStreamBufferSendFromISR( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferReceive + #define traceENTER_xStreamBufferReceive( xStreamBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) +#endif + +#ifndef traceRETURN_xStreamBufferReceive + #define traceRETURN_xStreamBufferReceive( xReceivedLength ) +#endif + +#ifndef traceENTER_xStreamBufferNextMessageLengthBytes + #define traceENTER_xStreamBufferNextMessageLengthBytes( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferNextMessageLengthBytes + #define traceRETURN_xStreamBufferNextMessageLengthBytes( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferReceiveFromISR + #define traceENTER_xStreamBufferReceiveFromISR( xStreamBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferReceiveFromISR + #define traceRETURN_xStreamBufferReceiveFromISR( xReceivedLength ) +#endif + +#ifndef traceENTER_xStreamBufferIsEmpty + #define traceENTER_xStreamBufferIsEmpty( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferIsEmpty + #define traceRETURN_xStreamBufferIsEmpty( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferIsFull + #define traceENTER_xStreamBufferIsFull( xStreamBuffer ) +#endif + +#ifndef traceRETURN_xStreamBufferIsFull + #define traceRETURN_xStreamBufferIsFull( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferSendCompletedFromISR + #define traceENTER_xStreamBufferSendCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferSendCompletedFromISR + #define traceRETURN_xStreamBufferSendCompletedFromISR( xReturn ) +#endif + +#ifndef traceENTER_xStreamBufferReceiveCompletedFromISR + #define traceENTER_xStreamBufferReceiveCompletedFromISR( xStreamBuffer, pxHigherPriorityTaskWoken ) +#endif + +#ifndef traceRETURN_xStreamBufferReceiveCompletedFromISR + #define traceRETURN_xStreamBufferReceiveCompletedFromISR( xReturn ) +#endif + +#ifndef traceENTER_uxStreamBufferGetStreamBufferNumber + #define traceENTER_uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) +#endif + +#ifndef traceRETURN_uxStreamBufferGetStreamBufferNumber + #define traceRETURN_uxStreamBufferGetStreamBufferNumber( uxStreamBufferNumber ) +#endif + +#ifndef traceENTER_vStreamBufferSetStreamBufferNumber + #define traceENTER_vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxStreamBufferNumber ) +#endif + +#ifndef traceRETURN_vStreamBufferSetStreamBufferNumber + #define traceRETURN_vStreamBufferSetStreamBufferNumber() +#endif + +#ifndef traceENTER_ucStreamBufferGetStreamBufferType + #define traceENTER_ucStreamBufferGetStreamBufferType( xStreamBuffer ) +#endif + +#ifndef traceRETURN_ucStreamBufferGetStreamBufferType + #define traceRETURN_ucStreamBufferGetStreamBufferType( ucStreamBufferType ) +#endif + +#ifndef traceENTER_vListInitialise + #define traceENTER_vListInitialise( pxList ) +#endif + +#ifndef traceRETURN_vListInitialise + #define traceRETURN_vListInitialise() +#endif + +#ifndef traceENTER_vListInitialiseItem + #define traceENTER_vListInitialiseItem( pxItem ) +#endif + +#ifndef traceRETURN_vListInitialiseItem + #define traceRETURN_vListInitialiseItem() +#endif + +#ifndef traceENTER_vListInsertEnd + #define traceENTER_vListInsertEnd( pxList, pxNewListItem ) +#endif + +#ifndef traceRETURN_vListInsertEnd + #define traceRETURN_vListInsertEnd() +#endif + +#ifndef traceENTER_vListInsert + #define traceENTER_vListInsert( pxList, pxNewListItem ) +#endif + +#ifndef traceRETURN_vListInsert + #define traceRETURN_vListInsert() +#endif + +#ifndef traceENTER_uxListRemove + #define traceENTER_uxListRemove( pxItemToRemove ) +#endif + +#ifndef traceRETURN_uxListRemove + #define traceRETURN_uxListRemove( uxNumberOfItems ) +#endif + +#ifndef traceENTER_xCoRoutineCreate + #define traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex ) +#endif + +#ifndef traceRETURN_xCoRoutineCreate + #define traceRETURN_xCoRoutineCreate( xReturn ) +#endif + +#ifndef traceENTER_vCoRoutineAddToDelayedList + #define traceENTER_vCoRoutineAddToDelayedList( xTicksToDelay, pxEventList ) +#endif + +#ifndef traceRETURN_vCoRoutineAddToDelayedList + #define traceRETURN_vCoRoutineAddToDelayedList() +#endif + +#ifndef traceENTER_vCoRoutineSchedule + #define traceENTER_vCoRoutineSchedule() +#endif + +#ifndef traceRETURN_vCoRoutineSchedule + #define traceRETURN_vCoRoutineSchedule() +#endif + +#ifndef traceENTER_xCoRoutineRemoveFromEventList + #define traceENTER_xCoRoutineRemoveFromEventList( pxEventList ) +#endif + +#ifndef traceRETURN_xCoRoutineRemoveFromEventList + #define traceRETURN_xCoRoutineRemoveFromEventList( xReturn ) +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT + #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef portSUPPRESS_TICKS_AND_SLEEP + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) +#endif + +#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP + #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 +#endif + +#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 + #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 +#endif + +#ifndef configUSE_TICKLESS_IDLE + #define configUSE_TICKLESS_IDLE 0 +#endif + +#ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING + #define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPRE_SLEEP_PROCESSING + #define configPRE_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPOST_SLEEP_PROCESSING + #define configPOST_SLEEP_PROCESSING( x ) +#endif + +#ifndef configUSE_QUEUE_SETS + #define configUSE_QUEUE_SETS 0 +#endif + +#ifndef portTASK_USES_FLOATING_POINT + #define portTASK_USES_FLOATING_POINT() +#endif + +#ifndef portALLOCATE_SECURE_CONTEXT + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) +#endif + +#ifndef portDONT_DISCARD + #define portDONT_DISCARD +#endif + +#ifndef configUSE_TIME_SLICING + #define configUSE_TIME_SLICING 1 +#endif + +#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS + #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 +#endif + +#ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#endif + +#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() +#endif + +#ifndef configUSE_TRACE_FACILITY + #define configUSE_TRACE_FACILITY 0 +#endif + +#ifndef mtCOVERAGE_TEST_MARKER + #define mtCOVERAGE_TEST_MARKER() +#endif + +#ifndef mtCOVERAGE_TEST_DELAY + #define mtCOVERAGE_TEST_DELAY() +#endif + +#ifndef portASSERT_IF_IN_ISR + #define portASSERT_IF_IN_ISR() +#endif + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +#ifndef configAPPLICATION_ALLOCATED_HEAP + #define configAPPLICATION_ALLOCATED_HEAP 0 +#endif + +#ifndef configENABLE_HEAP_PROTECTOR + #define configENABLE_HEAP_PROTECTOR 0 +#endif + +#ifndef configUSE_TASK_NOTIFICATIONS + #define configUSE_TASK_NOTIFICATIONS 1 +#endif + +#ifndef configTASK_NOTIFICATION_ARRAY_ENTRIES + #define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 +#endif + +#if configTASK_NOTIFICATION_ARRAY_ENTRIES < 1 + #error configTASK_NOTIFICATION_ARRAY_ENTRIES must be at least 1 +#endif + +#ifndef configUSE_POSIX_ERRNO + #define configUSE_POSIX_ERRNO 0 +#endif + +#ifndef configUSE_SB_COMPLETED_CALLBACK + +/* By default per-instance callbacks are not enabled for stream buffer or message buffer. */ + #define configUSE_SB_COMPLETED_CALLBACK 0 +#endif + +#ifndef portTICK_TYPE_IS_ATOMIC + #define portTICK_TYPE_IS_ATOMIC 0 +#endif + +#ifndef configSUPPORT_STATIC_ALLOCATION + /* Defaults to 0 for backward compatibility. */ + #define configSUPPORT_STATIC_ALLOCATION 0 +#endif + +#ifndef configKERNEL_PROVIDED_STATIC_MEMORY + #define configKERNEL_PROVIDED_STATIC_MEMORY 0 +#endif + +#ifndef configSUPPORT_DYNAMIC_ALLOCATION + /* Defaults to 1 for backward compatibility. */ + #define configSUPPORT_DYNAMIC_ALLOCATION 1 +#endif + +#if ( ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION != 1 ) ) + #error configUSE_STATS_FORMATTING_FUNCTIONS cannot be used without dynamic allocation, but configSUPPORT_DYNAMIC_ALLOCATION is not set to 1. +#endif + +#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) + #if ( ( configUSE_TRACE_FACILITY != 1 ) && ( configGENERATE_RUN_TIME_STATS != 1 ) ) + #error configUSE_STATS_FORMATTING_FUNCTIONS is 1 but the functions it enables are not used because neither configUSE_TRACE_FACILITY or configGENERATE_RUN_TIME_STATS are 1. Set configUSE_STATS_FORMATTING_FUNCTIONS to 0 in FreeRTOSConfig.h. + #endif +#endif + +#ifndef configSTATS_BUFFER_MAX_LENGTH + #define configSTATS_BUFFER_MAX_LENGTH 0xFFFF +#endif + +#ifndef configSTACK_DEPTH_TYPE + +/* Defaults to uint16_t for backward compatibility, but can be overridden + * in FreeRTOSConfig.h if uint16_t is too restrictive. */ + #define configSTACK_DEPTH_TYPE uint16_t +#endif + +#ifndef configRUN_TIME_COUNTER_TYPE + +/* Defaults to uint32_t for backward compatibility, but can be overridden in + * FreeRTOSConfig.h if uint32_t is too restrictive. */ + + #define configRUN_TIME_COUNTER_TYPE uint32_t +#endif + +#ifndef configMESSAGE_BUFFER_LENGTH_TYPE + +/* Defaults to size_t for backward compatibility, but can be overridden + * in FreeRTOSConfig.h if lengths will always be less than the number of bytes + * in a size_t. */ + #define configMESSAGE_BUFFER_LENGTH_TYPE size_t +#endif + +/* Sanity check the configuration. */ +#if ( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) + #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. +#endif + +#if ( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) + #error configUSE_MUTEXES must be set to 1 to use recursive mutexes +#endif + +#if ( ( configRUN_MULTIPLE_PRIORITIES == 0 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) + #error configRUN_MULTIPLE_PRIORITIES must be set to 1 to use task preemption disable +#endif + +#if ( ( configUSE_PREEMPTION == 0 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) + #error configUSE_PREEMPTION must be set to 1 to use task preemption disable +#endif + +#if ( ( configNUMBER_OF_CORES == 1 ) && ( configUSE_TASK_PREEMPTION_DISABLE != 0 ) ) + #error configUSE_TASK_PREEMPTION_DISABLE is not supported in single core FreeRTOS +#endif + +#if ( ( configNUMBER_OF_CORES == 1 ) && ( configUSE_CORE_AFFINITY != 0 ) ) + #error configUSE_CORE_AFFINITY is not supported in single core FreeRTOS +#endif + +#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_PORT_OPTIMISED_TASK_SELECTION != 0 ) ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION is not supported in SMP FreeRTOS +#endif + +#ifndef configINITIAL_TICK_COUNT + #define configINITIAL_TICK_COUNT 0 +#endif + +#if ( portTICK_TYPE_IS_ATOMIC == 0 ) + +/* Either variables of tick type cannot be read atomically, or + * portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when + * the tick count is returned to the standard critical section macros. */ + #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) +#else + +/* The tick type can be read atomically, so critical sections used when the + * tick count is returned can be defined away. */ + #define portTICK_TYPE_ENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) ( x ) +#endif /* if ( portTICK_TYPE_IS_ATOMIC == 0 ) */ + +/* Definitions to allow backward compatibility with FreeRTOS versions prior to + * V8 if desired. */ +#ifndef configENABLE_BACKWARD_COMPATIBILITY + #define configENABLE_BACKWARD_COMPATIBILITY 1 +#endif + +#ifndef configPRINTF + +/* configPRINTF() was not defined, so define it away to nothing. To use + * configPRINTF() then define it as follows (where MyPrintFunction() is + * provided by the application writer): + * + * void MyPrintFunction(const char *pcFormat, ... ); + #define configPRINTF( X ) MyPrintFunction X + * + * Then call like a standard printf() function, but placing brackets around + * all parameters so they are passed as a single parameter. For example: + * configPRINTF( ("Value = %d", MyVariable) ); */ + #define configPRINTF( X ) +#endif + +#ifndef configMAX + +/* The application writer has not provided their own MAX macro, so define + * the following generic implementation. */ + #define configMAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) +#endif + +#ifndef configMIN + +/* The application writer has not provided their own MIN macro, so define + * the following generic implementation. */ + #define configMIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) +#endif + +#if configENABLE_BACKWARD_COMPATIBILITY == 1 + #define eTaskStateGet eTaskGetState + #define portTickType TickType_t + #define xTaskHandle TaskHandle_t + #define xQueueHandle QueueHandle_t + #define xSemaphoreHandle SemaphoreHandle_t + #define xQueueSetHandle QueueSetHandle_t + #define xQueueSetMemberHandle QueueSetMemberHandle_t + #define xTimeOutType TimeOut_t + #define xMemoryRegion MemoryRegion_t + #define xTaskParameters TaskParameters_t + #define xTaskStatusType TaskStatus_t + #define xTimerHandle TimerHandle_t + #define xCoRoutineHandle CoRoutineHandle_t + #define pdTASK_HOOK_CODE TaskHookFunction_t + #define portTICK_RATE_MS portTICK_PERIOD_MS + #define pcTaskGetTaskName pcTaskGetName + #define pcTimerGetTimerName pcTimerGetName + #define pcQueueGetQueueName pcQueueGetName + #define vTaskGetTaskInfo vTaskGetInfo + #define xTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter + +/* Backward compatibility within the scheduler code only - these definitions + * are not really required but are included for completeness. */ + #define tmrTIMER_CALLBACK TimerCallbackFunction_t + #define pdTASK_CODE TaskFunction_t + #define xListItem ListItem_t + #define xList List_t + +/* For libraries that break the list data hiding, and access list structure + * members directly (which is not supposed to be done). */ + #define pxContainer pvContainer +#endif /* configENABLE_BACKWARD_COMPATIBILITY */ + +#if ( configUSE_ALTERNATIVE_API != 0 ) + #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 +#endif + +/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even + * if floating point hardware is otherwise supported by the FreeRTOS port in use. + * This constant is not supported by all FreeRTOS ports that include floating + * point support. */ +#ifndef configUSE_TASK_FPU_SUPPORT + #define configUSE_TASK_FPU_SUPPORT 1 +#endif + +/* Set configENABLE_MPU to 1 to enable MPU support and 0 to disable it. This is + * currently used in ARMv8M ports. */ +#ifndef configENABLE_MPU + #define configENABLE_MPU 0 +#endif + +/* Set configENABLE_FPU to 1 to enable FPU support and 0 to disable it. This is + * currently used in ARMv8M ports. */ +#ifndef configENABLE_FPU + #define configENABLE_FPU 1 +#endif + +/* Set configENABLE_MVE to 1 to enable MVE support and 0 to disable it. This is + * currently used in ARMv8M ports. */ +#ifndef configENABLE_MVE + #define configENABLE_MVE 0 +#endif + +/* Set configENABLE_TRUSTZONE to 1 enable TrustZone support and 0 to disable it. + * This is currently used in ARMv8M ports. */ +#ifndef configENABLE_TRUSTZONE + #define configENABLE_TRUSTZONE 1 +#endif + +/* Set configRUN_FREERTOS_SECURE_ONLY to 1 to run the FreeRTOS ARMv8M port on + * the Secure Side only. */ +#ifndef configRUN_FREERTOS_SECURE_ONLY + #define configRUN_FREERTOS_SECURE_ONLY 0 +#endif + +#ifndef configRUN_ADDITIONAL_TESTS + #define configRUN_ADDITIONAL_TESTS 0 +#endif + +/* The following config allows infinite loop control. For example, control the + * infinite loop in idle task function when performing unit tests. */ +#ifndef configCONTROL_INFINITE_LOOP + #define configCONTROL_INFINITE_LOOP() +#endif + +/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using + * dynamically allocated RAM, in which case when any task is deleted it is known + * that both the task's stack and TCB need to be freed. Sometimes the + * FreeRTOSConfig.h settings only allow a task to be created using statically + * allocated RAM, in which case when any task is deleted it is known that neither + * the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h + * settings allow a task to be created using either statically or dynamically + * allocated RAM, in which case a member of the TCB is used to record whether the + * stack and/or TCB were allocated statically or dynamically, so when a task is + * deleted the RAM that was allocated dynamically is freed again and no attempt is + * made to free the RAM that was allocated statically. + * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a + * task to be created using either statically or dynamically allocated RAM. Note + * that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with + * a statically allocated stack and a dynamically allocated TCB. + * + * The following table lists various combinations of portUSING_MPU_WRAPPERS, + * configSUPPORT_DYNAMIC_ALLOCATION and configSUPPORT_STATIC_ALLOCATION and + * when it is possible to have both static and dynamic allocation: + * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ + * | MPU | Dynamic | Static | Available Functions | Possible Allocations | Both Dynamic and | Need Free | + * | | | | | | Static Possible | | + * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ + * | 0 | 0 | 1 | xTaskCreateStatic | TCB - Static, Stack - Static | No | No | + * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| + * | 0 | 1 | 0 | xTaskCreate | TCB - Dynamic, Stack - Dynamic | No | Yes | + * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| + * | 0 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes | + * | | | | xTaskCreateStatic | 2. TCB - Static, Stack - Static | | | + * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| + * | 1 | 0 | 1 | xTaskCreateStatic, | TCB - Static, Stack - Static | No | No | + * | | | | xTaskCreateRestrictedStatic | | | | + * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| + * | 1 | 1 | 0 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes | + * | | | | xTaskCreateRestricted | 2. TCB - Dynamic, Stack - Static | | | + * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| + * | 1 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes | + * | | | | xTaskCreateStatic, | 2. TCB - Dynamic, Stack - Static | | | + * | | | | xTaskCreateRestricted, | 3. TCB - Static, Stack - Static | | | + * | | | | xTaskCreateRestrictedStatic | | | | + * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ + */ +#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE \ + ( ( ( portUSING_MPU_WRAPPERS == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) || \ + ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) ) + +/* + * In line with software engineering best practice, FreeRTOS implements a strict + * data hiding policy, so the real structures used by FreeRTOS to maintain the + * state of tasks, queues, semaphores, etc. are not accessible to the application + * code. However, if the application writer wants to statically allocate such + * an object then the size of the object needs to be known. Dummy structures + * that are guaranteed to have the same size and alignment requirements of the + * real objects are used for this purpose. The dummy list and list item + * structures below are used for inclusion in such a dummy structure. + */ +struct xSTATIC_LIST_ITEM +{ + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + TickType_t xDummy2; + void * pvDummy3[ 4 ]; + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy4; + #endif +}; +typedef struct xSTATIC_LIST_ITEM StaticListItem_t; + +#if ( configUSE_MINI_LIST_ITEM == 1 ) + /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ + struct xSTATIC_MINI_LIST_ITEM + { + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + TickType_t xDummy2; + void * pvDummy3[ 2 ]; + }; + typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; +#else /* if ( configUSE_MINI_LIST_ITEM == 1 ) */ + typedef struct xSTATIC_LIST_ITEM StaticMiniListItem_t; +#endif /* if ( configUSE_MINI_LIST_ITEM == 1 ) */ + +/* See the comments above the struct xSTATIC_LIST_ITEM definition. */ +typedef struct xSTATIC_LIST +{ + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + UBaseType_t uxDummy2; + void * pvDummy3; + StaticMiniListItem_t xDummy4; + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy5; + #endif +} StaticList_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the Task structure used internally by + * FreeRTOS is not accessible to application code. However, if the application + * writer wants to statically allocate the memory required to create a task then + * the size of the task object needs to be known. The StaticTask_t structure + * below is provided for this purpose. Its sizes and alignment requirements are + * guaranteed to match those of the genuine structure, no matter which + * architecture is being used, and no matter how the values in FreeRTOSConfig.h + * are set. Its contents are somewhat obfuscated in the hope users will + * recognise that it would be unwise to make direct use of the structure members. + */ +typedef struct xSTATIC_TCB +{ + void * pxDummy1; + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xDummy2; + #endif + #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) + UBaseType_t uxDummy26; + #endif + /* Modifying this structure to cause a configASSERT */ + /* StaticListItem_t xDummy3[ 2 ]; */ + /* UBaseType_t uxDummy5; */ + /* void * pxDummy6; */ + #if ( configNUMBER_OF_CORES > 1 ) + BaseType_t xDummy23; + UBaseType_t uxDummy24; + #endif + uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; + #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) + BaseType_t xDummy25; + #endif + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) + void * pxDummy8; + #endif + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxDummy9; + #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy10[ 2 ]; + #endif + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxDummy12[ 2 ]; + #endif + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + void * pxDummy14; + #endif + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + configRUN_TIME_COUNTER_TYPE ulDummy16; + #endif + #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) + configTLS_BLOCK_TYPE xDummy17; + #endif + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + #endif + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + uint8_t uxDummy20; + #endif + + #if ( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDummy21; + #endif + #if ( configUSE_POSIX_ERRNO == 1 ) + int iDummy22; + #endif +} StaticTask_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the Queue structure used internally by + * FreeRTOS is not accessible to application code. However, if the application + * writer wants to statically allocate the memory required to create a queue + * then the size of the queue object needs to be known. The StaticQueue_t + * structure below is provided for this purpose. Its sizes and alignment + * requirements are guaranteed to match those of the genuine structure, no + * matter which architecture is being used, and no matter how the values in + * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope + * users will recognise that it would be unwise to make direct use of the + * structure members. + */ +typedef struct xSTATIC_QUEUE +{ + void * pvDummy1[ 3 ]; + + union + { + void * pvDummy2; + UBaseType_t uxDummy2; + } u; + + StaticList_t xDummy3[ 2 ]; + UBaseType_t uxDummy4[ 3 ]; + uint8_t ucDummy5[ 2 ]; + + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy6; + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + void * pvDummy7; + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy8; + uint8_t ucDummy9; + #endif +} StaticQueue_t; +typedef StaticQueue_t StaticSemaphore_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the event group structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create an event group then the size of the event group object needs to be + * know. The StaticEventGroup_t structure below is provided for this purpose. + * Its sizes and alignment requirements are guaranteed to match those of the + * genuine structure, no matter which architecture is being used, and no matter + * how the values in FreeRTOSConfig.h are set. Its contents are somewhat + * obfuscated in the hope users will recognise that it would be unwise to make + * direct use of the structure members. + */ +typedef struct xSTATIC_EVENT_GROUP +{ + TickType_t xDummy1; + StaticList_t xDummy2; + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy3; + #endif + + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy4; + #endif +} StaticEventGroup_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the software timer structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create a software timer then the size of the queue object needs to be known. + * The StaticTimer_t structure below is provided for this purpose. Its sizes + * and alignment requirements are guaranteed to match those of the genuine + * structure, no matter which architecture is being used, and no matter how the + * values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in + * the hope users will recognise that it would be unwise to make direct use of + * the structure members. + */ +typedef struct xSTATIC_TIMER +{ + void * pvDummy1; + StaticListItem_t xDummy2; + TickType_t xDummy3; + void * pvDummy5; + TaskFunction_t pvDummy6; + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy7; + #endif + uint8_t ucDummy8; +} StaticTimer_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the stream buffer structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create a stream buffer then the size of the stream buffer object needs to be + * known. The StaticStreamBuffer_t structure below is provided for this + * purpose. Its size and alignment requirements are guaranteed to match those + * of the genuine structure, no matter which architecture is being used, and + * no matter how the values in FreeRTOSConfig.h are set. Its contents are + * somewhat obfuscated in the hope users will recognise that it would be unwise + * to make direct use of the structure members. + */ +typedef struct xSTATIC_STREAM_BUFFER +{ + size_t uxDummy1[ 4 ]; + void * pvDummy2[ 3 ]; + uint8_t ucDummy3; + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy4; + #endif + #if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) + void * pvDummy5[ 2 ]; + #endif +} StaticStreamBuffer_t; + +/* Message buffers are built on stream buffers. */ +typedef StaticStreamBuffer_t StaticMessageBuffer_t; + +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + +#endif /* INC_FREERTOS_H */ diff --git a/FreeRTOS/Test/CMock/tasks/tasks_freertos/FreeRTOSConfig.h b/FreeRTOS/Test/CMock/tasks/tasks_freertos/FreeRTOSConfig.h new file mode 100644 index 000000000..93d72b227 --- /dev/null +++ b/FreeRTOS/Test/CMock/tasks/tasks_freertos/FreeRTOSConfig.h @@ -0,0 +1,144 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "fake_assert.h" + +/* XXX: this file will be processed by unifdef to generate new header files + * that can be mocked according to the configurations desired + * it has a few limitations on the format of this file such as: + * no config that spans more than one line + * no strings in config names + * for more info please check the man file with $ man unifdef + */ + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* http://www.freertos.org/a00110.html +*----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_TICKLESS_IDLE 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 5 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) /* For test. */ +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 1 /* As there are a lot of tasks running. */ + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 9 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() +#define portUSING_MPU_WRAPPERS 0 +#define configENABLE_MPU 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +#define portSTACK_GROWTH ( -1 ) +#define configRECORD_STACK_HIGH_ADDRESS 1 + +/* This demo makes use of one or more example stats formatting functions. These + * format the raw data provided by the uxTaskGetSystemState() function in to human + * readable ASCII form. See the notes in the implementation of vTaskList() within + * FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. */ +/* *INDENT-OFF* */ +#define configASSERT( x ) do { if( x ) { vFakeAssert( true, __FILE__, __LINE__ ); } else { vFakeAssert( false, __FILE__, __LINE__ ); } } while( 0 ) +/* *INDENT-ON* */ + +#define portREMOVE_STATIC_QUALIFIER 1 + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 +#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/tasks/tasks_freertos/Makefile b/FreeRTOS/Test/CMock/tasks/tasks_freertos/Makefile new file mode 100644 index 000000000..966c0b17d --- /dev/null +++ b/FreeRTOS/Test/CMock/tasks/tasks_freertos/Makefile @@ -0,0 +1,77 @@ +SHELL += -x + +# Indent with spaces +.RECIPEPREFIX := $(.RECIPEPREFIX) $(.RECIPEPREFIX) + +# Do not move this line below the include +MAKEFILE_ABSPATH := $(abspath $(lastword $(MAKEFILE_LIST))) + +#PROJECT := tasks +# Project / Suite are determined based on path: $(UT_ROOT_DIR)/$(PROJECT)/$(SUITE) +PROJECT := $(lastword $(subst /, ,$(dir $(abspath $(MAKEFILE_ABSPATH)/../)))) +SUITE := $(lastword $(subst /, ,$(dir $(MAKEFILE_ABSPATH)))) + +SCRATCH_DIR := $(GENERATED_DIR)/$(PROJECT)/$(SUITE) + +include ../../makefile.in + +# PROJECT_SRC lists the .c files under test +PROJECT_SRC += tasks.c +PROJECT_DIR := $(abspath ../) +LOCAL_DIR := $(abspath .) + +# PROJECT_DEPS_SRC list the .c file that are dependencies of PROJECT_SRC files +# Files in PROJECT_DEPS_SRC are excluded from coverage measurements +PROJECT_DEPS_SRC += + +# PROJECT_HEADER_DEPS: headers that should be excluded from coverage measurements. +PROJECT_HEADER_DEPS += FreeRTOS.h + +# SUITE_UT_SRC: .c files that contain test cases (must end in _utest.c) +SUITE_UT_SRC := tasks_utest.c + +# SUITE_SUPPORT_SRC: .c files used for testing that do not contain test cases. +# Paths are relative to PROJECT_DIR +SUITE_SUPPORT_SRC += + +# List the headers used by PROJECT_SRC that you would like to mock +MOCK_FILES_ORIG := $(KERNEL_DIR)/include/timers.h +MOCK_FILES_ORIG += $(KERNEL_DIR)/include/list.h +MOCK_FILES_ORIG += $(KERNEL_DIR)/include/portable.h +MOCK_FILES_ORIG += $(PROJECT_DIR)/list_macros.h +MOCK_FILES_ORIG += $(PROJECT_DIR)/../config/fake_assert.h + +MOCK_FILES_FP := $(GENERATED_DIR)/$(PROJECT)/tasks_freertos/timers.h +MOCK_FILES_FP += $(GENERATED_DIR)/$(PROJECT)/tasks_freertos/list.h +MOCK_FILES_FP += $(GENERATED_DIR)/$(PROJECT)/tasks_freertos/portable.h +MOCK_FILES_FP += $(GENERATED_DIR)/$(PROJECT)/tasks_freertos/list_macros.h +MOCK_FILES_FP += $(GENERATED_DIR)/$(PROJECT)/tasks_freertos/fake_assert.h + +# List any addiitonal flags needed by the preprocessor +CPPFLAGS := -I $(GENERATED_DIR)/$(PROJECT)/tasks_freertos/include $(CPPFLAGS) +CPPFLAGS += -I . +CPPFLAGS += -I ../ + +# List any addiitonal flags needed by the compiler +CFLAGS += + +export +# Make variables available to included makefile + +include ../../testdir.mk + +$(MOCK_FILES_FP) : + -mkdir -p $(SCRATCH_DIR)/include + -mkdir -p $(SCRATCH_DIR)/cpp + cp $(LOCAL_DIR)/FreeRTOSConfig.h $(SCRATCH_DIR)/include/FreeRTOSConfig.h + cp $(LOCAL_DIR)/FreeRTOSConfig.h $(SCRATCH_DIR)/include/FreeRTOSConfig.def + cp $(LOCAL_DIR)/FreeRTOS.h $(SCRATCH_DIR)/include/ + sed -i '/#ifndef FREERTOS_CONFIG_H/d' $(SCRATCH_DIR)/include/FreeRTOSConfig.def + sed -i '/#define FREERTOS_CONFIG_H/d' $(SCRATCH_DIR)/include/FreeRTOSConfig.def + sed -i '/#endif/d' $(SCRATCH_DIR)/include/FreeRTOSConfig.def + sed -i '/#include/d' $(SCRATCH_DIR)/include/FreeRTOSConfig.def + for h_file in $(MOCK_FILES_ORIG) ; do \ + unifdef -f $(SCRATCH_DIR)/include/FreeRTOSConfig.def $$h_file \ + > $(SCRATCH_DIR)/$$(basename $$h_file) ; \ + done + diff --git a/FreeRTOS/Test/CMock/tasks/tasks_freertos/tasks_utest.c b/FreeRTOS/Test/CMock/tasks/tasks_freertos/tasks_utest.c new file mode 100644 index 000000000..820c4e0ad --- /dev/null +++ b/FreeRTOS/Test/CMock/tasks/tasks_freertos/tasks_utest.c @@ -0,0 +1,359 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ +/*! @file tasks_assert_utest.c */ + +/* =============================== INCLUDES =============================== */ +/* Tasks includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "fake_port.h" +#include "task.h" +#include "portmacro.h" + +/* C runtime includes. */ +#include +#include + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "CException.h" +#include "global_vars.h" + +/* Mock includes. */ +#include "mock_fake_assert.h" +#include "mock_portable.h" + +/* ================================= MACROS =============================== */ + +/** + * @brief CException code for when a configASSERT should be intercepted. + */ +#define configASSERT_E 0xAA101 + +/** + * @brief Expect a configASSERT from the function called. + * Break out of the called function when this occurs. + * @details Use this macro when the call passed in as a parameter is expected + * to cause invalid memory access. + */ +#define EXPECT_ASSERT_BREAK( call ) \ + do \ + { \ + shouldAbortOnAssertion = true; \ + CEXCEPTION_T e = CEXCEPTION_NONE; \ + Try \ + { \ + call; \ + TEST_FAIL(); \ + } \ + Catch( e ) \ + { \ + TEST_ASSERT_EQUAL( configASSERT_E, e ); \ + } \ + } while( 0 ) + +/* ============================ GLOBAL VARIABLES =========================== */ + +/** + * @brief Global counter for the number of assertions in code. + */ +static int assertionFailed = 0; + +/** + * @brief Flag which denotes if test need to abort on assertion. + */ +static BaseType_t shouldAbortOnAssertion; + +/** + * @brief counts entries to critical sections then subtracts from the variable + * when exiting, value should be zero at the end + */ +static uint32_t critical_section_counter = 0; + +static bool port_yield_within_api_called = false; +static port_yield_operation py_operation; +static bool port_disable_interrupts_called = false; +static bool port_enable_interrupts_called = false; +static bool port_yield_called = false; +static bool port_setup_tcb_called = false; +static bool portClear_Interrupt_called = false; +static bool portSet_Interrupt_called = false; +static bool portClear_Interrupt_from_isr_called = false; +static bool portSet_Interrupt_from_isr_called = false; +static bool port_invalid_interrupt_called = false; +static bool vApplicationStackOverflowHook_called = false; +static bool getIdleTaskMemoryValid = false; +static StaticTask_t xIdleTaskTCB; +static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; +static bool getIdleTaskMemory_called = false; +static bool vTaskDeletePre_called = false; +static bool vApplicationIdleHook_called = false; +static bool vApplicationTickHook_called = false; + +/* ========================== CALLBACK FUNCTIONS ========================== */ +static void vFakeAssertStub( bool x, + char * file, + int line, + int cmock_num_calls ) +{ + if( !x ) + { + assertionFailed++; + + if( shouldAbortOnAssertion == pdTRUE ) + { + Throw( configASSERT_E ); + } + } +} + +/* ========================== STATIC FUNCTIONS ============================ */ +static void validate_and_clear_assertions( void ) +{ + TEST_ASSERT_EQUAL( 1, assertionFailed ); + assertionFailed = 0; +} + + + +/* ======================== HOOK FUNCTIONS =================================*/ +void vApplicationTickHook() +{ + HOOK_DIAG(); + vApplicationTickHook_called = true; +} + +void vApplicationIdleHook( void ) +{ + HOOK_DIAG(); + vApplicationIdleHook_called = true; +} + +void vConfigureTimerForRunTimeStats( void ) +{ + HOOK_DIAG(); +} + +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) +{ + HOOK_DIAG(); + + if( getIdleTaskMemoryValid == true ) + { + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + * state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + } + else + { + *ppxIdleTaskTCBBuffer = NULL; + *ppxIdleTaskStackBuffer = NULL; + *pulIdleTaskStackSize = 0; + } + + getIdleTaskMemory_called = true; +} + +void vPortCurrentTaskDying( void * pvTaskToDelete, + volatile BaseType_t * pxPendYield ) +{ + HOOK_DIAG(); + vTaskDeletePre_called = true; +} + +void vFakePortEnterCriticalSection( void ) +{ + HOOK_DIAG(); + critical_section_counter++; +} + +void vFakePortExitCriticalSection( void ) +{ + HOOK_DIAG(); + critical_section_counter--; +} + +void vFakePortYieldWithinAPI() +{ + HOOK_DIAG(); + port_yield_within_api_called = true; + py_operation(); +} + +void vFakePortYieldFromISR() +{ + HOOK_DIAG(); +} + +uint32_t vFakePortDisableInterrupts() +{ + port_disable_interrupts_called = true; + HOOK_DIAG(); + return 0; +} + +void vFakePortEnableInterrupts() +{ + port_enable_interrupts_called = true; + HOOK_DIAG(); +} + +void vFakePortYield() +{ + HOOK_DIAG(); + port_yield_called = true; + py_operation(); +} + +void portSetupTCB_CB( void * tcb ) +{ + HOOK_DIAG(); + port_setup_tcb_called = true; +} + +void vFakePortClearInterruptMask( UBaseType_t bt ) +{ + HOOK_DIAG(); + portClear_Interrupt_called = true; +} + +UBaseType_t ulFakePortSetInterruptMask( void ) +{ + HOOK_DIAG(); + portSet_Interrupt_called = true; + return 1; +} + +void vFakePortClearInterruptMaskFromISR( UBaseType_t bt ) +{ + HOOK_DIAG(); + portClear_Interrupt_from_isr_called = true; +} + +UBaseType_t ulFakePortSetInterruptMaskFromISR( void ) +{ + HOOK_DIAG(); + portSet_Interrupt_from_isr_called = true; + return 1; +} + +void vFakePortAssertIfInterruptPriorityInvalid( void ) +{ + HOOK_DIAG(); + port_invalid_interrupt_called = true; +} + +void vApplicationStackOverflowHook( TaskHandle_t xTask, + char * stack ) +{ + HOOK_DIAG(); + vApplicationStackOverflowHook_called = true; +} + +unsigned int vFakePortGetCoreID( void ) +{ + HOOK_DIAG(); + return 0; +} + +void vFakePortReleaseTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetTaskLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortGetISRLock( void ) +{ + HOOK_DIAG(); +} + +void vFakePortReleaseISRLock( void ) +{ + HOOK_DIAG(); +} + +/* =========================== UNITY FIXTURES ============================= */ +/*! called before each test case */ +void setUp( void ) +{ + assertionFailed = 0; + shouldAbortOnAssertion = pdTRUE; + vFakeAssert_StubWithCallback( vFakeAssertStub ); +} + +/*! called after each test case */ +void tearDown( void ) +{ + TEST_ASSERT_EQUAL_MESSAGE( 0, assertionFailed, "Assertion check failed in code." ); + + mock_fake_assert_Verify(); + mock_fake_assert_Destroy(); +} + +/*! called at the beginning of the whole suite */ +void suiteSetUp() +{ +} + +/*! called at the end of the whole suite */ +int suiteTearDown( int numFailures ) +{ + return numFailures; +} + +/* ======================== TEST CASES ===================================== */ + +void test_xTaskCreateStatic_assert_static_task_eq_tcb_t( void ) +{ + TaskFunction_t xTFunc = NULL; + StaticTask_t xTaskBuffer[ 200 ]; + StackType_t xStackBuffer[ 200 ]; + + EXPECT_ASSERT_BREAK( xTaskCreateStatic( xTFunc, + NULL, + 120, + NULL, + 3, + xStackBuffer, + xTaskBuffer ) ); + + validate_and_clear_assertions(); +} diff --git a/FreeRTOS/Test/CMock/timers/timers_1_utest.c b/FreeRTOS/Test/CMock/timers/timers_1_utest.c index d7273027d..b2af29234 100644 --- a/FreeRTOS/Test/CMock/timers/timers_1_utest.c +++ b/FreeRTOS/Test/CMock/timers/timers_1_utest.c @@ -219,6 +219,19 @@ static void xCallback_Test_2_end( TimerHandle_t xTimer ) * pthread_exit( &i ); * } */ + +/** + * @brief Callback for vTaskYieldTaskWithinAPI used by tests for yield counts + * + * NumCalls is checked in the test assert. + */ +static void vTaskYieldWithinAPI_Callback( int NumCalls ) +{ + ( void ) NumCalls; + + portYIELD_WITHIN_API(); +} + /* ============================= STATIC FUNCTIONS ========================= */ static void * timer_thread_function( void * args ) { @@ -823,6 +836,7 @@ void test_timer_function_success3( void ) vQueueWaitForMessageRestricted_ExpectAnyArgs(); xTaskResumeAll_ExpectAndReturn( pdFALSE ); /* no context switch.. yield */ /* yield called */ + vTaskYieldWithinAPI_Stub( vTaskYieldWithinAPI_Callback ); /* API Call */ pthread_create( &thread_id, NULL, &timer_thread_function, NULL ); diff --git a/manifest.yml b/manifest.yml index 3a3c94cff..055c69433 100644 --- a/manifest.yml +++ b/manifest.yml @@ -5,7 +5,7 @@ license: "MIT" dependencies: - name: "FreeRTOS-Kernel" - version: "4ada1d7d5" + version: "5281427a9" repository: type: "git" url: "https://github.com/FreeRTOS/FreeRTOS-Kernel.git"