Modifications to correct behaviour when a task is blocked without specifying a wake time, and also introduce the xTaskGetSchedulerState() function.

This commit is contained in:
Richard Barry 2007-07-28 16:33:07 +00:00
parent 94c94d3c0e
commit 7a8eb507a7
3 changed files with 142 additions and 49 deletions

View File

@ -84,6 +84,10 @@
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
#endif
#ifdef GCC_ARM7_ECLIPSE
#include "portmacro.h"
#endif
#ifdef ROWLEY_LPC23xx
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
#endif

View File

@ -33,6 +33,12 @@
***************************************************************************
*/
/*
Changes since V4.3.1:
+ Added xTaskGetSchedulerState() function.
*/
#ifndef TASK_H
#define TASK_H
@ -131,6 +137,10 @@ typedef struct xTIME_OUT
*/
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
/* Definitions returned by xTaskGetSchedulerState(). */
#define taskSCHEDULER_NOT_STARTED 0
#define taskSCHEDULER_RUNNING 1
#define taskSCHEDULER_SUSPENDED 2
/*-----------------------------------------------------------
* TASK CREATION API
@ -940,7 +950,7 @@ void vTaskSetTimeOutState( xTimeOutType *pxTimeOut );
* Compare the time status now with that previously captured to see if the
* timeout has expired.
*/
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait );
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait );
/*
* Shortcut used by the queue implementation to prevent unnecessary call to
@ -948,6 +958,12 @@ portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTic
*/
void vTaskMissedYield( void );
/*
* Returns the scheduler state as taskSCHEDULER_RUNNING,
* taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED.
*/
portBASE_TYPE xTaskGetSchedulerState( void );
#endif /* TASK_H */

View File

@ -196,6 +196,16 @@ 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>
@ -236,6 +246,10 @@ Changes from V4.1.3
#define INCLUDE_xTaskResumeFromISR 1
#endif
#ifndef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 0
#endif
/*
* Task control block. A task control block (TCB) is allocated to each task,
* and stores the context of the task.
@ -486,6 +500,16 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
#endif
/*
* Checks that a task being resumed (unsuspended) is actually in the Suspended
* state.
*/
#if ( INCLUDE_vTaskSuspend == 1 )
static portBASE_TYPE prvIsTaskSuspended( const tskTCB * const pxTCB );
#endif
/*lint +e956 */
@ -936,11 +960,41 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
static portBASE_TYPE prvIsTaskSuspended( const tskTCB * const pxTCB )
{
portBASE_TYPE xReturn = pdFALSE;
/* Is the task we are attempting to resume actually in the
suspended list? */
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
{
/* Is it in the suspended list because it is in the
Suspended state? It is possible to be in the suspended
list because it is blocked on a task with no timeout
specified. */
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdTRUE )
{
xReturn = pdTRUE;
}
}
}
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
void vTaskResume( xTaskHandle pxTaskToResume )
{
tskTCB *pxTCB;
const tskTCB *pxTCB;
/* Remove the task from whichever list it is currently in, and place
it in the ready list. */
@ -952,11 +1006,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
{
taskENTER_CRITICAL();
{
/* Is the task we are attempting to resume actually suspended? */
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
if( prvIsTaskSuspended( pxTCB ) == pdTRUE )
{
/* As we are in a critical section we can access the ready
lists even if the scheduler is suspended. */
@ -972,7 +1022,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
}
}
}
}
taskEXIT_CRITICAL();
}
}
@ -986,15 +1035,11 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
{
portBASE_TYPE xYieldRequired = pdFALSE;
tskTCB *pxTCB;
const tskTCB *pxTCB;
pxTCB = ( tskTCB * ) pxTaskToResume;
/* Is the task we are attempting to resume actually suspended? */
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
if( prvIsTaskSuspended( pxTCB ) == pdTRUE )
{
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
@ -1010,7 +1055,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
}
}
return xYieldRequired;
}
@ -1385,14 +1429,6 @@ inline void vTaskIncrementTick( void )
prvDeleteTCB( ( tskTCB * ) pxTCB );
}
while( !listLIST_IS_EMPTY( &xPendingReadyList ) )
{
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xPendingReadyList );
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
prvDeleteTCB( ( tskTCB * ) pxTCB );
}
}
#endif
@ -1545,10 +1581,21 @@ void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )
}
/*-----------------------------------------------------------*/
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait )
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait )
{
portBASE_TYPE xReturn;
#if ( INCLUDE_vTaskSuspend == 1 )
/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
the maximum block time then the task should block indefinitely, and
therefore never time out. */
if( *pxTicksToWait == portMAX_DELAY )
{
xReturn = pdFALSE;
}
else /* We are not blocking indefinitely, perform the checks below. */
#endif
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xTickCount >= pxTimeOut->xTimeOnEntering ) )
{
/* The tick count is greater than the time at which vTaskSetTimeout()
@ -1857,7 +1904,33 @@ tskTCB *pxNewTCB;
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_xTaskGetSchedulerState == 1 )
portBASE_TYPE xTaskGetSchedulerState( void )
{
portBASE_TYPE xReturn;
if( xSchedulerRunning == pdFALSE )
{
xReturn = taskSCHEDULER_NOT_STARTED;
}
else
{
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
xReturn = taskSCHEDULER_RUNNING;
}
else
{
xReturn = taskSCHEDULER_SUSPENDED;
}
}
return xReturn;
}
#endif