Skip to content

Commit

Permalink
Merge branch 'main' into fix_misra_17_7
Browse files Browse the repository at this point in the history
  • Loading branch information
aggarg authored Dec 6, 2023
2 parents 000ae77 + edce1e9 commit fb2004b
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 131 deletions.
82 changes: 58 additions & 24 deletions MISRA.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,72 @@ grep 'MISRA Ref 8.4.1' . -rI

#### Rule 8.4

MISRA C:2012 Rule 8.4: A compatible declaration shall be visible when an
object or function with external linkage is defined.

_Ref 8.4.1_

- MISRA C:2012 Rule 8.4: A compatible declaration shall be visible when an
object or function with external linkage is defined.
This rule requires that a compatible declaration is made available
in a header file when an object with external linkage is defined.
pxCurrentTCB(s) is defined with external linkage but it is only
referenced from the assembly code in the port files. Therefore, adding
a declaration in header file is not useful as the assembly code will
still need to declare it separately.
- This rule requires that a compatible declaration is made available
in a header file when an object with external linkage is defined.
pxCurrentTCB(s) is defined with external linkage but it is only
referenced from the assembly code in the port files. Therefore, adding
a declaration in header file is not useful as the assembly code will
still need to declare it separately.


#### Rule 11.3

MISRA C:2012 Rule 11.3: A cast shall not be performed between a pointer to
object type and a pointer to a different object type.

_Ref 11.3.1_
- This rule prohibits casting a pointer to object into a pointer to a
different object because it may result in an incorrectly aligned pointer,
leading to undefined behavior. Even if the casting produces a correctly
aligned pointer, the behavior may be still undefined if the pointer is
used to access an object. FreeRTOS deliberately creates external aliases
for all the kernel object types (StaticEventGroup_t, StaticQueue_t,
StaticStreamBuffer_t, StaticTimer_t and StaticTask_t) for data hiding
purposes. The internal object types and the corresponding external
aliases are guaranteed to have the same size and alignment which is
checked using configASSERT.


#### Rule 11.5

MISRA C:2012 Rule 11.5: A conversion should not be performed from pointer to
void into pointer to object.
This rule prohibits conversion of a pointer to void into a pointer to
object because it may result in an incorrectly aligned pointer leading
to undefined behavior.

- MISRA C:2012 Rule 11.3: A cast shall not be performed between a pointer to
object type and a pointer to a different object type.
This rule prohibits casting a pointer to object into a pointer to a
different object because it may result in an incorrectly aligned pointer,
leading to undefined behavior. Even if the casting produces a correctly
aligned pointer, the behavior may be still undefined if the pointer is
used to access an object. FreeRTOS deliberately creates external aliases
for all the kernel object types (StaticEventGroup_t, StaticQueue_t,
StaticStreamBuffer_t, StaticTimer_t and StaticTask_t) for data hiding
purposes. The internal object types and the corresponding external
aliases are guaranteed to have the same size and alignment which is
checked using configASSERT.
_Ref 11.5.1_
- The memory blocks returned by pvPortMalloc() are guaranteed to meet the
architecture alignment requirements specified by portBYTE_ALIGNMENT.
The casting of the pointer to void returned by pvPortMalloc() is,
therefore, safe because it is guaranteed to be aligned.

_Ref 11.5.2_
- The conversion from a pointer to void into a pointer to EventGroup_t is
safe because it is a pointer to EventGroup_t, which is returned to the
application at the time of event group creation for data hiding
purposes.

_Ref 11.5.3_
- The conversion from a pointer to void in list macros for list item owner
is safe because the type of the pointer stored and retrieved is the
same.

_Ref 11.5.4_
- The conversion from a pointer to void into a pointer to EventGroup_t is
safe because it is a pointer to EventGroup_t, which is passed as a
parameter to the xTimerPendFunctionCallFromISR API when the callback is
pended.

_Ref 11.5.5_
- The conversion from a pointer to void into a pointer to uint8_t is safe
because data storage buffers are implemented as uint8_t arrays for the
ease of sizing, alignment and access.


### MISRA configuration
Expand Down Expand Up @@ -81,10 +119,6 @@ Copy below content to `misra.conf` to run Coverity on FreeRTOS-Kernel.
{
deviation: "Rule 8.7",
reason: "API functions are not used by the library outside of the files they are defined; however, they must be externally visible in order to be used by an application."
},
{
deviation: "Rule 11.5",
reason: "Allow casts from `void *`. List owner, pvOwner, is stored as `void *` and are cast to various types for use in functions."
}
]
}
Expand Down
3 changes: 3 additions & 0 deletions croutine.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex );

