diff --git a/FreeRTOS/Source b/FreeRTOS/Source index 4d9cd906d3..c4e99bf09f 160000 --- a/FreeRTOS/Source +++ b/FreeRTOS/Source @@ -1 +1 @@ -Subproject commit 4d9cd906d3f7c339ee3d6d64a00c416d58a8b003 +Subproject commit c4e99bf09f49fc45c08dd6ebff1071d2069d308a diff --git a/FreeRTOS/Test/CMock/Makefile b/FreeRTOS/Test/CMock/Makefile index 47b8433c2e..943e1ff97f 100644 --- a/FreeRTOS/Test/CMock/Makefile +++ b/FreeRTOS/Test/CMock/Makefile @@ -7,14 +7,14 @@ export CC ?= /usr/local/bin/gcc export LD ?= /usr/local/bin/ld # Add units here when adding a new unit test directory with the same name -UNITS := timers +UNITS := smp +UNITS += timers UNITS += tasks UNITS += list UNITS += queue UNITS += stream_buffer UNITS += message_buffer UNITS += event_groups -UNITS += smp .PHONY: makefile.in diff --git a/FreeRTOS/Test/CMock/coverage.mk b/FreeRTOS/Test/CMock/coverage.mk index 95f750cf0b..d8dc75c7de 100644 --- a/FreeRTOS/Test/CMock/coverage.mk +++ b/FreeRTOS/Test/CMock/coverage.mk @@ -1,12 +1,31 @@ -COVINFO := $(abspath $(SCRATCH_DIR)/..)/$(EXEC_PREFIX).info -COVINFO_INITIAL := $(SCRATCH_DIR)/$(EXEC_PREFIX)_initial.info -LCOV_LIST := $(addsuffix .info,$(addprefix $(SCRATCH_DIR)/,$(SUITE_UT_SRC:.c=))) -PROJ_GCDA_LIST := $(PROJ_SRC_LIST:.c=.gcda) -COV_REPORT_DIR := $(SCRATCH_DIR)/coverage -COVINFO_COMBINE := $(SCRATCH_DIR)/$(EXEC_PREFIX)_combined.info - - -GCOV_OPTS := --unconditional-branches --branch-probabilities +# Determine if we're in a nested test structure by checking for DISCRIMINATOR +ifdef DISCRIMINATOR + # Nested test structure (e.g., smp/granular_lock) + LCOV_LIST := $(addsuffix .info,$(addprefix $(SCRATCH_DIR)/$(EXEC_PREFIX)_,$(DISCRIMINATOR))) + INFO_PATTERN := $(SCRATCH_DIR)/$(EXEC_PREFIX)_%.info + TEST_PATTERN := $(BIN_DIR)/smp_$(PROJECT)_%_utest +else + # Flat test structure + LCOV_LIST := $(addsuffix .info,$(addprefix $(SCRATCH_DIR)/,$(SUITE_UT_SRC:.c=))) + INFO_PATTERN := $(SCRATCH_DIR)/%_utest.info + TEST_PATTERN := $(BIN_DIR)/$(EXEC_PREFIX)_%_utest +endif + +# Debug information for coverage +$(info === Coverage Configuration ===) +$(info DISCRIMINATOR: $(DISCRIMINATOR)) +$(info LCOV_LIST: $(LCOV_LIST)) +$(info INFO_PATTERN: $(INFO_PATTERN)) +$(info TEST_PATTERN: $(TEST_PATTERN)) + +# Common variables +COVINFO := $(abspath $(SCRATCH_DIR)/..)/$(EXEC_PREFIX).info +COVINFO_INITIAL := $(SCRATCH_DIR)/$(EXEC_PREFIX)_initial.info +PROJ_GCDA_LIST := $(PROJ_SRC_LIST:.c=.gcda) +COV_REPORT_DIR := $(SCRATCH_DIR)/coverage +COVINFO_COMBINE := $(SCRATCH_DIR)/$(EXEC_PREFIX)_combined.info + +GCOV_OPTS := --unconditional-branches --branch-probabilities # Cases that run test binaries cannot be run in parallel. .NOTPARALLEL : $(COVINFO) $(LCOV_LIST) $(PROJ_GCDA_LIST) @@ -18,7 +37,6 @@ NO_DELETE : $(MOCK_HDR_LIST) $(MOCK_SRC_LIST) $(MOCK_OBJ_LIST) \ $(SUITE_OBJ_LIST) $(RUNNER_SRC_LIST) $(RUNNER_OBJ_LIST) \ $(COVINFO) $(LCOV_LIST) - # Generate gcov files by default run : gcov @@ -26,7 +44,7 @@ gcov : $(PROJ_GCDA_LIST) clean : rm -rf $(SCRATCH_DIR) - rm -f $(BIN_DIR)/$(PROJECT)_utest_* + rm -f $(BIN_DIR)/*$(PROJECT)* rm -f $(COVINFO) libs : @@ -37,6 +55,8 @@ $(1) endef $(PROJ_GCDA_LIST) : $(EXEC_LIST) + @echo "=== Generating GCDA files ===" + @echo "Executables: $(EXEC_LIST)" rm -f $(PROJ_DIR)/*.gcda mkdir -p $(BIN_DIR) # run each test case @@ -46,43 +66,46 @@ $(PROJ_GCDA_LIST) : $(EXEC_LIST) lcov : $(COVINFO) lcovhtml : $(COVINFO) + @echo "=== Generating HTML coverage report ===" + @echo "Output directory: $(COV_REPORT_DIR)" mkdir -p $(COV_REPORT_DIR) genhtml $(COVINFO) $(LCOV_OPTS) --output-directory $(COV_REPORT_DIR) bin: $(EXEC_LIST) -# Run and append to gcov data files - # Generate callgraph for coverage filtering $(PROJ_DIR)/callgraph.json : $(PROJ_SRC_LIST) + @echo "=== Generating callgraph ===" mkdir -p $(PROJ_DIR) #python3 $(UT_ROOT_DIR)/tools/callgraph.py --out $@ $^ -# Generate baseline inital coverage data from .gcno file +# Generate baseline initial coverage data from .gcno file $(COVINFO_INITIAL) : $(EXEC_LIST) + @echo "=== Generating initial coverage data ===" + @echo "Output file: $@" lcov $(LCOV_OPTS) --capture --initial --directory $(SCRATCH_DIR) -o $@ -# Run the test runner and genrate a filtered gcov.json.gz file -$(SCRATCH_DIR)/%_utest.info : $(BIN_DIR)/$(EXEC_PREFIX)_%_utest \ - $(PROJ_DIR)/callgraph.json +# Add debug information before pattern rules +$(info === Coverage Pattern Debug ===) +$(info Looking for info files: $(LCOV_LIST)) +$(info Info pattern: $(INFO_PATTERN)) +$(info Test pattern: $(TEST_PATTERN)) +$(info Executables: $(EXEC_LIST)) + +# Run the test runner and generate coverage info file +$(INFO_PATTERN) : $(TEST_PATTERN) $(PROJ_DIR)/callgraph.json + @echo "=== Generating coverage info for $@ ===" + @echo "Using test executable: $<" # Remove any existing coverage data rm -f $(PROJ_DIR)/*.gcda # run the testrunner $< + @echo "Capturing coverage data..." lcov $(LCOV_OPTS) --directory $(SCRATCH_DIR) --capture -o $@ - # Gather coverage into a json.gz file - -#gcov $(GCOV_OPTS) $(SCRATCH_DIR)/$*/$(PROJECT).gcda \ -# --json-format --stdout | gzip > $(subst .info,.json.gz,$@) - - # Filter coverage based on tags in unit test file -# $(TOOLS_DIR)/filtercov.py --in $(subst .info,.json.gz,$@) \ -# --map $(PROJ_DIR)/callgraph.json \ -# --test $(PROJ_DIR)/$(PROJECT)_utest_$*.c \ -# --format lcov \ -# --out $@ + + @echo "Coverage summary:" lcov $(LCOV_OPTS) --summary $@ # Remove temporary files @@ -91,9 +114,28 @@ $(SCRATCH_DIR)/%_utest.info : $(BIN_DIR)/$(EXEC_PREFIX)_%_utest \ # Combine lcov from each test bin into one lcov info file for the suite $(COVINFO_COMBINE) : $(LCOV_LIST) + @echo "=== Combining coverage data ===" + @echo "Input files: $(LCOV_LIST)" + @echo "Output file: $@" lcov $(LCOV_OPTS) -o $@ $(foreach cov,$(LCOV_LIST),--add-tracefile $(cov) ) # Add baseline / initial coverage generated by gcc to point out untagged functions $(COVINFO) : $(COVINFO_COMBINE) $(COVINFO_INITIAL) + @echo "=== Generating final coverage report ===" + @echo "Initial coverage: $(COVINFO_INITIAL)" + @echo "Combined coverage: $(COVINFO_COMBINE)" + @echo "Output file: $@" lcov $(LCOV_OPTS) -o $@ --add-tracefile $(COVINFO_INITIAL) --add-tracefile $(COVINFO_COMBINE) +# Debug target for coverage configuration +coverage-debug: + @echo "=== Coverage Debug Information ===" + @echo "DISCRIMINATOR: $(DISCRIMINATOR)" + @echo "LCOV_LIST: $(LCOV_LIST)" + @echo "INFO_PATTERN: $(INFO_PATTERN)" + @echo "TEST_PATTERN: $(TEST_PATTERN)" + @echo "COVINFO: $(COVINFO)" + @echo "COVINFO_INITIAL: $(COVINFO_INITIAL)" + @echo "COVINFO_COMBINE: $(COVINFO_COMBINE)" + @echo "EXEC_LIST: $(EXEC_LIST)" + @echo "PROJ_GCDA_LIST: $(PROJ_GCDA_LIST)" \ No newline at end of file diff --git a/FreeRTOS/Test/CMock/smp/Makefile b/FreeRTOS/Test/CMock/smp/Makefile index 948942e367..937cce63de 100644 --- a/FreeRTOS/Test/CMock/smp/Makefile +++ b/FreeRTOS/Test/CMock/smp/Makefile @@ -9,6 +9,7 @@ SUITES += single_priority_no_timeslice SUITES += single_priority_timeslice SUITES += multiple_priorities_no_timeslice SUITES += multiple_priorities_timeslice +SUITES += granular_lock # SUITS mock dependency source for coverage test SUITES += multiple_priorities_no_timeslice_mock diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/FreeRTOSConfig_1.h b/FreeRTOS/Test/CMock/smp/granular_lock/FreeRTOSConfig_1.h new file mode 100644 index 0000000000..ccce483a51 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/FreeRTOSConfig_1.h @@ -0,0 +1,175 @@ +/* + * 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 0 +#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 0 +#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 0 +#define portSTACK_GROWTH ( 1 ) +#define configUSE_PASSIVE_IDLE_HOOK 0 +#define configUSE_TICKLESS_IDLE 1 +#define configSTACK_DEPTH_TYPE uint32_t + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 0 +#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 0 +#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 */ + +/* =========================== INSTRUMENT THROUGH TRACE MACRO =========================== */ +int xTraceBlockingOnQueueReceive( void * pxQueue ); +#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) do{ if( xTraceBlockingOnQueueReceive( pxQueue ) != 0 ) { return errQUEUE_EMPTY; } } while( 0 ) + +int xTraceUnblockingOnQueueReceive( void * pxQueue ); +#define traceUNBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) do{ if( xTraceUnblockingOnQueueReceive( pxQueue ) != 0 ) { return errQUEUE_EMPTY; } } while( 0 ) + +int xTraceBlockingOnQueueSend( void * pxQueue ); +#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) do{ if( xTraceBlockingOnQueueSend( pxQueue ) != 0 ) { return errQUEUE_FULL; } } while( 0 ) + +int xTraceUnblockingOnQueueSend( void * pxQueue ); +#define traceUNBLOCKING_ON_QUEUE_SEND( pxQueue ) do{ if( xTraceUnblockingOnQueueSend( pxQueue ) != 0 ) { return errQUEUE_FULL; } } while( 0 ) + +int xTraceEventGroupTaskBlocked( void * pxEventGroup ); +#define traceEVENT_GROUP_BLOCK_ON_BITS_WAITING( pxEventGroup, uxBitsToWaitFor ) do{ if( xTraceEventGroupTaskBlocked( pxEventGroup ) != 0 ) { return 0; } } while( 0 ) + +int xTraceEventGroupTaskUnblocked( void * pxEventGroup ); +#define traceEVENT_GROUP_UNBLOCK_ON_BITS_WAITING( pxEventGroup, uxBitsToWaitFor, xMatchFound ) do{ if( xTraceEventGroupTaskUnblocked( pxEventGroup ) != 0 ) { return 0; } } while( 0 ) + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/FreeRTOSConfig_timers.h b/FreeRTOS/Test/CMock/smp/granular_lock/FreeRTOSConfig_timers.h new file mode 100644 index 0000000000..8de5d5c9b2 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/FreeRTOSConfig_timers.h @@ -0,0 +1,175 @@ +/* + * 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 0 + #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 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 0 + #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 */ + + /* =========================== INSTRUMENT THROUGH TRACE MACRO =========================== */ + int xTraceBlockingOnQueueReceive( void * pxQueue ); + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) do{ if( xTraceBlockingOnQueueReceive( pxQueue ) != 0 ) { return errQUEUE_EMPTY; } } while( 0 ) + + int xTraceUnblockingOnQueueReceive( void * pxQueue ); + #define traceUNBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) do{ if( xTraceUnblockingOnQueueReceive( pxQueue ) != 0 ) { return errQUEUE_EMPTY; } } while( 0 ) + + int xTraceBlockingOnQueueSend( void * pxQueue ); + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) do{ if( xTraceBlockingOnQueueSend( pxQueue ) != 0 ) { return errQUEUE_FULL; } } while( 0 ) + + int xTraceUnblockingOnQueueSend( void * pxQueue ); + #define traceUNBLOCKING_ON_QUEUE_SEND( pxQueue ) do{ if( xTraceUnblockingOnQueueSend( pxQueue ) != 0 ) { return errQUEUE_FULL; } } while( 0 ) + + int xTraceEventGroupTaskBlocked( void * pxEventGroup ); + #define traceEVENT_GROUP_BLOCK_ON_BITS_WAITING( pxEventGroup, uxBitsToWaitFor ) do{ if( xTraceEventGroupTaskBlocked( pxEventGroup ) != 0 ) { return 0; } } while( 0 ) + + int xTraceEventGroupTaskUnblocked( void * pxEventGroup ); + #define traceEVENT_GROUP_UNBLOCK_ON_BITS_WAITING( pxEventGroup, uxBitsToWaitFor, xMatchFound ) do{ if( xTraceEventGroupTaskUnblocked( pxEventGroup ) != 0 ) { return 0; } } while( 0 ) + + #endif /* FREERTOS_CONFIG_H */ + \ No newline at end of file diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/Makefile b/FreeRTOS/Test/CMock/smp/granular_lock/Makefile new file mode 100644 index 0000000000..5a3b20bf98 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/Makefile @@ -0,0 +1,394 @@ +# Change according to what your unit test directory is. +$(info === Starting Build Process ===) +$(info Time: $(shell date)) + +include ../../makefile.in + +.PRECIOUS: + +PROJECT := granular_lock +PROJECT_SRC := tasks.c queue.c timers.c event_groups.c stream_buffer.c +PROJECT_SRC_PATHS := $(addprefix $(KERNEL_DIR)/,$(PROJECT_SRC)) + +# Test dependencies that should be excluded from coverage +TEST_DEPS_SRC := list.c +TEST_DEPS_PATHS := $(addprefix $(KERNEL_DIR)/,$(TEST_DEPS_SRC)) + +# Test/CMock/tasks +PROJECT_DIR := $(abspath .) +PROJ_DIR := $(abspath .) + +# Test support files +TEST_SUPPORT_DIR := $(UT_ROOT_DIR)/smp +TEST_SUPPORT_SRC := smp_utest_common + +# List the dependency files you wish to mock +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)/smp/granular_lock/portmacro.h +MOCK_FILES_FP += $(KERNEL_DIR)/include/timers.h + +# List special compilation flags for this module +CFLAGS += -Wno-unused-function + +# List special preprocessing flags for this module +CPPFLAGS += + +# List special linking flags for this module +LDFLAGS += + +# Coverage options +COVERAGE_OPTS := -fprofile-arcs -ftest-coverage -fprofile-generate + +# Directory definitions +PARENT_DIR := $(notdir $(realpath $(dir $(PROJECT_DIR)))) +SCRATCH_DIR := $(GENERATED_DIR)/$(PARENT_DIR)/$(PROJECT) + +# Mock file definitions +MOCK_FILES := $(notdir $(MOCK_FILES_FP)) +MOCK_SRC_LIST := $(foreach disc,$(DISCRIMINATOR),$(addprefix $(SCRATCH_DIR)/$(disc)/mocks/mock_,$(MOCK_FILES:.h=.c))) + +# Preprocessed file definitions +CPP_FILES := $(foreach disc,$(DISCRIMINATOR),$(addprefix $(SCRATCH_DIR)/$(disc)/cpp/,$(notdir $(MOCK_FILES_FP)))) +DEP_FILES := $(foreach disc,$(DISCRIMINATOR),$(addsuffix .d,$(addprefix $(SCRATCH_DIR)/$(disc)/cpp/,$(notdir $(MOCK_FILES_FP))))) + +# Test file definitions +PROJ_SRC_LIST := $(sort $(wildcard $(PROJECT)_*_utest.c)) +SUITE_UT_SRC := $(subst $(PROJECT)_,,$(PROJ_SRC_LIST)) +DISCRIMINATOR := $(subst _utest,,$(subst .c,,$(subst $(PROJECT)_,,$(PROJ_SRC_LIST)))) + +# Directory paths +MOCK_DIRS := $(foreach disc,$(DISCRIMINATOR),$(SCRATCH_DIR)/$(disc)/mocks) +CPP_DIRS := $(foreach disc,$(DISCRIMINATOR),$(SCRATCH_DIR)/$(disc)/cpp) +INCLUDE_DIRS := $(foreach disc,$(DISCRIMINATOR),$(SCRATCH_DIR)/$(disc)/include) +CONFIG_DIRS := $(foreach disc,$(DISCRIMINATOR),$(SCRATCH_DIR)/$(disc)) + +# Debug Information +$(info === Project Configuration ===) +$(info PROJECT = $(PROJECT)) +$(info PROJECT_DIR = $(PROJECT_DIR)) +$(info KERNEL_DIR = $(KERNEL_DIR)) +$(info === Source Files ===) +$(info PROJECT_SRC = $(PROJECT_SRC)) +$(info PROJECT_SRC_PATHS = $(PROJECT_SRC_PATHS)) +$(info === Test Dependencies ===) +$(info TEST_DEPS_SRC = $(TEST_DEPS_SRC)) +$(info TEST_DEPS_PATHS = $(TEST_DEPS_PATHS)) +$(info === Test Configuration ===) +$(info DISCRIMINATOR = $(DISCRIMINATOR)) +$(info SUITE_UT_SRC = $(SUITE_UT_SRC)) +$(info MOCK_FILES_FP = $(MOCK_FILES_FP)) + +# Handle empty mock files +ifeq ($(MOCK_FILES_FP),) + $(info No mock files specified) + $(shell mkdir -p $(MOCK_DIRS)) + $(shell for n in $(MOCK_DIRS) ; do touch -a $(n)/mock_dummy.c) +endif + +# Executable definitions +EXEC_LIST := $(addprefix $(BIN_DIR)/smp_,$(patsubst %.c,%,$(PROJ_SRC_LIST))) + +$(info === Build Targets ===) +$(info EXEC_LIST = $(EXEC_LIST)) +$(info SCRATCH_DIR = $(SCRATCH_DIR)) + +.PHONY: all Makefile directories + +.SECONDARY: +all : directories $(EXEC_LIST) + +$(info === Defining Build Rules ===) + +# Add rule for FreeRTOSConfig.h +define config-file-rule +$(info Defining config-file-rule for $(1)) +$(SCRATCH_DIR)/$(1)/include/FreeRTOSConfig.h: $(PROJECT_DIR)/FreeRTOSConfig_$(1).h | directories + @echo "=== Setting up FreeRTOSConfig.h for discriminator $(1) ===" + cp $$< $$@ +endef + +# Generate rules for each discriminator and executable +define exec-rule +$(info Defining exec-rule for $(1)) +$(BIN_DIR)/smp_$(PROJECT)_$(1)_utest: $(addprefix $(SCRATCH_DIR)/$(1)/mocks/mock_,$(MOCK_FILES:.h=.o)) \ + $(SCRATCH_DIR)/$(1)/test_runner.o \ + $(addprefix $(SCRATCH_DIR)/$(1)/,$(PROJECT_SRC:.c=.o)) \ + $(addprefix $(SCRATCH_DIR)/$(1)/,$(TEST_DEPS_SRC:.c=.o)) \ + $(SCRATCH_DIR)/$(1)/$(notdir $(TEST_SUPPORT_SRC)).o \ + $(SCRATCH_DIR)/$(1)/$(PROJECT)_utest.o | libs directories + @echo "=== Building executable for discriminator $(1) ===" + @echo "Building $$@ with:" + @echo " Mocks: $$(filter %/mocks/mock_%,$$(^))" + @echo " Runner: $$(filter %/test_runner.o,$$(^))" + @echo " Sources: $$(filter $$(addprefix $(SCRATCH_DIR)/$(1)/,$$(PROJECT_SRC:.c=.o)),$$(^))" + @echo " Test Dependencies: $$(filter $$(addprefix $(SCRATCH_DIR)/$(1)/,$$(TEST_DEPS_SRC:.c=.o)),$$(^))" + @echo " Test Support: $$(filter %/$(notdir $(TEST_SUPPORT_SRC)).o,$$(^))" + @echo " Test: $$(filter %/$(PROJECT)_utest.o,$$(^))" + $$(CC) $$^ $$(LDFLAGS) -o $$@ +endef + +# Generate rules for each source file and discriminator +define src-rule +$(info Defining src-rule for $(1) - $(2)) +$(SCRATCH_DIR)/$(1)/$(2:.c=.i): $(KERNEL_DIR)/$(2) $(SCRATCH_DIR)/$(1)/include/FreeRTOSConfig.h | directories + @echo "=== Preprocessing $(2) for discriminator $(1) ===" + $$(eval INCLUDE = -I$(SCRATCH_DIR)/$(1)/include) + $$(eval INCLUDE += -I$(SCRATCH_DIR)/$(1)/mocks) + $$(eval INCLUDE += -I$(KERNEL_DIR)/include) + $$(eval INCLUDE += -I$(PROJECT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/config) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/smp/granular_lock) + $$(eval INCLUDE += -I$(TEST_SUPPORT_DIR)) + $$(CC) -E $$< $$(INCLUDE) $$(CPPFLAGS) \ + -include stdint.h \ + -include FreeRTOSConfig.h \ + -include FreeRTOS.h \ + -include fake_port.h \ + -include portmacro.h \ + -include projdefs.h \ + -o $$@ + +$(SCRATCH_DIR)/$(1)/$(2:.c=.o): $(SCRATCH_DIR)/$(1)/$(2:.c=.i) + @echo "=== Compiling $(2) for discriminator $(1) ===" + $$(CC) -c $$< $$(CFLAGS) $$(COVERAGE_OPTS) -o $$@ +endef + +# Generate rules for test dependencies (without coverage) +define test-dep-rule +$(info Defining test-dep-rule for $(1) - $(2)) +$(SCRATCH_DIR)/$(1)/$(2:.c=.i): $(KERNEL_DIR)/$(2) $(SCRATCH_DIR)/$(1)/include/FreeRTOSConfig.h | directories + @echo "=== Preprocessing test dependency $(2) for discriminator $(1) ===" + $$(eval INCLUDE = -I$(SCRATCH_DIR)/$(1)/include) + $$(eval INCLUDE += -I$(SCRATCH_DIR)/$(1)/mocks) + $$(eval INCLUDE += -I$(KERNEL_DIR)/include) + $$(eval INCLUDE += -I$(PROJECT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/config) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/smp/granular_lock) + $$(eval INCLUDE += -I$(TEST_SUPPORT_DIR)) + $$(CC) -E $$< $$(INCLUDE) $$(CPPFLAGS) \ + -include stdint.h \ + -include FreeRTOSConfig.h \ + -include FreeRTOS.h \ + -include fake_port.h \ + -include portmacro.h \ + -include projdefs.h \ + -o $$@ + +$(SCRATCH_DIR)/$(1)/$(2:.c=.o): $(SCRATCH_DIR)/$(1)/$(2:.c=.i) + @echo "=== Compiling test dependency $(2) for discriminator $(1) ===" + $$(CC) -c $$< $$(CFLAGS) -o $$@ +endef + +# Add rule for test support files +define test-support-rule +$(info Defining test-support-rule for $(1) - $(notdir $(2))) +$(SCRATCH_DIR)/$(1)/$(2).o: $(TEST_SUPPORT_DIR)/$(2).c $(addprefix $(SCRATCH_DIR)/$(1)/mocks/mock_,$(MOCK_FILES:.h=.o)) | directories + @echo "=== Compiling test support file $(2) for discriminator $(1) ===" + $$(eval INCLUDE = -I$(SCRATCH_DIR)/$(1)/include) + $$(eval INCLUDE += -I$(SCRATCH_DIR)/$(1)/mocks) + $$(eval INCLUDE += -I$(KERNEL_DIR)/include) + $$(eval INCLUDE += -I$(TEST_SUPPORT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/config) + $$(eval INCLUDE += -I$(PROJECT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/smp/granular_lock) + $$(CC) -c $$< $$(INCLUDE) $$(CPPFLAGS) $$(CFLAGS) -o $$@ +endef + +# Test runner compilation +define runner-rule +$(info Defining runner-rule for $(1)) +$(SCRATCH_DIR)/$(1)/test_runner.o: $(SCRATCH_DIR)/$(1)/test_runner.c + @echo "=== Compiling test runner for discriminator $(1) ===" + $$(eval INCLUDE = -I$(SCRATCH_DIR)/$(1)/include) + $$(eval INCLUDE += -I$(SCRATCH_DIR)/$(1)/mocks) + $$(eval INCLUDE += -I$(KERNEL_DIR)/include) + $$(eval INCLUDE += -I$(PROJECT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/config) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/smp/granular_lock) + $$(eval INCLUDE += -I$(TEST_SUPPORT_DIR)) + $$(eval INCLUDE += -I$(UNITY_SRC_DIR)) + $$(CC) -c $$< $$(INCLUDE) $$(CPPFLAGS) $$(CFLAGS) -o $$@ + +$(SCRATCH_DIR)/$(1)/test_runner.c: $(PROJECT_DIR)/$(PROJECT)_$(1)_utest.c Makefile | directories + @echo "=== Generating test runner for discriminator $(1) ===" + ruby $(UNITY_BIN_DIR)/generate_test_runner.rb "--use_param_tests=1" \ + $(PROJECT)_$(1)_utest.c $(PROJECT_DIR)/$(PROJECT).yml $$@ +endef + +# Mock generation rules for each discriminator +define mock-gen-rule +$(info Defining mock-gen-rule for $(1)) +$(SCRATCH_DIR)/$(1)/mocks/mock_%.c: $(SCRATCH_DIR)/$(1)/cpp/%.h $(PROJECT_DIR)/$(PROJECT).yml | directories + @echo "=== Generating mock for $$(notdir $$<) ===" + @echo "Source header: $$<" + @echo "Target mock: $$@" + cd $(SCRATCH_DIR)/$(1) && \ + CMOCK_DIR=$(CMOCK_DIR) \ + UNITY_DIR=$(UNITY_DIR) \ + ruby $(CMOCK_EXEC_DIR)/cmock.rb \ + -o$(PROJECT_DIR)/$(PROJECT).yml \ + --includes=stdint.h,FreeRTOS.h \ + cpp/$$(notdir $$<) +endef + +# Create explicit rules for header files +define header-rule +$(info Defining header-rule for $(1) - $(notdir $(2))) +$(SCRATCH_DIR)/$(1)/cpp/$(notdir $(2)): $(2) | directories + @echo "=== Copying header file for discriminator $(1) ===" + @echo "Source: $(2)" + @echo "Target: $$@" + cp $$< $$@ +endef + +$(info === Applying Rules ===) +$(info Processing discriminators: $(DISCRIMINATOR)) + +# First, apply config file rules +$(foreach disc,$(DISCRIMINATOR),$(eval $(call config-file-rule,$(disc)))) +$(info Config files created) + +# Copy header files +$(foreach disc,$(DISCRIMINATOR),\ + $(foreach mock_fp,$(MOCK_FILES_FP),\ + $(eval $(call header-rule,$(disc),$(mock_fp))))) +$(info Header files copied) + +# Apply mock generation rules +$(foreach disc,$(DISCRIMINATOR),$(eval $(call mock-gen-rule,$(disc)))) +$(info Mock generation rules applied) + +# Mock object compilation +define mock-rule +$(info Defining mock-rule for $(1)) +$(SCRATCH_DIR)/$(1)/mocks/mock_%.o: $(SCRATCH_DIR)/$(1)/mocks/mock_%.c + @echo "=== Compiling mock for discriminator $(1): $$(notdir $$<) ===" + $$(eval INCLUDE = -I$(SCRATCH_DIR)/$(1)/include) + $$(eval INCLUDE += -I$(SCRATCH_DIR)/$(1)/mocks) + $$(eval INCLUDE += -I$(KERNEL_DIR)/include) + $$(eval INCLUDE += -I$(PROJECT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/smp/granular_lock) + $$(CC) -c $$< $$(INCLUDE) $$(CPPFLAGS) $$(CFLAGS) -fPIC \ + -include stdint.h \ + -include FreeRTOS.h \ + -DUNITY_EXCLUDE_MATH_H \ + -DUNITY_EXCLUDE_STDINT_H \ + -DUNITY_OUTPUT_CHAR -o $$@ +endef + +$(foreach disc,$(DISCRIMINATOR),$(eval $(call mock-rule,$(disc)))) +$(info Mock compilation rules applied) + +# Then apply source rules +$(foreach disc,$(DISCRIMINATOR),$(foreach src,$(PROJECT_SRC),$(eval $(call src-rule,$(disc),$(src))))) +$(info Source rules applied) + +# Apply test dependency rules +$(foreach disc,$(DISCRIMINATOR),$(foreach src,$(TEST_DEPS_SRC),$(eval $(call test-dep-rule,$(disc),$(src))))) +$(info Test dependency rules applied) + +# Apply test support rules +$(foreach disc,$(DISCRIMINATOR),\ + $(eval $(call test-support-rule,$(disc),$(TEST_SUPPORT_SRC)))) +$(info Test support rules applied) + +# Then apply test runner rules +$(foreach disc,$(DISCRIMINATOR),$(eval $(call runner-rule,$(disc)))) +$(info Test runner rules applied) + +# Test file compilation +define test-rule +$(info Defining test-rule for $(1)) +$(SCRATCH_DIR)/$(1)/$(PROJECT)_utest.o: $(PROJECT_DIR)/$(PROJECT)_$(1)_utest.c \ + $(addprefix $(SCRATCH_DIR)/$(1)/mocks/mock_,$(MOCK_FILES:.h=.o)) \ + $(SCRATCH_DIR)/$(1)/$(notdir $(TEST_SUPPORT_SRC)).o \ + $(SCRATCH_DIR)/$(1)/test_runner.o \ + $(UT_ROOT_DIR)/smp/global_vars.h | directories + @echo "=== Compiling test file for discriminator $(1) ===" + $$(eval INCLUDE = -I$(SCRATCH_DIR)/$(1)/include) + $$(eval INCLUDE += -I$(SCRATCH_DIR)/$(1)/mocks) + $$(eval INCLUDE += -I$(KERNEL_DIR)/include) + $$(eval INCLUDE += -I$(PROJECT_DIR)) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/config) + $$(eval INCLUDE += -I$(UT_ROOT_DIR)/smp/granular_lock) + $$(eval INCLUDE += -I$(TEST_SUPPORT_DIR)) + $$(eval INCLUDE += -I$(UNITY_SRC_DIR)) + $$(CC) -c $$< $$(INCLUDE) $$(CPPFLAGS) $$(CFLAGS) -o $$@ +endef + +$(foreach disc,$(DISCRIMINATOR),$(eval $(call test-rule,$(disc)))) +$(info Test compilation rules applied) + +# Finally apply exec rules +$(foreach disc,$(DISCRIMINATOR),$(eval $(call exec-rule,$(disc)))) +$(info Exec rules applied) + +# Directory creation +directories: + @echo "=== Creating build directories ===" + -mkdir -p $(SCRATCH_DIR) + -mkdir -p $(CONFIG_DIRS) + -mkdir -p $(MOCK_DIRS) + -mkdir -p $(CPP_DIRS) + -mkdir -p $(INCLUDE_DIRS) + -mkdir -p $(BIN_DIR) + -mkdir -p $(LIB_DIR) + @echo "Directories created:" + @echo " SCRATCH_DIR: $(SCRATCH_DIR)" + @echo " CONFIG_DIRS: $(CONFIG_DIRS)" + @echo " MOCK_DIRS: $(MOCK_DIRS)" + @echo " CPP_DIRS: $(CPP_DIRS)" + @echo " INCLUDE_DIRS: $(INCLUDE_DIRS)" + @echo " BIN_DIR: $(BIN_DIR)" + @echo " LIB_DIR: $(LIB_DIR)" + +# Verification targets +.PHONY: show-build show-sources show-paths + +show-build: + @echo "=== Build Configuration ===" + @echo "Project: $(PROJECT)" + @echo "Source Files:" + @for src in $(PROJECT_SRC); do echo " $$src"; done + @echo "Test Dependencies:" + @for dep in $(TEST_DEPS_SRC); do echo " $$dep"; done + @echo "Test Files:" + @for test in $(SUITE_UT_SRC); do echo " $$test"; done + @echo "Final Executables:" + @for exec in $(EXEC_LIST); do echo " $$exec"; done + +show-sources: + @echo "=== Source Files to Process ===" + @for src in $(PROJECT_SRC); do \ + echo "Source: $(KERNEL_DIR)/$$src"; \ + for disc in $(DISCRIMINATOR); do \ + echo " Disc: $$disc - Preprocessed: $(SCRATCH_DIR)/$$disc/$${src%.c}.i"; \ + echo " Disc: $$disc - Object: $(SCRATCH_DIR)/$$disc/$${src%.c}.o"; \ + done; \ + done + @echo "=== Test Dependencies to Process ===" + @for dep in $(TEST_DEPS_SRC); do \ + echo "Dependency: $(KERNEL_DIR)/$$dep"; \ + for disc in $(DISCRIMINATOR); do \ + echo " Disc: $$disc - Preprocessed: $(SCRATCH_DIR)/$$disc/$${dep%.c}.i"; \ + echo " Disc: $$disc - Object: $(SCRATCH_DIR)/$$disc/$${dep%.c}.o"; \ + done; \ + done + +show-paths: + @echo "=== Directory Paths ===" + @echo "KERNEL_DIR: $(KERNEL_DIR)" + @echo "PROJECT_DIR: $(PROJECT_DIR)" + @echo "SCRATCH_DIR: $(SCRATCH_DIR)" + @echo "MOCK_DIRS: $(MOCK_DIRS)" + @echo "CPP_DIRS: $(CPP_DIRS)" + @echo "INCLUDE_DIRS: $(INCLUDE_DIRS)" + +$(info === Build Process Setup Complete ===) +$(info Time: $(shell date)) + +EXEC_PREFIX := smp_$(PROJECT) +$(info EXEC_PREFIX: $(EXEC_PREFIX)) + +include ../../coverage.mk \ No newline at end of file diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock.yml b/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock.yml new file mode 100644 index 0000000000..e149b08f25 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock.yml @@ -0,0 +1,32 @@ +:cmock: + :mock_prefix: mock_ + :when_no_prototypes: :warn + :when_ptr: :compare_ptr + :treat_externs: :include + :enforce_strict_ordering: TRUE + :plugins: + - :ignore + - :ignore_arg + - :expect_any_args + - :callback + - :return_thru_ptr + :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" + :treat_externs: :exclude # Now the extern-ed functions will be mocked. + :weak: __attribute__((weak)) + :verbosity: 3 + :attributes: + - PRIVILEGED_FUNCTION + :strippables: + - PRIVILEGED_FUNCTION + - portDONT_DISCARD + :treat_externs: :include diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock_1_utest.c b/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock_1_utest.c new file mode 100644 index 0000000000..9e3287fc83 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock_1_utest.c @@ -0,0 +1,528 @@ +/* + * 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 granular_lock_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" +#include "semphr.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_portmacro.h" + +/* =========================== EXTERN VARIABLES =========================== */ +extern portSPINLOCK_TYPE xTaskSpinlock; +extern portSPINLOCK_TYPE xISRSpinlock; + +/* =========================== GLOBAL VARIABLES =========================== */ + +static TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; +uint32_t xPortCriticalNestingCount[ configNUMBER_OF_CORES ] = { 0U }; + +static int xQueueTestMode = 0; + +static BaseType_t xCoreYields[ configNUMBER_OF_CORES ] = { 0 }; + +static UBaseType_t xInterruptMaskCount[ configNUMBER_OF_CORES ] = { 0U }; +static BaseType_t xInterruptDisableStatus[ configNUMBER_OF_CORES ] = { 0U }; + +/* ============================ Callback Functions ============================ */ +static void vFakePortInitSpinlock_callback( portSPINLOCK_TYPE *pxSpinlock, int cmock_num_calls ) +{ + TEST_ASSERT_NOT_EQUAL( NULL, pxSpinlock ); + + pxSpinlock->uxLockCount = 0; + pxSpinlock->xOwnerCore = -1; +} + +static void vYieldCores( void ) +{ + BaseType_t i; + BaseType_t xPreviousCoreId = portGET_CORE_ID(); + + if( ( xTaskSpinlock.uxLockCount == 0U ) && ( xISRSpinlock.uxLockCount == 0U ) ) + { + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( ( xCoreYields[ i ] == pdTRUE ) && + ( xInterruptMaskCount[ i ] == 0 ) && + ( xInterruptDisableStatus[ i ] == pdFALSE ) ) + { + vSetCurrentCore( i ); + xCoreYields[ i ] = pdFALSE; + vTaskSwitchContext( i ); + } + } + + vSetCurrentCore( xPreviousCoreId ); + } +} + +static void vFakePortReleaseSpinlock_callback( BaseType_t xCoreID, portSPINLOCK_TYPE *pxSpinlock, int cmock_num_calls ) +{ + TEST_ASSERT_NOT_EQUAL( NULL, pxSpinlock ); + TEST_ASSERT_NOT_EQUAL( -1, pxSpinlock->xOwnerCore ); + TEST_ASSERT_NOT_EQUAL( 0, pxSpinlock->uxLockCount ); + TEST_ASSERT_EQUAL( xCoreID, pxSpinlock->xOwnerCore ); + + pxSpinlock->uxLockCount = pxSpinlock->uxLockCount - 1U; + if( pxSpinlock->uxLockCount == 0U ) + { + pxSpinlock->xOwnerCore = -1; + } + + /* Check if and pending core yield. */ + vYieldCores(); +} + +static void vFakePortGetSpinlock_callback( BaseType_t xCoreID, portSPINLOCK_TYPE *pxSpinlock, int cmock_num_calls ) +{ + TEST_ASSERT_NOT_EQUAL( NULL, pxSpinlock ); + + if( pxSpinlock->uxLockCount == 0 ) + { + // TEST_ASSERT_EQUAL( -1, pxSpinlock->xOwnerCore ); + pxSpinlock->uxLockCount = pxSpinlock->uxLockCount + 1U; + pxSpinlock->xOwnerCore = xCoreID; + } + else + { + TEST_ASSERT_EQUAL( xCoreID, pxSpinlock->xOwnerCore ); + pxSpinlock->uxLockCount = pxSpinlock->uxLockCount + 1U; + } +} + +static void vFakePortYieldCore_callback( int xCoreID, + int cmock_num_calls ) +{ + BaseType_t xCoreInCritical = pdFALSE; + BaseType_t xPreviousCoreId; + + /* Check if the lock is acquired by any core. */ + if( ( xTaskSpinlock.uxLockCount != 0U ) || ( xISRSpinlock.uxLockCount != 0U ) ) + { + xCoreInCritical = pdTRUE; + } + + if( xCoreInCritical == pdTRUE ) + { + /* If a task is in the critical section, pend the core yield until the + * spinlock is released. */ + xCoreYields[ xCoreID ] = pdTRUE; + } + else + { + /* No task is in the critical section. We can yield this core. */ + xPreviousCoreId = portGET_CORE_ID(); + vSetCurrentCore( xCoreID ); + vTaskSwitchContext( xCoreID ); + vSetCurrentCore( xPreviousCoreId ); + } +} + +static UBaseType_t ulFakePortSetInterruptMaskFromISR_callback( int cmock_num_calls ) +{ + ( void )cmock_num_calls; + xInterruptMaskCount[ portGET_CORE_ID() ]++; + return xInterruptMaskCount[ portGET_CORE_ID() ]; +} + +static void vFakePortClearInterruptMaskFromISR_callback( UBaseType_t uxNewMaskValue, int cmock_num_calls ) +{ + ( void )uxNewMaskValue; + ( void )cmock_num_calls; + TEST_ASSERT_EQUAL( uxNewMaskValue, xInterruptMaskCount[ portGET_CORE_ID() ] ); + TEST_ASSERT_NOT_EQUAL( 0, xInterruptMaskCount[ portGET_CORE_ID() ] ); + xInterruptMaskCount[ portGET_CORE_ID() ]--; + + /* Check if and pending core yield. */ + vYieldCores(); +} + +static UBaseType_t ulFakePortSetInterruptMask_callback( int cmock_num_calls ) +{ + ( void )cmock_num_calls; + xInterruptMaskCount[ portGET_CORE_ID() ]++; + return xInterruptMaskCount[ portGET_CORE_ID() ]; +} + +static void vFakePortClearInterruptMask_callback( UBaseType_t uxNewMaskValue, int cmock_num_calls ) +{ + ( void )uxNewMaskValue; + ( void )cmock_num_calls; + TEST_ASSERT_EQUAL( uxNewMaskValue, xInterruptMaskCount[ portGET_CORE_ID() ] ); + TEST_ASSERT_NOT_EQUAL( 0, xInterruptMaskCount[ portGET_CORE_ID() ] ); + xInterruptMaskCount[ portGET_CORE_ID() ]--; + + /* Check if and pending core yield. */ + vYieldCores(); +} + +static uint32_t vFakePortDisableInterrupts_callback( int cmock_num_calls ) +{ + xInterruptDisableStatus[ portGET_CORE_ID() ] = pdTRUE; + return 0; +} + +static void vFakePortEnableInterrupts_callback( int cmock_num_calls ) +{ + xInterruptDisableStatus[ portGET_CORE_ID() ] = pdFALSE; + + /* Check if and pending core yield. */ + vYieldCores(); +} + +/* ============================ Trace Functions ============================ */ + +int xTraceBlockingOnQueueReceive( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 0 ) + { + /* After the queue lock is acquired but before the task state is changed, task B + * running on core 1 delete task A. Trace macro is used to simulate asynchronous + * behavior. */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 1 ) + { + /* After the queue lock is acquired but before the task state is changed, task B + * running on core 1 delete task A. Trace macro is used to simulate asynchronous + * behavior. */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 2 ) + { + static int xTaskCallNumbers = 0; + + if( xTaskCallNumbers == 0 ) + { + /* After the queue lock is acquired but before the task state is changed, task B + * running on core 1 delete task A. Trace macro is used to simulate asynchronous + * behavior. */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 0; + } + xTaskCallNumbers++; + } + else if( xQueueTestMode == 3 || xQueueTestMode == 4 || + xQueueTestMode == 5 || xQueueTestMode == 6 || + xQueueTestMode == 7 || xQueueTestMode == 8 || + xQueueTestMode == 9 || xQueueTestMode == 10 ) + { + /* For other test modes, don't use this trace point */ + xReturn = 0; + } + + return xReturn; +} + +int xTraceBlockingOnQueueSend( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 3 ) + { + /* xQueueSend vs vTaskDelete */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 4 ) + { + /* xQueueSend vs vTaskSuspend */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 9 ) + { + /* xSemaphoreGive vs vTaskDelete */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 10 ) + { + /* xSemaphoreGive vs vTaskSuspend */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +int xTraceUnblockingOnQueueReceive( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 0 ) + { + /* xQueueReceive vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 1 ) + { + /* xQueueReceive vs vTaskSuspend - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 2 ) + { + static int xTaskCallNumbers = 0; + if( xTaskCallNumbers == 0 ) + { + /* Keep looping in the xQueueReceive function. */ + vSetCurrentCore( 1 ); + vTaskResume( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 1; + } + xTaskCallNumbers++; + } + else if( xQueueTestMode == 7 ) + { + /* xSemaphoreTake vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 8 ) + { + /* xSemaphoreTake vs vTaskSuspend - return early */ + xReturn = 1; + } + else + { + /* Don't return early for other test modes */ + xReturn = 0; + } + + return xReturn; +} + +int xTraceUnblockingOnQueueSend( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 3 ) + { + /* xQueueSend vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 4 ) + { + /* xQueueSend vs vTaskSuspend - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 9 ) + { + /* xSemaphoreGive vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 10 ) + { + /* xSemaphoreGive vs vTaskSuspend - return early */ + xReturn = 1; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +int xTraceEventGroupTaskBlocked( void * pxEventGroup ) +{ + int xReturn; + + ( void ) pxEventGroup; + + if( xQueueTestMode == 5 ) + { + /* xEventGroupWaitBits vs vTaskDelete */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 6 ) + { + /* xEventGroupWaitBits vs vTaskSuspend */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +int xTraceEventGroupTaskUnblocked( void * pxEventGroup ) +{ + int xReturn; + + ( void ) pxEventGroup; + + if( xQueueTestMode == 5 ) + { + /* xEventGroupWaitBits vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 6 ) + { + /* xEventGroupWaitBits vs vTaskSuspend - return early */ + xReturn = 1; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +/* ============================ Unity Fixtures ============================ */ + +/*! called before each testcase */ +void setUp( void ) +{ + /* Use the common setup for the testing. */ + commonSetUp(); + /* Specify the granular lock specific implementation. */ + vFakePortInitSpinlock_Stub( vFakePortInitSpinlock_callback ); + vFakePortReleaseSpinlock_Stub( vFakePortReleaseSpinlock_callback ); + vFakePortGetSpinlock_Stub( vFakePortGetSpinlock_callback ); + vFakePortYieldCore_Stub( vFakePortYieldCore_callback ); + + /* Interrupt masks. */ + memset( xInterruptMaskCount, 0, sizeof( UBaseType_t ) * configNUMBER_OF_CORES ); + ulFakePortSetInterruptMaskFromISR_StopIgnore(); + ulFakePortSetInterruptMaskFromISR_Stub( ulFakePortSetInterruptMaskFromISR_callback ); + vFakePortClearInterruptMaskFromISR_StopIgnore(); + vFakePortClearInterruptMaskFromISR_Stub( vFakePortClearInterruptMaskFromISR_callback ); + + ulFakePortSetInterruptMask_StopIgnore(); + ulFakePortSetInterruptMask_Stub( ulFakePortSetInterruptMask_callback ); + vFakePortClearInterruptMask_StopIgnore(); + vFakePortClearInterruptMask_Stub( vFakePortClearInterruptMask_callback ); + + memset( xInterruptDisableStatus, 0, sizeof( BaseType_t ) * configNUMBER_OF_CORES ); + vFakePortDisableInterrupts_StopIgnore(); + vFakePortDisableInterrupts_Stub( vFakePortDisableInterrupts_callback ); + vFakePortEnableInterrupts_StopIgnore(); + vFakePortEnableInterrupts_Stub( vFakePortEnableInterrupts_callback ); +} + +/*! 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 ============================== */ + +void test_granular_locks_smoke(void) +{ + 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 ); + } +} diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock_timers_utest.c b/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock_timers_utest.c new file mode 100644 index 0000000000..c9691172c1 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/granular_lock_timers_utest.c @@ -0,0 +1,530 @@ +/* + * 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 granular_lock_timers_utest.c */ + +/* C runtime includes. */ +#include +#include +#include +#include + +/* Task includes */ +#include "FreeRTOS.h" +#include "FreeRTOSConfig.h" +#include "event_groups.h" +#include "queue.h" +#include "semphr.h" + +/* Test includes. */ +#include "unity.h" +#include "unity_memory.h" +#include "../global_vars.h" +#include "../smp_utest_common.h" + +/* Mock includes. */ +#include "mock_fake_assert.h" +#include "mock_fake_port.h" +#include "mock_portmacro.h" + +/* =========================== EXTERN VARIABLES =========================== */ +extern portSPINLOCK_TYPE xTaskSpinlock; +extern portSPINLOCK_TYPE xISRSpinlock; + +/* =========================== GLOBAL VARIABLES =========================== */ + +static TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ] = { NULL }; +uint32_t xPortCriticalNestingCount[ configNUMBER_OF_CORES ] = { 0U }; + +static int xQueueTestMode = 0; + +static BaseType_t xCoreYields[ configNUMBER_OF_CORES ] = { 0 }; + +static UBaseType_t xInterruptMaskCount[ configNUMBER_OF_CORES ] = { 0U }; +static BaseType_t xInterruptDisableStatus[ configNUMBER_OF_CORES ] = { 0U }; + +/* ============================ Callback Functions ============================ */ +static void vFakePortInitSpinlock_callback( portSPINLOCK_TYPE *pxSpinlock, int cmock_num_calls ) +{ + TEST_ASSERT_NOT_EQUAL( NULL, pxSpinlock ); + + pxSpinlock->uxLockCount = 0; + pxSpinlock->xOwnerCore = -1; +} + +static void vYieldCores( void ) +{ + BaseType_t i; + BaseType_t xPreviousCoreId = portGET_CORE_ID(); + + if( ( xTaskSpinlock.uxLockCount == 0U ) && ( xISRSpinlock.uxLockCount == 0U ) ) + { + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( ( xCoreYields[ i ] == pdTRUE ) && + ( xInterruptMaskCount[ i ] == 0 ) && + ( xInterruptDisableStatus[ i ] == pdFALSE ) ) + { + vSetCurrentCore( i ); + xCoreYields[ i ] = pdFALSE; + vTaskSwitchContext( i ); + } + } + + vSetCurrentCore( xPreviousCoreId ); + } +} + +static void vFakePortReleaseSpinlock_callback( BaseType_t xCoreID, portSPINLOCK_TYPE *pxSpinlock, int cmock_num_calls ) +{ + TEST_ASSERT_NOT_EQUAL( NULL, pxSpinlock ); + TEST_ASSERT_NOT_EQUAL( -1, pxSpinlock->xOwnerCore ); + TEST_ASSERT_NOT_EQUAL( 0, pxSpinlock->uxLockCount ); + TEST_ASSERT_EQUAL( xCoreID, pxSpinlock->xOwnerCore ); + + pxSpinlock->uxLockCount = pxSpinlock->uxLockCount - 1U; + if( pxSpinlock->uxLockCount == 0U ) + { + pxSpinlock->xOwnerCore = -1; + } + + /* Check if and pending core yield. */ + vYieldCores(); +} + +static void vFakePortGetSpinlock_callback( BaseType_t xCoreID, portSPINLOCK_TYPE *pxSpinlock, int cmock_num_calls ) +{ + TEST_ASSERT_NOT_EQUAL( NULL, pxSpinlock ); + + if( pxSpinlock->uxLockCount == 0 ) + { + // TEST_ASSERT_EQUAL( -1, pxSpinlock->xOwnerCore ); + pxSpinlock->uxLockCount = pxSpinlock->uxLockCount + 1U; + pxSpinlock->xOwnerCore = xCoreID; + } + else + { + TEST_ASSERT_EQUAL( xCoreID, pxSpinlock->xOwnerCore ); + pxSpinlock->uxLockCount = pxSpinlock->uxLockCount + 1U; + } +} + +static void vFakePortYieldCore_callback( int xCoreID, + int cmock_num_calls ) +{ + BaseType_t xCoreInCritical = pdFALSE; + BaseType_t xPreviousCoreId; + + /* Check if the lock is acquired by any core. */ + if( ( xTaskSpinlock.uxLockCount != 0U ) || ( xISRSpinlock.uxLockCount != 0U ) ) + { + xCoreInCritical = pdTRUE; + } + + if( xCoreInCritical == pdTRUE ) + { + /* If a task is in the critical section, pend the core yield until the + * spinlock is released. */ + xCoreYields[ xCoreID ] = pdTRUE; + } + else + { + /* No task is in the critical section. We can yield this core. */ + xPreviousCoreId = portGET_CORE_ID(); + vSetCurrentCore( xCoreID ); + vTaskSwitchContext( xCoreID ); + vSetCurrentCore( xPreviousCoreId ); + } +} + +static UBaseType_t ulFakePortSetInterruptMaskFromISR_callback( int cmock_num_calls ) +{ + ( void )cmock_num_calls; + xInterruptMaskCount[ portGET_CORE_ID() ]++; + return xInterruptMaskCount[ portGET_CORE_ID() ]; +} + +static void vFakePortClearInterruptMaskFromISR_callback( UBaseType_t uxNewMaskValue, int cmock_num_calls ) +{ + ( void )uxNewMaskValue; + ( void )cmock_num_calls; + TEST_ASSERT_EQUAL( uxNewMaskValue, xInterruptMaskCount[ portGET_CORE_ID() ] ); + TEST_ASSERT_NOT_EQUAL( 0, xInterruptMaskCount[ portGET_CORE_ID() ] ); + xInterruptMaskCount[ portGET_CORE_ID() ]--; + + /* Check if and pending core yield. */ + vYieldCores(); +} + +static UBaseType_t ulFakePortSetInterruptMask_callback( int cmock_num_calls ) +{ + ( void )cmock_num_calls; + xInterruptMaskCount[ portGET_CORE_ID() ]++; + return xInterruptMaskCount[ portGET_CORE_ID() ]; +} + +static void vFakePortClearInterruptMask_callback( UBaseType_t uxNewMaskValue, int cmock_num_calls ) +{ + ( void )uxNewMaskValue; + ( void )cmock_num_calls; + TEST_ASSERT_EQUAL( uxNewMaskValue, xInterruptMaskCount[ portGET_CORE_ID() ] ); + TEST_ASSERT_NOT_EQUAL( 0, xInterruptMaskCount[ portGET_CORE_ID() ] ); + xInterruptMaskCount[ portGET_CORE_ID() ]--; + + /* Check if and pending core yield. */ + vYieldCores(); +} + +static uint32_t vFakePortDisableInterrupts_callback( int cmock_num_calls ) +{ + xInterruptDisableStatus[ portGET_CORE_ID() ] = pdTRUE; + return 0; +} + +static void vFakePortEnableInterrupts_callback( int cmock_num_calls ) +{ + xInterruptDisableStatus[ portGET_CORE_ID() ] = pdFALSE; + + /* Check if and pending core yield. */ + vYieldCores(); +} + +/* ============================ Trace Functions ============================ */ + +int xTraceBlockingOnQueueReceive( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 0 ) + { + /* After the queue lock is acquired but before the task state is changed, task B + * running on core 1 delete task A. Trace macro is used to simulate asynchronous + * behavior. */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 1 ) + { + /* After the queue lock is acquired but before the task state is changed, task B + * running on core 1 delete task A. Trace macro is used to simulate asynchronous + * behavior. */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 2 ) + { + static int xTaskCallNumbers = 0; + + if( xTaskCallNumbers == 0 ) + { + /* After the queue lock is acquired but before the task state is changed, task B + * running on core 1 delete task A. Trace macro is used to simulate asynchronous + * behavior. */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 0; + } + xTaskCallNumbers++; + } + else if( xQueueTestMode == 3 || xQueueTestMode == 4 || + xQueueTestMode == 5 || xQueueTestMode == 6 || + xQueueTestMode == 7 || xQueueTestMode == 8 || + xQueueTestMode == 9 || xQueueTestMode == 10 ) + { + /* For other test modes, don't use this trace point */ + xReturn = 0; + } + + return xReturn; +} + +int xTraceBlockingOnQueueSend( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 3 ) + { + /* xQueueSend vs vTaskDelete */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 4 ) + { + /* xQueueSend vs vTaskSuspend */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 9 ) + { + /* xSemaphoreGive vs vTaskDelete */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 10 ) + { + /* xSemaphoreGive vs vTaskSuspend */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +int xTraceUnblockingOnQueueReceive( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 0 ) + { + /* xQueueReceive vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 1 ) + { + /* xQueueReceive vs vTaskSuspend - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 2 ) + { + static int xTaskCallNumbers = 0; + if( xTaskCallNumbers == 0 ) + { + /* Keep looping in the xQueueReceive function. */ + vSetCurrentCore( 1 ); + vTaskResume( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 1; + } + xTaskCallNumbers++; + } + else if( xQueueTestMode == 7 ) + { + /* xSemaphoreTake vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 8 ) + { + /* xSemaphoreTake vs vTaskSuspend - return early */ + xReturn = 1; + } + else + { + /* Don't return early for other test modes */ + xReturn = 0; + } + + return xReturn; +} + +int xTraceUnblockingOnQueueSend( void * pxQueue ) +{ + int xReturn; + + ( void ) pxQueue; + + if( xQueueTestMode == 3 ) + { + /* xQueueSend vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 4 ) + { + /* xQueueSend vs vTaskSuspend - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 9 ) + { + /* xSemaphoreGive vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 10 ) + { + /* xSemaphoreGive vs vTaskSuspend - return early */ + xReturn = 1; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +int xTraceEventGroupTaskBlocked( void * pxEventGroup ) +{ + int xReturn; + + ( void ) pxEventGroup; + + if( xQueueTestMode == 5 ) + { + /* xEventGroupWaitBits vs vTaskDelete */ + vSetCurrentCore( 1 ); + vTaskDelete( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else if( xQueueTestMode == 6 ) + { + /* xEventGroupWaitBits vs vTaskSuspend */ + vSetCurrentCore( 1 ); + vTaskSuspend( xTaskHandles[ 0 ] ); + vSetCurrentCore( 0 ); + xReturn = 0; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +int xTraceEventGroupTaskUnblocked( void * pxEventGroup ) +{ + int xReturn; + + ( void ) pxEventGroup; + + if( xQueueTestMode == 5 ) + { + /* xEventGroupWaitBits vs vTaskDelete - return early */ + xReturn = 1; + } + else if( xQueueTestMode == 6 ) + { + /* xEventGroupWaitBits vs vTaskSuspend - return early */ + xReturn = 1; + } + else + { + xReturn = 0; + } + + return xReturn; +} + +/* ============================ Unity Fixtures ============================ */ + +/*! called before each testcase */ +void setUp( void ) +{ + /* Use the common setup for the testing. */ + commonSetUp(); + + /* Specify the granular lock specific implementation. */ + vFakePortInitSpinlock_Stub( vFakePortInitSpinlock_callback ); + vFakePortReleaseSpinlock_Stub( vFakePortReleaseSpinlock_callback ); + vFakePortGetSpinlock_Stub( vFakePortGetSpinlock_callback ); + vFakePortYieldCore_Stub( vFakePortYieldCore_callback ); + + /* Interrupt masks. */ + memset( xInterruptMaskCount, 0, sizeof( UBaseType_t ) * configNUMBER_OF_CORES ); + ulFakePortSetInterruptMaskFromISR_StopIgnore(); + ulFakePortSetInterruptMaskFromISR_Stub( ulFakePortSetInterruptMaskFromISR_callback ); + vFakePortClearInterruptMaskFromISR_StopIgnore(); + vFakePortClearInterruptMaskFromISR_Stub( vFakePortClearInterruptMaskFromISR_callback ); + + ulFakePortSetInterruptMask_StopIgnore(); + ulFakePortSetInterruptMask_Stub( ulFakePortSetInterruptMask_callback ); + vFakePortClearInterruptMask_StopIgnore(); + vFakePortClearInterruptMask_Stub( vFakePortClearInterruptMask_callback ); + + memset( xInterruptDisableStatus, 0, sizeof( BaseType_t ) * configNUMBER_OF_CORES ); + vFakePortDisableInterrupts_StopIgnore(); + vFakePortDisableInterrupts_Stub( vFakePortDisableInterrupts_callback ); + vFakePortEnableInterrupts_StopIgnore(); + vFakePortEnableInterrupts_Stub( vFakePortEnableInterrupts_callback ); +} + +/*! 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 ============================== */ + +void test_granular_locks_timers_smoke(void) +{ + uint32_t i; + + /* Create configNUMBER_OF_CORES - 1 tasks of equal priority */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ){ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + } + + vTaskStartScheduler(); + + /* Timer task at core 0 */ + + /* Verify all configNUMBER_OF_CORES tasks are in the running state */ + for( i = 1; i < configNUMBER_OF_CORES ; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } +} diff --git a/FreeRTOS/Test/CMock/smp/granular_lock/portmacro.h b/FreeRTOS/Test/CMock/smp/granular_lock/portmacro.h new file mode 100644 index 0000000000..10db0b8676 --- /dev/null +++ b/FreeRTOS/Test/CMock/smp/granular_lock/portmacro.h @@ -0,0 +1,209 @@ +/* + * 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 + * + */ + +/* + * Changes from V3.2.3 + * + + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + + + + Changes from V3.2.4 + + + + Removed the use of the %0 parameter within the assembler macros and + + replaced them with hard coded registers. This will ensure the + + assembler does not select the link register as the temp register as + + was occasionally happening previously. + + + + The assembler statements are now included in a single asm block rather + + than each line having its own asm block. + + + + Changes from V4.5.0 + + + + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + + and replaced them with portYield_FROM_ISR() macro. Application code + + should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() + + macros as per the V4.5.1 demo code. + */ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +#include + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +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 +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +#define portPOINTER_SIZE_TYPE uint64_t +/*-----------------------------------------------------------*/ + +/* Requires definition of UBaseType_t */ +#include "fake_port.h" +#include + +/* Hardware specifics. */ +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() __asm volatile ( "NOP" ) + +/* + * These define the timer to use for generating the tick interrupt. + * They are put in this file so they can be shared between "port.c" + * and "portisr.c". + */ +#define portTIMER_REG_BASE_PTR +#define portTIMER_CLK_ENABLE_BIT +#define portTIMER_AIC_CHANNEL + +/*-----------------------------------------------------------*/ + +/* Task utilities. */ + +/* + * portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR + * and portEXIT_SWITCHING_ISR can only be called from ARM mode, but + * are included here for efficiency. An attempt to call one from + * THUMB mode code will result in a compile time error. + */ + +#define portRESTORE_CONTEXT() +/*-----------------------------------------------------------*/ + +#define portSAVE_CONTEXT() +#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 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 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() \ + vFakePortAssertIfInterruptPriorityInvalid() +#define portENTER_CRITICAL() vFakePortEnterCriticalSection() +#define portEXIT_CRITICAL() vFakePortExitCriticalSection() + +#define portCHECK_IF_IN_ISR() vFakePortCheckIfInISR() +#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) \ + vPortCurrentTaskDying( ( pvTaskToDelete ), ( pxPendYield ) ) +#define portSETUP_TCB( pxTCB ) portSetupTCB_CB( pxTCB ); +#define portASSERT_IF_IN_ISR() vFakePortAssertIfISR(); + +#define portGET_CORE_ID() vFakePortGetCoreID() +#define portYIELD_CORE( x ) vFakePortYieldCore( x ) + +#define portENTER_CRITICAL_FROM_ISR vFakePortEnterCriticalFromISR +#define portEXIT_CRITICAL_FROM_ISR vFakePortExitCriticalFromISR + +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) + +/* We need to define it here because CMock does not recognize the + * #if ( portUSING_MPU_WRAPPERS == 1 ) guard around xTaskGetMPUSettings + * and then complains about the missing xMPU_SETTINGS type in the + * generated mocks. */ +typedef struct MPU_SETTINGS +{ + uint32_t ulDummy; +} xMPU_SETTINGS; + +#define portUSING_GRANULAR_LOCKS ( 1 ) + +typedef struct xPortSpinlock +{ + volatile uint32_t uxLockCount; + volatile BaseType_t xOwnerCore; +} xPortSpinlock_t; + +#define portSPINLOCK_TYPE xPortSpinlock_t + +void vFakePortGetSpinlock( BaseType_t xCoreID, portSPINLOCK_TYPE *pxSpinlock ); +#define portGET_SPINLOCK vFakePortGetSpinlock + +void vFakePortReleaseSpinlock( BaseType_t xCoreID, portSPINLOCK_TYPE *pxSpinlock ); +#define portRELEASE_SPINLOCK vFakePortReleaseSpinlock + +void vFakePortInitSpinlock( portSPINLOCK_TYPE *pxSpinlock ); +#define portINIT_SPINLOCK vFakePortInitSpinlock +#define portINIT_SPINLOCK_STATIC { 0 } + +#define portENTER_CRITICAL_DATA_GROUP vFakePortEnterCriticalDataGroup +#define portEXIT_CRITICAL_DATA_GROUP vFakePortExitCriticalDataGroup +void vFakePortEnterCriticalDataGroup( portSPINLOCK_TYPE *pxTaskSpinLock, portSPINLOCK_TYPE *pxISRSpinLock ); +void vFakePortExitCriticalDataGroup( portSPINLOCK_TYPE *pxTaskSpinLock, portSPINLOCK_TYPE *pxISRSpinLock ); + +extern uint32_t xPortCriticalNestingCount[ configNUMBER_OF_CORES ]; +#define portGET_CRITICAL_NESTING_COUNT( xCoreID ) xPortCriticalNestingCount[ ( xCoreID ) ] +#define portSET_CRITICAL_NESTING_COUNT( xCoreID, x ) do{ xPortCriticalNestingCount[ ( xCoreID ) ] = ( x ); } while( 0 ) +#define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ) do{ xPortCriticalNestingCount[ ( xCoreID ) ]++; } while( 0 ) +#define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ) do{ xPortCriticalNestingCount[ ( xCoreID ) ]--; } while( 0 ) + + +/*-----------------------------------------------------------*/ + +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ +#endif /* PORTMACRO_H */ 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 index c85c39add2..7c36f07d1b 100644 --- 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 @@ -422,6 +422,7 @@ void test_coverage_prvYieldCore_core_id_ne_current_coreid( void ) TaskHandle_t xTaskHandle; task.xTaskRunState = 1; /* running on core 1 */ + task.xPreemptionDisable = 1; task2.xTaskRunState = -2; /* running on core 2 taskTASK_YIELDING */ xTaskHandle = &task; pxCurrentTCBs[ 0 ] = &task; @@ -465,6 +466,7 @@ void test_coverage_prvYieldCore_runstate_eq_yielding( void ) TaskHandle_t xTaskHandle; task.xTaskRunState = 1; /* running on core 1 */ + task.xPreemptionDisable = 1; task2.xTaskRunState = -2; /* running on core 2 taskTASK_YIELDING */ xTaskHandle = &task; pxCurrentTCBs[ 0 ] = &task;