FreeRTOS / FreeRTOS-Kernel

FreeRTOS kernel files only, submoduled into https://github.com/FreeRTOS/FreeRTOS and various other repos.

Home Page:https://www.FreeRTOS.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Access violation in taskSELECT_HIGHEST_PRIORITY_TASK()

Ju1He1 opened this issue · comments

Describe the bug
Hey guys, we upgraded to the latest FreeRTOS release.
Unfortunately, when running the MSVC Simulation in latest VS 2022 we are running into a access violation after calling vTaskStartScheduler().

After expanding the macro it is clear that uxTopPriority has an undefined value which causes pxReadyTasksLists[uxTopPriority] to crash in tasks.c.

Unexpanded:
grafik

Expanded
grafik

Target
latest MSVC 17 Simulation

Host

  • Host OS: Windows 10

To Reproduce
Run

static void RunGTestInTask(void* pvParameters)
{
//you should not get to here
};

int main(int argc, char* argv[])
{

  ::testing::InitGoogleTest(&argc, argv);


  configASSERT(pdTRUE == xTaskCreate(
    RunGTestInTask,       /* Function that implements the task. */
    mg_strGTestTaskName.c_str(),          /* Text name for the task. */
    configMINIMAL_STACK_SIZE,      /* Stack size in words, not bytes. */
    (void*)1,    /* Parameter passed into the task. */
    5,/* Priority at which the task is created. */
    &mg_gtestTask));      /* Used to pass out the created task's handle. */


  /* Start the tasks and timer running. */
  vTaskStartScheduler();

  if (0 != mg_iGTestResult)
  {
    std::runtime_error ex("GTest failed with result" + std::to_string(mg_iGTestResult));
    throw ex;
  }
  return mg_iGTestResult;
}

Expected behavior
The application should not crash :D

Screenshots
See above

Additional context
I have taken the latest config file from the Windows Simulator. Not sure if this is relevant

/*
 * 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

 /*-----------------------------------------------------------
  * 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
  *----------------------------------------------------------*/

#define configUSE_PREEMPTION					1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION	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 ) ( 2000 * 1024 ) ) /* This demo tests heap_5 so places multiple blocks within this total heap size.  See mainREGION_1_SIZE to mainREGION_3_SIZE definitions in main.c. */
#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			2
#define configENABLE_HEAP_PROTECTOR     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					( 7 )

/* Run time stats gathering configuration options. */
#define configRUN_TIME_COUNTER_TYPE				uint64_t
configRUN_TIME_COUNTER_TYPE 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			1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue()

/* Co-routine related configuration options. */
#define configUSE_CO_ROUTINES 					1
#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_xTaskGetHandle					1
#define INCLUDE_eTaskGetState					1
#define INCLUDE_xSemaphoreGetMutexHolder		1
#define INCLUDE_xTimerPendFunctionCall			1
#define INCLUDE_xTaskAbortDelay					1

/* The Win32 target is capable of running all the tests tasks at the same
 * time. */
#define configRUN_ADDITIONAL_TESTS				1

 /* It is a good idea to define configASSERT() while developing.  configASSERT()
 uses the same semantics as the standard C assert() macro. */
extern void vAssertCalled(const char* const pcFileName, unsigned long ulLine);
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled(__FILE__, __LINE__)

#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 */

#ifdef WIN32_LEAN_AND_MEAN
#include "winsock2.h"
#else
#include <winsock.h>
#endif /* WIN32_LEAN_AND_MEAN */



#endif /* FREERTOS_CONFIG_H */

Add any other context about the problem here.
see above

Does anybody else has this issue?

Thanks for reporting this bug @Ju1He1! I'll take a look and make sure to post back the next steps. For now - I will be trying to duplicate this issue.

Oddly enough the BitScanReverse (line 5155 of your second image) should handle the instantiation of uxTopPriority.

I did some digging. _BitScanReverse searches for the MSB.
However uxTopPriority is left initialised. This will return some random MSB.
Also _BitScanReverse() seams to return a boolean in case everything worked

I did the following changes

UBaseType_t uxTopPriority = 0; 
BOOLEAN bRes = _BitScanReverse((DWORD*)&(uxTopPriority), (uxTopReadyPriority)); 
configASSERT(TRUE == bRes); //is there a better way to handle errors?

with these changes it works again. IMHO leaving variables uninitialized is pretty dangerous, we should init all variables to some error value by default.
@kstribrnAmzn pls check if you can adopt these changes to your main branch :)

However uxTopPriority is left initialised.

I'm assuming you meant uninitialized there since this goes with your solution. This is interesting as _BitScanReverse() is supposed to set the value of uxTopPriority to the index of the most significant bit set. In your case, this should have been bit 5 which would correspond to your example task priority.

This may be due to the version of VS that you're using. Our demo doesn't use the full VS setup but instead a stripped down version of MSBuild.

I've asked @chinglee-iot to duplicate this issue as he has a windows machine setup.

Hey @kstribrnAmzn : I agree this is a strange behaviour.
Not sure if this is releated to the VS version though.
This crash is 100% reproducible in debug builds. In release builds it occurs some times.
This is because in the debug build the stack in initialised with 0xccccccc (i.e. a very high number which is likely to trigger an index out of bounds error). I do not know what the value of the stack is in release builds.
=>for your tests please run debug builds :)

@Ju1He1

It looks like this issue is a data type problem.

From your screen share, UBaseType_t is defined as 8 bytes data type while _BitScanReverse takes a 4 bytes data type pointer to return index. This cause the problem that only the first 4 bytes are updated with index the second 4 bytes are filled with 0xCCCCCCCC in debug mode.

uxTopPriority = 14,757,395,255,531,667,461 => 0xCCCCCCCC00000005

In the implementation, UBaseType_t is 4 bytes long with 32-bits compiler and is 8 bytes long with 64-bits compiler. portGET_HIGHEST_PRIORITY is implemented differently with 64-bits compiler to consider in the size of UBaseType_t.

It looks like UBaseType_t is defined as 8 bytes data type but compiled with 32-bits compiler. Can you help to check the following information in your environment?

  • The UbaseType_t definition
  • Which portGET_HIGHEST_PRIORITY implementation is used

Usually, they are controlled by MSVC predefined macro _M_X64. Reference the following link.

Hey @chinglee-iot Thx for your answer
The latest release https://github.com/FreeRTOS/FreeRTOS-Kernel/releases/tag/V11.0.1 does not provide multiple implementations of portGET_HIGHEST_PRIORITY (). However Ubasetype_T is defined as typedef unsigned long long UBaseType_t; (i.e. 64 bit).
When I replace the portGET_HIGHEST_PRIORITY() in the current release with the new version from the main branch it works :)

=> so could you create a new release to fix this issue?

The PR to supporting building for x64 in MSVC is merged after v11.0.1 is released. This fix will be included in the next release. Thank you for creating this issue.

can you make a gues when a next release will be created? Are we talking about a weeks or several months?

I will propose a new release to the team, but I can't guess the creation time.
At the same time, we can consider the following methods to unblock your development:

  • Use 32-bit compiler to build MSVC simulator
  • Merge the PR to support 64-bit compiler to your code base

This PR will be closed due to the fix is already merged in the main branch. Thanks for creating this issue again.