/* Allocate the memory that will store the co-routine control block. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );

if( pxCoRoutine )
Expand Down
39 changes: 21 additions & 18 deletions event_groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,

traceENTER_xEventGroupCreate();

/* Allocate the event group. Justification for MISRA deviation as
* follows: pvPortMalloc() always ensures returned memory blocks are
* aligned per the requirements of the MCU stack. In this case
* pvPortMalloc() must return a pointer that is guaranteed to meet the
* alignment requirements of the EventGroup_t structure - which (if you
* follow it through) is the alignment requirements of the TickType_t type
* (EventBits_t being of TickType_t itself). Therefore, whenever the
* stack alignment requirements are greater than or equal to the
* TickType_t alignment requirements the cast is safe. In other cases,
* where the natural word size of the architecture is less than
* sizeof( TickType_t ), the TickType_t variables will be accessed in two
* or more reads operations, and the alignment requirements is only that
* of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );

if( pxEventBits != NULL )
{
Expand Down Expand Up @@ -749,7 +739,10 @@ void vEventGroupSetBitsCallback( void * pvEventGroup,
{
traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );

( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
/* MISRA Ref 11.5.4 [Callback function parameter] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );

traceRETURN_vEventGroupSetBitsCallback();
}
Expand All @@ -762,7 +755,10 @@ void vEventGroupClearBitsCallback( void * pvEventGroup,
{
traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );

( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
/* MISRA Ref 11.5.4 [Callback function parameter] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );

traceRETURN_vEventGroupClearBitsCallback();
}
Expand Down Expand Up @@ -831,7 +827,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
{
UBaseType_t xReturn;
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */

/* MISRA Ref 11.5.2 [Opaque pointer] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup;

traceENTER_uxEventGroupGetNumber( xEventGroup );

Expand Down Expand Up @@ -859,7 +859,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
{
traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );

( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
/* MISRA Ref 11.5.2 [Opaque pointer] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;

traceRETURN_vEventGroupSetNumber();
}
Expand Down
16 changes: 11 additions & 5 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -1886,14 +1886,20 @@
#ifndef traceENTER_xTaskGetIdleTaskHandle
#define traceENTER_xTaskGetIdleTaskHandle()
#endif
#else
#ifndef traceENTER_xTaskGetIdleTaskHandle
#define traceENTER_xTaskGetIdleTaskHandle( xCoreID )
#endif

#if ( configNUMBER_OF_CORES == 1 )
#ifndef traceRETURN_xTaskGetIdleTaskHandle
#define traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandle )
#endif
#endif

#ifndef traceRETURN_xTaskGetIdleTaskHandle
#define traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandle )
#ifndef traceENTER_xTaskGetIdleTaskHandleForCore
#define traceENTER_xTaskGetIdleTaskHandleForCore( xCoreID )
#endif

#ifndef traceRETURN_xTaskGetIdleTaskHandleForCore
#define traceRETURN_xTaskGetIdleTaskHandleForCore( xIdleTaskHandle )
#endif

#ifndef traceENTER_vTaskStepTick
Expand Down
17 changes: 8 additions & 9 deletions include/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -2030,24 +2030,23 @@ BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
* xTaskGetIdleTaskHandle() is only available if
* INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h.
*
* Simply returns the handle of the idle task. It is not valid to call
* xTaskGetIdleTaskHandle() before the scheduler has been started.
* In single-core FreeRTOS, this function simply returns the handle of the idle
* task. It is not valid to call xTaskGetIdleTaskHandle() before the scheduler
* has been started.
*
* In the FreeRTOS SMP, there are a total of configNUMBER_OF_CORES idle tasks:
* 1. 1 Active idle task which does all the housekeeping.
* 2. ( configNUMBER_OF_CORES - 1 ) Passive idle tasks which do nothing.
* These idle tasks are created to ensure that each core has an idle task to run when
* no other task is available to run.
*
* Set xCoreID to 0 to get the Active idle task handle. Set xCoreID to
* 1,2 ... ( configNUMBER_OF_CORES - 1 ) to get the Passive idle task
* handles.
* no other task is available to run. Call xTaskGetIdleTaskHandle() or
* xTaskGetIdleTaskHandleForCore() with xCoreID set to 0 to get the Active
* idle task handle. Call xTaskGetIdleTaskHandleForCore() with xCoreID set to
* 1,2 ... ( configNUMBER_OF_CORES - 1 ) to get the Passive idle task handles.
*/
#if ( configNUMBER_OF_CORES == 1 )
TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
TaskHandle_t xTaskGetIdleTaskHandle( BaseType_t xCoreID ) PRIVILEGED_FUNCTION;
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION;

/**
* configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
Expand Down
14 changes: 4 additions & 10 deletions queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,16 +517,10 @@ BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
* zero in the case the queue is used as a semaphore. */
xQueueSizeInBytes = ( size_t ) ( ( size_t ) uxQueueLength * ( size_t ) uxItemSize );

/* Allocate the queue and storage area. Justification for MISRA
* deviation as follows: pvPortMalloc() always ensures returned memory
* blocks are aligned per the requirements of the MCU stack. In this case
* pvPortMalloc() must return a pointer that is guaranteed to meet the
* alignment requirements of the Queue_t structure - which in this case
* is an int8_t *. Therefore, whenever the stack alignment requirements
* are greater than or equal to the pointer to char requirements the cast
* is safe. In other cases alignment requirements are not strict (one or
* two bytes). */
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );

if( pxNewQueue != NULL )
{
Expand Down
Loading

0 comments on commit fb2004b

Please sign in to comment.