From f9ed98af699a56ddc99d146feb5782fe3782a81b Mon Sep 17 00:00:00 2001 From: RichardBarry Date: Sat, 28 Jul 2007 16:33:07 +0000 Subject: [PATCH] Modifications to correct behaviour when a task is blocked without specifying a wake time, and also introduce the xTaskGetSchedulerState() function. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@97 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/include/portable.h | 4 + Source/include/task.h | 18 +++- Source/tasks.c | 167 +++++++++++++++++++++++++++----------- 3 files changed, 141 insertions(+), 48 deletions(-) diff --git a/Source/include/portable.h b/Source/include/portable.h index 06f290a71..04c8ec1e5 100644 --- a/Source/include/portable.h +++ b/Source/include/portable.h @@ -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 diff --git a/Source/include/task.h b/Source/include/task.h index 888fe855c..7a857f3ba 100644 --- a/Source/include/task.h +++ b/Source/include/task.h @@ -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 */ diff --git a/Source/tasks.c b/Source/tasks.c index 76b3d3c3c..4e1261747 100644 --- a/Source/tasks.c +++ b/Source/tasks.c @@ -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 @@ -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 ); - - /* 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(); - } + /* 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(); } } } @@ -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 -- 2.39.5