//////////////////////////////////////////////////////////////////////// ///The existing API and corrected version is given in each case /// //////////////////////////////////////////////////////////////////////// /*-----------------------------------------------------------*/ signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) { signed portBASE_TYPE xReturn; tskTCB * pxNewTCB; /* Allocate the memory required by the TCB and stack for the new task, checking that the allocation was successful. */ pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); if( pxNewTCB != NULL ) { portSTACK_TYPE *pxTopOfStack; #if( portUSING_MPU_WRAPPERS == 1 ) /* Should the task be created in privileged mode? */ portBASE_TYPE xRunPrivileged; if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 ) { xRunPrivileged = pdTRUE; } else { xRunPrivileged = pdFALSE; } uxPriority &= ~portPRIVILEGE_BIT; #endif /* portUSING_MPU_WRAPPERS == 1 */ /* Calculate the top of stack address. This depends on whether the stack grows from high memory to low (as per the 80x86) or visa versa. portSTACK_GROWTH is used to make the result positive or negative as required by the port. */ #if( portSTACK_GROWTH < 0 ) { pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) ); } #else { pxTopOfStack = pxNewTCB->pxStack; /* If we want to use stack checking on architectures that use a positive stack growth direction then we also need to store the other extreme of the stack space. */ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); } #endif /* Setup the newly allocated TCB with the initial state of the task. */ prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); /* Initialize the TCB stack to look as if the task was already running, but had been interrupted by the scheduler. The return address is set to the start of the task function. Once the stack has been initialised the top of stack variable is updated. */ #if( portUSING_MPU_WRAPPERS == 1 ) { pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); } #else { pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); } #endif /* We are going to manipulate the task queues to add this task to a ready list, so must make sure no interrupts occur. */ portENTER_CRITICAL(); { uxCurrentNumberOfTasks++; if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) { /* As this is the first task it must also be the current task. */ pxCurrentTCB = pxNewTCB; /* This is the first task to be created so do the preliminary initialisation required. We will not recover if this call fails, but we will report the failure. */ prvInitialiseTaskLists(); } else { /* If the scheduler is not already running, make this task the current task if it is the highest priority task to be created so far. */ if( xSchedulerRunning == pdFALSE ) { if( pxCurrentTCB->uxPriority <= uxPriority ) { pxCurrentTCB = pxNewTCB; } } } /* Remember the top priority to make context switching faster. Use the priority in pxNewTCB as this has been capped to a valid value. */ if( pxNewTCB->uxPriority > uxTopUsedPriority ) { uxTopUsedPriority = pxNewTCB->uxPriority; } #if ( configUSE_TRACE_FACILITY == 1 ) { /* Add a counter into the TCB for tracing only. */ pxNewTCB->uxTCBNumber = uxTaskNumber; } #endif uxTaskNumber++; prvAddTaskToReadyQueue( pxNewTCB ); xReturn = pdPASS; traceTASK_CREATE( pxNewTCB ); } portEXIT_CRITICAL(); } else { xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; traceTASK_CREATE_FAILED( pxNewTCB ); } if( xReturn == pdPASS ) { if( ( void * ) pxCreatedTask != NULL ) { /* Pass the TCB out - in an anonymous way. The calling function/ task can use this as a handle to delete the task later if required.*/ *pxCreatedTask = ( xTaskHandle ) pxNewTCB; } if( xSchedulerRunning != pdFALSE ) { /* If the created task is of a higher priority than the current task then it should run now. */ if( pxCurrentTCB->uxPriority < uxPriority ) { portYIELD_WITHIN_API(); } } } return xReturn; } /*-----------------------------------------------------------*/ signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) { signed portBASE_TYPE xReturn; tskTCB * pxNewTCB; /* Allocate the memory required by the TCB and stack for the new task, checking that the allocation was successful. */ pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); if( pxNewTCB != NULL ) { portSTACK_TYPE *pxTopOfStack; #if( portUSING_MPU_WRAPPERS == 1 ) /* Should the task be created in privileged mode? */ portBASE_TYPE xRunPrivileged; if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 ) { xRunPrivileged = pdTRUE; } else { xRunPrivileged = pdFALSE; } uxPriority &= ~portPRIVILEGE_BIT; #endif /* portUSING_MPU_WRAPPERS == 1 */ /* Calculate the top of stack address. This depends on whether the stack grows from high memory to low (as per the 80x86) or visa versa. portSTACK_GROWTH is used to make the result positive or negative as required by the port. */ #if( portSTACK_GROWTH < 0 ) { pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) ); } #else { pxTopOfStack = pxNewTCB->pxStack; /* If we want to use stack checking on architectures that use a positive stack growth direction then we also need to store the other extreme of the stack space. */ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); } #endif /* Setup the newly allocated TCB with the initial state of the task. */ prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); /* Initialize the TCB stack to look as if the task was already running, but had been interrupted by the scheduler. The return address is set to the start of the task function. Once the stack has been initialised the top of stack variable is updated. */ #if( portUSING_MPU_WRAPPERS == 1 ) { pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); } #else { pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); } #endif /* We are going to manipulate the task queues to add this task to a ready list, so must make sure no interrupts occur. */ portENTER_CRITICAL(); { uxCurrentNumberOfTasks++; if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) { /* As this is the first task it must also be the current task. */ pxCurrentTCB = pxNewTCB; /* This is the first task to be created so do the preliminary initialisation required. We will not recover if this call fails, but we will report the failure. */ prvInitialiseTaskLists(); } else { /* If the scheduler is not already running, make this task the current task if it is the highest priority task to be created so far. */ if( xSchedulerRunning == pdFALSE ) { //////////////////////////////////////////////////////////////////////// ///The operator in the following condition is changed to fix a bug /// //////////////////////////////////////////////////////////////////////// if( pxCurrentTCB->uxPriority < uxPriority ) { pxCurrentTCB = pxNewTCB; } } } /* Remember the top priority to make context switching faster. Use the priority in pxNewTCB as this has been capped to a valid value. */ if( pxNewTCB->uxPriority > uxTopUsedPriority ) { uxTopUsedPriority = pxNewTCB->uxPriority; } #if ( configUSE_TRACE_FACILITY == 1 ) { /* Add a counter into the TCB for tracing only. */ pxNewTCB->uxTCBNumber = uxTaskNumber; } #endif uxTaskNumber++; prvAddTaskToReadyQueue( pxNewTCB ); xReturn = pdPASS; traceTASK_CREATE( pxNewTCB ); } portEXIT_CRITICAL(); } else { xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; traceTASK_CREATE_FAILED( pxNewTCB ); } if( xReturn == pdPASS ) { if( ( void * ) pxCreatedTask != NULL ) { /* Pass the TCB out - in an anonymous way. The calling function/ task can use this as a handle to delete the task later if required.*/ *pxCreatedTask = ( xTaskHandle ) pxNewTCB; } if( xSchedulerRunning != pdFALSE ) { /* If the created task is of a higher priority than the current task then it should run now. */ if( pxCurrentTCB->uxPriority < uxPriority ) { portYIELD_WITHIN_API(); } } } return xReturn; } /*-----------------------------------------------------------*/ void vTaskSwitchContext( void ) { if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context switch. */ xMissedYield = pdTRUE; return; } traceTASK_SWITCHED_OUT(); #if ( configGENERATE_RUN_TIME_STATS == 1 ) { unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); /* Add the amount of time the task has been running to the accumulated time so far. The time the task started running was stored in ulTaskSwitchedInTime. Note that there is no overflow protection here so count values are only valid until the timer overflows. Generally this will be about 1 hour assuming a 1uS timer increment. */ pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); ulTaskSwitchedInTime = ulTempCounter; } #endif taskFIRST_CHECK_FOR_STACK_OVERFLOW(); taskSECOND_CHECK_FOR_STACK_OVERFLOW(); /* Find the highest priority queue that contains ready tasks. */ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) { --uxTopReadyPriority; } /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the same priority get an equal share of the processor time. */ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); traceTASK_SWITCHED_IN(); vWriteTraceToBuffer(); } /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ void vTaskSwitchContext( void ) { //////////////////////////////////////////////////////////////////////// ///Following variable is added to change the code to fix a bug /// ///We need to use the list operation list_GET_OWNER_OF_FIRST_ENTRY /// ///to preempt a task (schedule a task from a queue different than /// ///the queue for running task. /// ///To schedule a task from the queue for running task, we /// ///need to use the list operations /// ///list_ROTATE_LEFT followed by list_GET_OWNER_OF_FIRST_ENTRY /// //////////////////////////////////////////////////////////////////////// signed portBASE_TYPE preemt = pdTRUE; // true for preemt ///////////////////////////////////////////////// if ( ( pxCurrentTCB->uxPriority == uxTopReadyPriority ) && ( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) ) { preemt = pdFALSE; } //////////////////////////////////////////////////////////////////////// ///The above statement decides whether we need to do a preemption /// ///or context switch /// //////////////////////////////////////////////////////////////////////// if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context switch. */ xMissedYield = pdTRUE; return; } traceTASK_SWITCHED_OUT(); #if ( configGENERATE_RUN_TIME_STATS == 1 ) { unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); /* Add the amount of time the task has been running to the accumulated time so far. The time the task started running was stored in ulTaskSwitchedInTime. Note that there is no overflow protection here so count values are only valid until the timer overflows. Generally this will be about 1 hour assuming a 1uS timer increment. */ pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); ulTaskSwitchedInTime = ulTempCounter; } #endif taskFIRST_CHECK_FOR_STACK_OVERFLOW(); taskSECOND_CHECK_FOR_STACK_OVERFLOW(); /* Find the highest priority queue that contains ready tasks. */ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) { --uxTopReadyPriority; } /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the same priority get an equal share of the processor time. */ // listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); //////////////////////////////////////////////////////////////////////// ///The above statement is replaced with the following three /// ///statements to do a preemtion or just context switch /// //////////////////////////////////////////////////////////////////////// if( preempt == pdTRUE ) { list_ROTATE_LEFT( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); } list_GET_OWNER_OF_FIRST_ENTRY(pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); traceTASK_SWITCHED_IN(); vWriteTraceToBuffer(); } /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskPrioritySet == 1 ) void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) { tskTCB *pxTCB; unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE; /* Ensure the new priority is valid. */ if( uxNewPriority >= configMAX_PRIORITIES ) { uxNewPriority = configMAX_PRIORITIES - 1; } portENTER_CRITICAL(); { if( pxTask == pxCurrentTCB ) { pxTask = NULL; } /* If null is passed in here then we are changing the priority of the calling function. */ pxTCB = prvGetTCBFromHandle( pxTask ); traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); #if ( configUSE_MUTEXES == 1 ) { uxCurrentPriority = pxTCB->uxBasePriority; } #else { uxCurrentPriority = pxTCB->uxPriority; } #endif if( uxCurrentPriority != uxNewPriority ) { /* The priority change may have readied a task of higher priority than the calling task. */ if( uxNewPriority > uxCurrentPriority ) { if( pxTask != NULL ) { /* The priority of another task is being raised. If we were raising the priority of the currently running task there would be no need to switch as it must have already been the highest priority task. */ xYieldRequired = pdTRUE; } } else if( pxTask == NULL ) { /* Setting our own priority down means there may now be another task of higher priority that is ready to execute. */ xYieldRequired = pdTRUE; } #if ( configUSE_MUTEXES == 1 ) { /* Only change the priority being used if the task is not currently using an inherited priority. */ if( pxTCB->uxBasePriority == pxTCB->uxPriority ) { pxTCB->uxPriority = uxNewPriority; } /* The base priority gets set whatever. */ pxTCB->uxBasePriority = uxNewPriority; } #else { pxTCB->uxPriority = uxNewPriority; } #endif listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /* If the task is in the blocked or suspended list we need do nothing more than change it's priority variable. However, if the task is in a ready list it needs to be removed and placed in the queue appropriate to its new priority. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) { /* The task is currently in its ready list - remove before adding it to it's new ready list. As we are in a critical section we can do this even if the scheduler is suspended. */ vListRemove( &( pxTCB->xGenericListItem ) ); prvAddTaskToReadyQueue( pxTCB ); } if( xYieldRequired == pdTRUE ) { portYIELD_WITHIN_API(); } } } portEXIT_CRITICAL(); } #endif /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskPrioritySet == 1 ) void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) { tskTCB *pxTCB; unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE; /* Ensure the new priority is valid. */ if( uxNewPriority >= configMAX_PRIORITIES ) { uxNewPriority = configMAX_PRIORITIES - 1; } portENTER_CRITICAL(); { if( pxTask == pxCurrentTCB ) { pxTask = NULL; } /* If null is passed in here then we are changing the priority of the calling function. */ pxTCB = prvGetTCBFromHandle( pxTask ); traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); #if ( configUSE_MUTEXES == 1 ) { uxCurrentPriority = pxTCB->uxBasePriority; } #else { uxCurrentPriority = pxTCB->uxPriority; } #endif if( uxCurrentPriority != uxNewPriority ) { /* The priority change may have readied a task of higher priority than the calling task. */ if( uxNewPriority > uxCurrentPriority ) { if( pxTask != NULL ) { /* The priority of another task is being raised. If we were raising the priority of the currently running task there would be no need to switch as it must have already been the highest priority task. */ xYieldRequired = pdTRUE; } } else if( pxTask == NULL ) { /* Setting our own priority down means there may now be another task of higher priority that is ready to execute. */ xYieldRequired = pdTRUE; } #if ( configUSE_MUTEXES == 1 ) { /* Only change the priority being used if the task is not currently using an inherited priority. */ if( pxTCB->uxBasePriority == pxTCB->uxPriority ) { pxTCB->uxPriority = uxNewPriority; } /* The base priority gets set whatever. */ pxTCB->uxBasePriority = uxNewPriority; } #else { pxTCB->uxPriority = uxNewPriority; } #endif //////////////////////////////////////////////////////////////////////// ///Following statement lead to an error if the node is present in /// ///the waiting queue for a resource. Hence the node is removed, /// ///value set, and reinserted /// //////////////////////////////////////////////////////////////////////// //listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); if( listIS_CONTAINED_WITHIN( ( &pxTCB->xGenericListItem )->pvContainer, &( pxTCB->xEventListItem ) ) ) { vListRemove( &( pxTCB->xGenericListItem ) ); listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); vListInsert( ( &pxTCB->xGenericListItem )->pvContainer,&( pxTCB->xEventListItem ) ); } else { listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); } //////////////////////////////////////////////////////////////////////// /// /// /// /// /// /// //////////////////////////////////////////////////////////////////////// /* If the task is in the blocked or suspended list we need do nothing more than change it's priority variable. However, if the task is in a ready list it needs to be removed and placed in the queue appropriate to its new priority. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) { /* The task is currently in its ready list - remove before adding it to it's new ready list. As we are in a critical section we can do this even if the scheduler is suspended. */ vListRemove( &( pxTCB->xGenericListItem ) ); prvAddTaskToReadyQueue( pxTCB ); } if( xYieldRequired == pdTRUE ) { portYIELD_WITHIN_API(); } } } portEXIT_CRITICAL(); } #endif /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) { tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) { /* Adjust the mutex holder state to account for its new priority. */ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /* If the task being modified is in the ready state it will need to be moved in to a new list. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) ) { vListRemove( &( pxTCB->xGenericListItem ) ); /* Inherit the priority before being moved into the new list. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; prvAddTaskToReadyQueue( pxTCB ); } else { /* Just inherit the priority. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; } } } #endif /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) { tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) { /* Adjust the mutex holder state to account for its new priority. */ //////////////////////////////////////////////////////////////////////// ///Following statement lead to an error if the node is present in /// ///the waiting queue for a resource. Hence the node is removed, /// ///value set, and reinserted /// //////////////////////////////////////////////////////////////////////// //listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); if( listIS_CONTAINED_WITHIN( ( &pxTCB->xGenericListItem )->pvContainer, &( pxTCB->xEventListItem ) ) ) { vListRemove( &( pxTCB->xGenericListItem ) ); listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); vListInsert( ( &pxTCB->xGenericListItem )->pvContainer,&( pxTCB->xEventListItem ) ); } else { listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); } //////////////////////////////////////////////////////////////////////// /// /// /// /// /// /// //////////////////////////////////////////////////////////////////////// /* If the task being modified is in the ready state it will need to be moved in to a new list. */ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) ) { vListRemove( &( pxTCB->xGenericListItem ) ); /* Inherit the priority before being moved into the new list. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; prvAddTaskToReadyQueue( pxTCB ); } else { /* Just inherit the priority. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; } } } #endif /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) { portBASE_TYPE xReturn = pdFALSE; const tskTCB * const pxTCB = ( tskTCB * ) xTask; /* 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 vTaskSuspend( xTaskHandle pxTaskToSuspend ) { tskTCB *pxTCB; portENTER_CRITICAL(); { /* Ensure a yield is performed if the current task is being suspended. */ if( pxTaskToSuspend == pxCurrentTCB ) { pxTaskToSuspend = NULL; } /* If null is passed in here then we are suspending ourselves. */ pxTCB = prvGetTCBFromHandle( pxTaskToSuspend ); //////////////////////////////////////////////////////////////////////// ///Suspending a task while it is in delayed or blocked state leads /// ///to some problems. Hence the code is changed so that a task will /// ///be suspended only if it is in ready state /// //////////////////////////////////////////////////////////////////////// if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) ) { traceTASK_SUSPEND( pxTCB ); /* Remove task from the ready/delayed list and place in the suspended list. */ vListRemove( &( pxTCB->xGenericListItem ) ); //////////////////////////////////////////////////////////////////////// ///The following if condition is always false in the modified code /// ///hence the statement is commented /// //////////////////////////////////////////////////////////////////////// /* Is the task waiting on an event also? if( pxTCB->xEventListItem.pvContainer ) { vListRemove( &( pxTCB->xEventListItem ) ); } */ vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); } //////////////////////////////////////////////////////////////////////// ///Suspending a task while it is in delayed or blocked state leads /// ///to some problems. Hence the code is changed so that a task will /// ///be suspended only if it is in ready state /// //////////////////////////////////////////////////////////////////////// } portEXIT_CRITICAL(); /* We may have just suspended the current task. */ if( ( void * ) pxTaskToSuspend == NULL ) { portYIELD_WITHIN_API(); } } #endif /*-----------------------------------------------------------*/