Add stack check macros.

This commit is contained in:
Richard Barry 2008-03-03 20:56:55 +00:00
parent 71ef3153ea
commit 39f6b0b5de
3 changed files with 108 additions and 199 deletions

View file

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

View file

@ -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

View file

@ -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
@ -399,6 +227,7 @@ static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
} \
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
}
/*-----------------------------------------------------------*/
/*
* Macro that looks at the list of tasks that are currently delayed to see if
@ -427,6 +256,79 @@ register tskTCB *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
*----------------------------------------------------------*/
@ -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 ] ) ) )
{
@ -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
/*-----------------------------------------------------------*/