mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01: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"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef GCC_ARM7_ECLIPSE
 | 
			
		||||
	#include "portmacro.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ROWLEY_LPC23xx
 | 
			
		||||
	#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										169
									
								
								Source/tasks.c
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								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 <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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user