mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-05-08 22:29:04 -04:00
Add stack check macros.
This commit is contained in:
parent
71ef3153ea
commit
39f6b0b5de
|
@ -118,8 +118,8 @@
|
|||
#error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_uxGetStackHighWaterMark
|
||||
#define INCLUDE_uxGetStackHighWaterMark 0
|
||||
#ifndef INCLUDE_uxTaskGetStackHighWaterMark
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 0
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_RECURSIVE_MUTEXES
|
||||
|
@ -189,6 +189,9 @@
|
|||
#define traceBLOCKING_ON_QUEUE_SEND( pxQueue )
|
||||
#endif
|
||||
|
||||
#ifndef configCHECK_FOR_STACK_OVERFLOW
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||
#endif
|
||||
|
||||
/* The following event macros are embedded in the kernel API calls. */
|
||||
|
||||
|
|
|
@ -868,9 +868,9 @@ unsigned portLONG ulTaskEndTrace( void );
|
|||
|
||||
/**
|
||||
* task.h
|
||||
* <PRE>unsigned portBASE_TYPE uxGetStackHighWaterMark( void );</PRE>
|
||||
* <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void );</PRE>
|
||||
*
|
||||
* INCLUDE_uxGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for
|
||||
* INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for
|
||||
* this function to be available.
|
||||
*
|
||||
* Returns the high water mark for the stack of the calling task. That is,
|
||||
|
@ -878,7 +878,7 @@ unsigned portLONG ulTaskEndTrace( void );
|
|||
* started. The small the returned number the closer the task has come
|
||||
* to overflowing its stack.
|
||||
*/
|
||||
unsigned portBASE_TYPE uxGetStackHighWaterMark( void );
|
||||
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void );
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
|
||||
|
|
294
Source/tasks.c
294
Source/tasks.c
|
@ -25,11 +25,11 @@
|
|||
|
||||
***************************************************************************
|
||||
|
||||
Please ensure to read the configuration and relevant port sections of the
|
||||
Please ensure to read the configuration and relevant port sections of the
|
||||
online documentation.
|
||||
|
||||
+++ http://www.FreeRTOS.org +++
|
||||
Documentation, latest information, license and contact details.
|
||||
Documentation, latest information, license and contact details.
|
||||
|
||||
+++ http://www.SafeRTOS.com +++
|
||||
A version that is certified for use in safety critical systems.
|
||||
|
@ -40,180 +40,6 @@
|
|||
***************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.00:
|
||||
|
||||
+ Call to portRESTORE_CONTEXT has been removed. The first context
|
||||
switch is now performed within sPortStartScheduler().
|
||||
|
||||
Changes from V1.01:
|
||||
|
||||
+ More use of 8bit data types.
|
||||
+ Function name prefixes changed where the data type returned has changed.
|
||||
+ configUSE_TRACE_FACILITY is no longer defined by default.
|
||||
|
||||
Changes from V1.2.0
|
||||
|
||||
+ Introduced ucTopReadyPriority. This tracks the highest priority ready
|
||||
queue that contains a valid TCB and thus makes the context switch
|
||||
slightly faster.
|
||||
|
||||
+ prvAddTaskToReadyQueue() has been made a macro.
|
||||
|
||||
Changes from V1.2.6
|
||||
|
||||
+ Added conditional compilation directives.
|
||||
+ Extended API.
|
||||
+ Rearranged function order.
|
||||
+ Creating a task now causes a context switch if the task being created
|
||||
has a higher priority than the calling task - assuming the kernel is
|
||||
running.
|
||||
+ vTaskDelete() now only causes a context switch if the calling task is
|
||||
the task being deleted.
|
||||
|
||||
Changes from V2.0.0
|
||||
|
||||
+ Allow the type of the tick count to be 16 or 32 bits.
|
||||
+ Introduce xPendingReadyList feature to allow the time interrupts have to
|
||||
be disabled to be minimised.
|
||||
+ Remove the #if( INCLUDE_vTaskSuspendAll ) statements. vTaskSuspendAll()
|
||||
is now always included as it is used by the scheduler itself.
|
||||
|
||||
Changes from V2.1.0
|
||||
|
||||
+ Bug fix - pxCurrentTCB is now initialised before the call to
|
||||
prvInitializeTaskLists(). Previously pxCurrentTCB could be accessed
|
||||
while null.
|
||||
|
||||
Changed from V2.1.1
|
||||
|
||||
+ Change to where lStackSize is declared within sTaskCreate() to prevent
|
||||
compiler warnings with 8051 port.
|
||||
|
||||
Changes from V2.2.0
|
||||
|
||||
+ Explicit use of 'signed' qualifier on portCHAR types added.
|
||||
+ Changed odd calculation of initial pxTopOfStack value when
|
||||
portSTACK_GROWTH < 0.
|
||||
+ Removed pcVersionNumber definition.
|
||||
|
||||
Changes from V2.5.3
|
||||
|
||||
+ cTaskResumeAll() modified to ensure it can be called prior to the task
|
||||
lists being initialised.
|
||||
|
||||
Changes from V2.5.5
|
||||
|
||||
+ Added API function vTaskDelayUntil().
|
||||
+ Added INCLUDE_vTaskDelay conditional compilation.
|
||||
|
||||
Changes from V2.6.0
|
||||
|
||||
+ Updated the vWriteTraceToBuffer macro to always be 4 byte aligned so it
|
||||
can be used on ARM architectures.
|
||||
+ tskMAX_TASK_NAME_LEN definition replaced with the port specific
|
||||
configMAX_TASK_NAME_LEN definition.
|
||||
+ Removed the call to strcpy when copying across the task name into the
|
||||
TCB.
|
||||
+ Added ucTasksDeleted variable to prevent vTaskSuspendAll() being called
|
||||
too often in the idle task.
|
||||
|
||||
Changes between V3.0.0 and V2.6.1
|
||||
|
||||
+ When resuming the scheduler a yield is performed if either a tick has
|
||||
been missed, or a task is moved from the pending ready list into a ready
|
||||
list. Previously a yield was not performed on this second condition.
|
||||
+ Introduced the type portBASE_TYPE. This necessitates several API
|
||||
changes.
|
||||
+ Removed the sUsingPreemption variable. The constant defined in
|
||||
portmacro.h is now used directly.
|
||||
+ The idle task can now include an optional hook function - and no longer
|
||||
completes its time slice if other tasks with equal priority to it are
|
||||
ready to run.
|
||||
+ See the FreeRTOS.org documentation for more information on V2.x.x to
|
||||
V3.x.x modifications.
|
||||
|
||||
Changes from V3.1.1
|
||||
|
||||
+ Modified vTaskPrioritySet() and vTaskResume() to allow these functions to
|
||||
be called while the scheduler is suspended.
|
||||
+ Corrected the task ordering within event lists.
|
||||
|
||||
Changes from V3.2.0
|
||||
|
||||
+ Added function xTaskGetCurrentTaskHandle().
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Changed the volatile declarations on some variables to reflect the
|
||||
changes to the list definitions.
|
||||
+ Changed the order of the TCB definition so there is commonality between
|
||||
the task control block and a co-routine control block.
|
||||
+ Allow the scheduler to be started even if no tasks other than the idle
|
||||
task has been created. This allows co-routines to run even when no tasks
|
||||
have been created.
|
||||
+ The need for a context switch is now signalled if a task woken by an
|
||||
event has a priority greater or equal to the currently running task.
|
||||
Previously this was only greater than.
|
||||
|
||||
Changes from V4.0.0
|
||||
|
||||
+ Added the xMissedYield handling.
|
||||
|
||||
Changes from V4.0.1
|
||||
|
||||
+ The function vTaskList() now suspends the scheduler rather than disabling
|
||||
interrupts during the creation of the task list.
|
||||
+ Allow a task to delete itself by passing in its own handle. Previously
|
||||
this could only be done by passing in NULL.
|
||||
+ The tick hook function is now called only within a tick isr. Previously
|
||||
it was also called when the tick function was called during the scheduler
|
||||
unlocking process.
|
||||
|
||||
Changes from V4.0.3
|
||||
|
||||
+ Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary
|
||||
yields.
|
||||
|
||||
Changed from V4.0.4
|
||||
|
||||
+ Bug fix: The 'value' of the event list item is updated when the priority
|
||||
of a task is changed. Previously only the priority of the TCB itself was
|
||||
changed.
|
||||
+ When resuming a task a check is first made to see if the task is actually
|
||||
suspended.
|
||||
+ vTaskPrioritySet() and vTaskResume() no longer use the event list item.
|
||||
This has not been necessary since V4.0.1 when the xMissedYield handling
|
||||
was added.
|
||||
+ Implement xTaskResumeFromISR().
|
||||
|
||||
Changes from V4.0.5
|
||||
|
||||
+ Added utility functions and xOverflowCount variable to facilitate the
|
||||
queue.c changes.
|
||||
|
||||
Changes from V4.1.2
|
||||
|
||||
+ Tasks that block on events with a timeout of portMAX_DELAY are now
|
||||
blocked indefinitely if configINCLUDE_vTaskSuspend is defined.
|
||||
Previously portMAX_DELAY was just the longest block time possible.
|
||||
|
||||
Changes from V4.1.3
|
||||
|
||||
+ Very small change made to xTaskCheckForTimeout() as a result of the
|
||||
SafeRTOS testing. This corrects the case where the function can return an
|
||||
invalid value - but only in an extremely unlikely scenario.
|
||||
|
||||
Changes since V4.3.1:
|
||||
|
||||
+ Added xTaskGetSchedulerState() function.
|
||||
+ Added prvIsTaskSuspended() to take into account the Occurrence of
|
||||
vTaskResume() or vTaskResumeFromISR() being called passing in the
|
||||
handle of a task that appears in the Suspended list only because it
|
||||
is blocked on an event without a timeout being specified.
|
||||
+ Updated xTaskCheckForTimeout() to take into account that tasks blocked
|
||||
using the Suspended list should never time out.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -345,6 +171,8 @@ static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
|||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro that writes a trace of scheduler activity to a buffer. This trace
|
||||
* shows which task is running when and is very useful as a debugging tool.
|
||||
|
@ -382,7 +210,7 @@ static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
|||
#define vWriteTraceToBuffer()
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Place the task represented by pxTCB into the appropriate ready queue for
|
||||
|
@ -398,7 +226,8 @@ static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
|||
uxTopReadyPriority = pxTCB->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of tasks that are currently delayed to see if
|
||||
|
@ -424,9 +253,82 @@ register tskTCB *pxTCB; \
|
|||
{ \
|
||||
vListRemove( &( pxTCB->xEventListItem ) ); \
|
||||
} \
|
||||
prvAddTaskToReadyQueue( pxTCB ); \
|
||||
prvAddTaskToReadyQueue( pxTCB ); \
|
||||
} \
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Call the stack overflow hook function if the stack of the task being swapped
|
||||
* out is currently overflowed, or looks like it might have overflowed in the
|
||||
* past.
|
||||
*
|
||||
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
|
||||
* the current stack state only - comparing the current top of stack value to
|
||||
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
|
||||
* will also cause the last few stack bytes to be checked to ensure the value
|
||||
* to which the bytes were set when the task was created have not been
|
||||
* overwritten. Note this second test does not guarantee that an overflown
|
||||
* stack will always be recognised.
|
||||
*/
|
||||
|
||||
#if( configCHECK_FOR_STACK_OVERFLOW == 0 )
|
||||
|
||||
/* FreeRTOSConfig.h is not set to check for stack overflows. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW()
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH >= 0 ) )
|
||||
|
||||
/* This is an invalid setting. */
|
||||
#error configCHECK_FOR_STACK_OVERFLOW can only be set to a non zero value on architectures where the stack grows down from high memory.
|
||||
|
||||
#endif /* ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH >= 0 ) */
|
||||
|
||||
#if( configCHECK_FOR_STACK_OVERFLOW == 1 )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \
|
||||
\
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
|
||||
#if( configCHECK_FOR_STACK_OVERFLOW > 1 )
|
||||
|
||||
/* Both the current statck state and the stack fill bytes are to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \
|
||||
static const unsigned portCHAR ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
|
||||
\
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
\
|
||||
/* Has the extremity of the task stack ever been written over? */ \
|
||||
if( memcmp( pxCurrentTCB->pxStack, ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Several functions take an xTaskHandle parameter that can optionally be NULL,
|
||||
|
@ -508,7 +410,7 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
|
|||
* This function determines the 'high water mark' of the task stack by
|
||||
* determining how much of the stack remains at the original preset value.
|
||||
*/
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxGetStackHighWaterMark == 1 ) )
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
||||
|
||||
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte );
|
||||
|
||||
|
@ -528,8 +430,6 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CREATION API documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
@ -663,7 +563,7 @@ tskTCB * pxNewTCB;
|
|||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
deleted. */
|
||||
if( pxTaskToDelete == pxCurrentTCB )
|
||||
{
|
||||
|
@ -697,7 +597,7 @@ tskTCB * pxNewTCB;
|
|||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Force a reschedule if we have just deleted the current task. */
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( ( void * ) pxTaskToDelete == NULL )
|
||||
{
|
||||
|
@ -912,7 +812,7 @@ tskTCB * pxNewTCB;
|
|||
{
|
||||
/* The priority change may have readied a task of higher
|
||||
priority than the calling task. */
|
||||
if( uxNewPriority > uxCurrentPriority )
|
||||
if( uxNewPriority > uxCurrentPriority )
|
||||
{
|
||||
if( pxTask != NULL )
|
||||
{
|
||||
|
@ -985,7 +885,7 @@ tskTCB * pxNewTCB;
|
|||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
suspended. */
|
||||
if( pxTaskToSuspend == pxCurrentTCB )
|
||||
{
|
||||
|
@ -1407,8 +1307,8 @@ inline void vTaskIncrementTick( void )
|
|||
{
|
||||
xList *pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists.
|
||||
If there are any items in pxDelayedTaskList here then there is
|
||||
/* Tick count has overflowed so we need to swap the delay lists.
|
||||
If there are any items in pxDelayedTaskList here then there is
|
||||
an error! */
|
||||
pxTemp = pxDelayedTaskList;
|
||||
pxDelayedTaskList = pxOverflowDelayedTaskList;
|
||||
|
@ -1423,7 +1323,7 @@ inline void vTaskIncrementTick( void )
|
|||
{
|
||||
++uxMissedTicks;
|
||||
|
||||
/* The tick hook gets called at regular intervals, even if the
|
||||
/* The tick hook gets called at regular intervals, even if the
|
||||
scheduler is locked. */
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
{
|
||||
|
@ -1514,6 +1414,8 @@ void vTaskSwitchContext( void )
|
|||
return;
|
||||
}
|
||||
|
||||
taskCHECK_FOR_STACK_OVERFLOW();
|
||||
|
||||
/* Find the highest priority queue that contains ready tasks. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
|
||||
{
|
||||
|
@ -1548,7 +1450,7 @@ portTickType xTimeToWake;
|
|||
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
{
|
||||
if( xTicksToWait == portMAX_DELAY )
|
||||
{
|
||||
/* Add ourselves to the suspended task list instead of a delayed task
|
||||
|
@ -1933,7 +1835,8 @@ tskTCB *pxNewTCB;
|
|||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxGetStackHighWaterMark == 1 ) )
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
||||
|
||||
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )
|
||||
{
|
||||
register unsigned portSHORT usCount = 0;
|
||||
|
@ -1948,14 +1851,17 @@ tskTCB *pxNewTCB;
|
|||
|
||||
return usCount;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_uxGetStackHighWaterMark == 1 )
|
||||
unsigned portBASE_TYPE uxGetStackHighWaterMark( void )
|
||||
#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
|
||||
|
||||
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void )
|
||||
{
|
||||
return usTaskCheckFreeStackSpace( pxCurrentTCB->pxStack );
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
Loading…
Reference in a new issue