+ Very small change made to xTaskCheckForTimeout() as a result of the \r
SafeRTOS testing. This corrects the case where the function can return an\r
invalid value - but only in an extremely unlikely scenario.\r
+\r
+Changes since V4.3.1:\r
+\r
+ + Added xTaskGetSchedulerState() function.\r
+ + Added prvIsTaskSuspended() to take into account the Occurrence of\r
+ vTaskResume() or vTaskResumeFromISR() being called passing in the\r
+ handle of a task that appears in the Suspended list only because it\r
+ is blocked on an event without a timeout being specified.\r
+ + Updated xTaskCheckForTimeout() to take into account that tasks blocked\r
+ using the Suspended list should never time out.\r
*/\r
\r
#include <stdio.h>\r
\r
#ifndef INCLUDE_xTaskResumeFromISR\r
#define INCLUDE_xTaskResumeFromISR 1\r
-#endif \r
+#endif\r
+\r
+#ifndef INCLUDE_xTaskGetSchedulerState\r
+ #define INCLUDE_xTaskGetSchedulerState 0\r
+#endif\r
\r
/*\r
* Task control block. A task control block (TCB) is allocated to each task,\r
\r
#endif\r
\r
+/*\r
+ * Checks that a task being resumed (unsuspended) is actually in the Suspended\r
+ * state.\r
+ */\r
+#if ( INCLUDE_vTaskSuspend == 1 )\r
+\r
+ static portBASE_TYPE prvIsTaskSuspended( const tskTCB * const pxTCB ); \r
+\r
+#endif\r
+\r
/*lint +e956 */\r
\r
\r
#endif\r
/*-----------------------------------------------------------*/\r
\r
+#if ( INCLUDE_vTaskSuspend == 1 )\r
+\r
+ static portBASE_TYPE prvIsTaskSuspended( const tskTCB * const pxTCB )\r
+ {\r
+ portBASE_TYPE xReturn = pdFALSE;\r
+\r
+ /* Is the task we are attempting to resume actually in the\r
+ suspended list? */\r
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
+ {\r
+ /* Has the task already been resumed from within an ISR? */\r
+ if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )\r
+ { \r
+ /* Is it in the suspended list because it is in the\r
+ Suspended state? It is possible to be in the suspended\r
+ list because it is blocked on a task with no timeout\r
+ specified. */\r
+ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdTRUE )\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
#if ( INCLUDE_vTaskSuspend == 1 )\r
\r
void vTaskResume( xTaskHandle pxTaskToResume )\r
{\r
- tskTCB *pxTCB;\r
+ const tskTCB *pxTCB;\r
\r
/* Remove the task from whichever list it is currently in, and place\r
it in the ready list. */\r
{\r
taskENTER_CRITICAL();\r
{\r
- /* Is the task we are attempting to resume actually suspended? */\r
- if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
+ if( prvIsTaskSuspended( pxTCB ) == pdTRUE )\r
{\r
- /* Has the task already been resumed from within an ISR? */\r
- if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )\r
- { \r
- /* As we are in a critical section we can access the ready \r
- lists even if the scheduler is suspended. */\r
- vListRemove( &( pxTCB->xGenericListItem ) );\r
- prvAddTaskToReadyQueue( pxTCB );\r
-\r
- /* We may have just resumed a higher priority task. */\r
- if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
- {\r
- /* This yield may not cause the task just resumed to run, but\r
- will leave the lists in the correct state for the next yield. */\r
- taskYIELD();\r
- }\r
+ /* As we are in a critical section we can access the ready\r
+ lists even if the scheduler is suspended. */\r
+ vListRemove( &( pxTCB->xGenericListItem ) );\r
+ prvAddTaskToReadyQueue( pxTCB );\r
+\r
+ /* We may have just resumed a higher priority task. */\r
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
+ {\r
+ /* This yield may not cause the task just resumed to run, but\r
+ will leave the lists in the correct state for the next yield. */\r
+ taskYIELD();\r
}\r
}\r
}\r
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )\r
{\r
portBASE_TYPE xYieldRequired = pdFALSE;\r
- tskTCB *pxTCB;\r
+ const tskTCB *pxTCB;\r
\r
pxTCB = ( tskTCB * ) pxTaskToResume;\r
\r
- /* Is the task we are attempting to resume actually suspended? */\r
- if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
+ if( prvIsTaskSuspended( pxTCB ) == pdTRUE )\r
{\r
- /* Has the task already been resumed from within an ISR? */\r
- if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )\r
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
{\r
- if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
- {\r
- xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );\r
- vListRemove( &( pxTCB->xGenericListItem ) ); \r
- prvAddTaskToReadyQueue( pxTCB );\r
- }\r
- else\r
- {\r
- /* We cannot access the delayed or ready lists, so will hold this\r
- task pending until the scheduler is resumed, at which point a \r
- yield will be preformed if necessary. */\r
- vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
- }\r
+ xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );\r
+ vListRemove( &( pxTCB->xGenericListItem ) ); \r
+ prvAddTaskToReadyQueue( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ /* We cannot access the delayed or ready lists, so will hold this\r
+ task pending until the scheduler is resumed, at which point a\r
+ yield will be preformed if necessary. */\r
+ vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
}\r
}\r
\r
\r
prvDeleteTCB( ( tskTCB * ) pxTCB );\r
} \r
-\r
- while( !listLIST_IS_EMPTY( &xPendingReadyList ) )\r
- {\r
- listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xPendingReadyList );\r
- vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );\r
-\r
- prvDeleteTCB( ( tskTCB * ) pxTCB );\r
- } \r
}\r
\r
#endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
-portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType *pxTicksToWait )\r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait )\r
{\r
portBASE_TYPE xReturn;\r
\r
+ #if ( INCLUDE_vTaskSuspend == 1 )\r
+ /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is\r
+ the maximum block time then the task should block indefinitely, and\r
+ therefore never time out. */\r
+ if( *pxTicksToWait == portMAX_DELAY )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else /* We are not blocking indefinitely, perform the checks below. */\r
+ #endif\r
+\r
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xTickCount >= pxTimeOut->xTimeOnEntering ) )\r
{\r
- /* The tick count is greater than the time at which vTaskSetTimeout() \r
+ /* The tick count is greater than the time at which vTaskSetTimeout()\r
was called, but has also overflowed since vTaskSetTimeOut() was called.\r
It must have wrapped all the way around and gone past us again. This\r
passed since vTaskSetTimeout() was called. */\r
\r
#endif\r
\r
+/*-----------------------------------------------------------*/\r
\r
+#if ( INCLUDE_xTaskGetSchedulerState == 1 )\r
\r
+ portBASE_TYPE xTaskGetSchedulerState( void )\r
+ {\r
+ portBASE_TYPE xReturn;\r
+ \r
+ if( xSchedulerRunning == pdFALSE )\r
+ {\r
+ xReturn = taskSCHEDULER_NOT_STARTED;\r
+ }\r
+ else\r
+ {\r
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
+ {\r
+ xReturn = taskSCHEDULER_RUNNING;\r
+ }\r
+ else\r
+ {\r
+ xReturn = taskSCHEDULER_SUSPENDED;\r
+ }\r
+ }\r
+ \r
+ return xReturn;\r
+ }\r
+\r
+#endif\r
\r
\r