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>
@ -234,7 +244,11 @@ Changes from V4.1.3
#ifndef INCLUDE_xTaskResumeFromISR
#define INCLUDE_xTaskResumeFromISR 1
#endif
#endif
#ifndef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 0
#endif
/*
* Task control block. A task control block (TCB) is allocated to each 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,24 +1006,19 @@ 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 )
if( prvIsTaskSuspended( pxTCB ) == pdTRUE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
{
/* As we are in a critical section we can access the ready
lists even if the scheduler is suspended. */
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
/* As we are in a critical section we can access the ready
lists even if the scheduler is suspended. */
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
/* We may have just resumed a higher priority task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
/* This yield may not cause the task just resumed to run, but
will leave the lists in the correct state for the next yield. */
taskYIELD();
}
/* We may have just resumed a higher priority task. */
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
{
/* This yield may not cause the task just resumed to run, but
will leave the lists in the correct state for the next yield. */
taskYIELD();
}
}
}
@ -986,29 +1035,24 @@ 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 )
if( prvIsTaskSuspended( pxTCB ) == pdTRUE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
{
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
}
else
{
/* We cannot access the delayed or ready lists, so will hold this
task pending until the scheduler is resumed, at which point a
yield will be preformed if necessary. */
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
vListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyQueue( pxTCB );
}
else
{
/* We cannot access the delayed or ready lists, so will hold this
task pending until the scheduler is resumed, at which point a
yield will be preformed if necessary. */
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
}
@ -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,13 +1581,24 @@ 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()
/* The tick count is greater than the time at which vTaskSetTimeout()
was called, but has also overflowed since vTaskSetTimeOut() was called.
It must have wrapped all the way around and gone past us again. This
passed since vTaskSetTimeout() was called. */
@ -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