mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
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:
parent
94c94d3c0e
commit
7a8eb507a7
|
@ -84,6 +84,10 @@
|
||||||
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
|
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GCC_ARM7_ECLIPSE
|
||||||
|
#include "portmacro.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ROWLEY_LPC23xx
|
#ifdef ROWLEY_LPC23xx
|
||||||
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
|
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,6 +33,12 @@
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes since V4.3.1:
|
||||||
|
|
||||||
|
+ Added xTaskGetSchedulerState() function.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef TASK_H
|
#ifndef TASK_H
|
||||||
#define TASK_H
|
#define TASK_H
|
||||||
|
|
||||||
|
@ -131,6 +137,10 @@ typedef struct xTIME_OUT
|
||||||
*/
|
*/
|
||||||
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
|
#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
|
* TASK CREATION API
|
||||||
|
@ -940,7 +950,7 @@ void vTaskSetTimeOutState( xTimeOutType *pxTimeOut );
|
||||||
* Compare the time status now with that previously captured to see if the
|
* Compare the time status now with that previously captured to see if the
|
||||||
* timeout has expired.
|
* 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
|
* 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 );
|
void vTaskMissedYield( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the scheduler state as taskSCHEDULER_RUNNING,
|
||||||
|
* taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED.
|
||||||
|
*/
|
||||||
|
portBASE_TYPE xTaskGetSchedulerState( void );
|
||||||
|
|
||||||
#endif /* TASK_H */
|
#endif /* TASK_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
165
Source/tasks.c
165
Source/tasks.c
|
@ -196,6 +196,16 @@ Changes from V4.1.3
|
||||||
+ Very small change made to xTaskCheckForTimeout() as a result of the
|
+ Very small change made to xTaskCheckForTimeout() as a result of the
|
||||||
SafeRTOS testing. This corrects the case where the function can return an
|
SafeRTOS testing. This corrects the case where the function can return an
|
||||||
invalid value - but only in an extremely unlikely scenario.
|
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 <stdio.h>
|
||||||
|
@ -236,6 +246,10 @@ Changes from V4.1.3
|
||||||
#define INCLUDE_xTaskResumeFromISR 1
|
#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,
|
* Task control block. A task control block (TCB) is allocated to each task,
|
||||||
* and stores the context of the task.
|
* and stores the context of the task.
|
||||||
|
@ -486,6 +500,16 @@ static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth );
|
||||||
|
|
||||||
#endif
|
#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 */
|
/*lint +e956 */
|
||||||
|
|
||||||
|
|
||||||
|
@ -936,11 +960,41 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
#endif
|
#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 )
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||||
|
|
||||||
void vTaskResume( xTaskHandle pxTaskToResume )
|
void vTaskResume( xTaskHandle pxTaskToResume )
|
||||||
{
|
{
|
||||||
tskTCB *pxTCB;
|
const tskTCB *pxTCB;
|
||||||
|
|
||||||
/* Remove the task from whichever list it is currently in, and place
|
/* Remove the task from whichever list it is currently in, and place
|
||||||
it in the ready list. */
|
it in the ready list. */
|
||||||
|
@ -952,24 +1006,19 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
{
|
{
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
/* Is the task we are attempting to resume actually suspended? */
|
if( prvIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||||
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
|
|
||||||
{
|
{
|
||||||
/* Has the task already been resumed from within an ISR? */
|
/* As we are in a critical section we can access the ready
|
||||||
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
|
lists even if the scheduler is suspended. */
|
||||||
{
|
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||||
/* As we are in a critical section we can access the ready
|
prvAddTaskToReadyQueue( pxTCB );
|
||||||
lists even if the scheduler is suspended. */
|
|
||||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
|
||||||
prvAddTaskToReadyQueue( pxTCB );
|
|
||||||
|
|
||||||
/* We may have just resumed a higher priority task. */
|
/* We may have just resumed a higher priority task. */
|
||||||
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
|
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
|
||||||
{
|
{
|
||||||
/* This yield may not cause the task just resumed to run, but
|
/* This yield may not cause the task just resumed to run, but
|
||||||
will leave the lists in the correct state for the next yield. */
|
will leave the lists in the correct state for the next yield. */
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -986,29 +1035,24 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
|
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
|
||||||
{
|
{
|
||||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||||
tskTCB *pxTCB;
|
const tskTCB *pxTCB;
|
||||||
|
|
||||||
pxTCB = ( tskTCB * ) pxTaskToResume;
|
pxTCB = ( tskTCB * ) pxTaskToResume;
|
||||||
|
|
||||||
/* Is the task we are attempting to resume actually suspended? */
|
if( prvIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||||
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
|
|
||||||
{
|
{
|
||||||
/* Has the task already been resumed from within an ISR? */
|
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||||
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
|
|
||||||
{
|
{
|
||||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
|
||||||
{
|
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||||
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
|
prvAddTaskToReadyQueue( pxTCB );
|
||||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
}
|
||||||
prvAddTaskToReadyQueue( pxTCB );
|
else
|
||||||
}
|
{
|
||||||
else
|
/* We cannot access the delayed or ready lists, so will hold this
|
||||||
{
|
task pending until the scheduler is resumed, at which point a
|
||||||
/* We cannot access the delayed or ready lists, so will hold this
|
yield will be preformed if necessary. */
|
||||||
task pending until the scheduler is resumed, at which point a
|
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
||||||
yield will be preformed if necessary. */
|
|
||||||
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1385,14 +1429,6 @@ inline void vTaskIncrementTick( void )
|
||||||
|
|
||||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||||
}
|
}
|
||||||
|
|
||||||
while( !listLIST_IS_EMPTY( &xPendingReadyList ) )
|
|
||||||
{
|
|
||||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xPendingReadyList );
|
|
||||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
|
||||||
|
|
||||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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;
|
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 ) )
|
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()
|
||||||
|
@ -1857,7 +1904,33 @@ tskTCB *pxNewTCB;
|
||||||
|
|
||||||
#endif
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue