FreeRTOS source:

- Major refactor to consolidate the multiple places where a task is removed from a ready list and placed in a delay list into a single function, reducing code size, and enabling the easy addition of up-coming functionality.
 - Replace the enum used for task notification states with a uint8_t to reduce the TCB struct size with some compilers, and allow additional members to be added without increasing its size.
 - Rearrange FreeRTOS.h so all INCLUDE_ defaults are grouped together.
This commit is contained in:
Richard Barry 2016-02-10 12:58:15 +00:00
parent 42e73b9b8f
commit 2acc8f2c99
4 changed files with 234 additions and 418 deletions

View File

@ -56,7 +56,7 @@ extern int uiInEventGroupSetBitsFromISR;
#define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */ #define TRACE_CPU_CLOCK_HZ configCPU_CLOCK_HZ /* Defined in "FreeRTOSConfig.h" */
#if (SELECTED_PORT == PORT_ARM_CortexM) #if (SELECTED_PORT == PORT_ARM_CortexM)
/* Uses CMSIS API */ /* Uses CMSIS API */
#define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status; #define TRACE_SR_ALLOC_CRITICAL_SECTION() int __irq_status;
@ -571,8 +571,8 @@ void* prvTraceGetCurrentTaskHandle(void);
/* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */ /* Called on vTaskDelayUntil - note the use of FreeRTOS variable xTimeToWake */
#undef traceTASK_DELAY_UNTIL #undef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() \ #define traceTASK_DELAY_UNTIL( xTickTimeToWake ) \
trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, xTimeToWake); \ trcKERNEL_HOOKS_TASK_DELAY(TASK_DELAY_UNTIL, pxCurrentTCB, ( xTickTimeToWake)); \
trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED(); trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED();
#if (INCLUDE_OBJECT_DELETE == 1) #if (INCLUDE_OBJECT_DELETE == 1)
@ -819,7 +819,7 @@ else \
#undef traceTASK_NOTIFY_TAKE #undef traceTASK_NOTIFY_TAKE
#define traceTASK_NOTIFY_TAKE() \ #define traceTASK_NOTIFY_TAKE() \
if (pxCurrentTCB->eNotifyState == eNotified) \ if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \
vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_TAKE, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); \ vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_TAKE, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); \
else \ else \
vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_TAKE_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_TAKE_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait);
@ -831,7 +831,7 @@ else \
#undef traceTASK_NOTIFY_WAIT #undef traceTASK_NOTIFY_WAIT
#define traceTASK_NOTIFY_WAIT() \ #define traceTASK_NOTIFY_WAIT() \
if (pxCurrentTCB->eNotifyState == eNotified) \ if (pxCurrentTCB->ucNotifyState == taskNOTIFICATION_RECEIVED) \
vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); \ vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); \
else \ else \
vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait); vTraceStoreKernelCallWithParam(TRACE_TASK_NOTIFY_WAIT_FAILED, TRACE_CLASS_TASK, uxTaskGetTaskNumber(pxCurrentTCB), xTicksToWait);
@ -848,7 +848,7 @@ else \
#undef traceTASK_NOTIFY_FROM_ISR #undef traceTASK_NOTIFY_FROM_ISR
#define traceTASK_NOTIFY_FROM_ISR() \ #define traceTASK_NOTIFY_FROM_ISR() \
vTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTaskToNotify)); vTraceStoreKernelCall(TRACE_TASK_NOTIFY_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTaskToNotify));
#undef traceTASK_NOTIFY_GIVE_FROM_ISR #undef traceTASK_NOTIFY_GIVE_FROM_ISR
#define traceTASK_NOTIFY_GIVE_FROM_ISR() \ #define traceTASK_NOTIFY_GIVE_FROM_ISR() \
vTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTaskToNotify)); vTraceStoreKernelCall(TRACE_TASK_NOTIFY_GIVE_FROM_ISR, TRACE_CLASS_TASK, uxTaskGetTaskNumber(xTaskToNotify));

View File

@ -129,30 +129,6 @@ extern "C" {
#error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#ifndef INCLUDE_vTaskPrioritySet
#error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_uxTaskPriorityGet
#error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskDelete
#error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskSuspend
#error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskDelayUntil
#error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef INCLUDE_vTaskDelay
#error Missing definition: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif
#ifndef configUSE_16_BIT_TICKS #ifndef configUSE_16_BIT_TICKS
#error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
@ -165,20 +141,38 @@ extern "C" {
#define configUSE_CO_ROUTINES 0 #define configUSE_CO_ROUTINES 0
#endif #endif
#if configUSE_CO_ROUTINES != 0 #ifndef INCLUDE_vTaskPrioritySet
#ifndef configMAX_CO_ROUTINE_PRIORITIES #define INCLUDE_vTaskPrioritySet 0
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
#endif
#endif #endif
#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK #ifndef INCLUDE_uxTaskPriorityGet
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 #define INCLUDE_uxTaskPriorityGet 0
#endif
#ifndef INCLUDE_vTaskDelete
#define INCLUDE_vTaskDelete 0
#endif
#ifndef INCLUDE_vTaskSuspend
#define INCLUDE_vTaskSuspend 0
#endif
#ifndef INCLUDE_vTaskDelayUntil
#define INCLUDE_vTaskDelayUntil 0
#endif
#ifndef INCLUDE_vTaskDelay
#define INCLUDE_vTaskDelay 0
#endif #endif
#ifndef INCLUDE_xTaskGetIdleTaskHandle #ifndef INCLUDE_xTaskGetIdleTaskHandle
#define INCLUDE_xTaskGetIdleTaskHandle 0 #define INCLUDE_xTaskGetIdleTaskHandle 0
#endif #endif
#ifndef INCLUDE_xTaskAbortDelay
#define INCLUDE_xTaskAbortDelay 0
#endif
#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle #ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#endif #endif
@ -199,14 +193,6 @@ extern "C" {
#define INCLUDE_xTaskGetTaskHandle 0 #define INCLUDE_xTaskGetTaskHandle 0
#endif #endif
#ifndef configUSE_APPLICATION_TASK_TAG
#define configUSE_APPLICATION_TASK_TAG 0
#endif
#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
#endif
#ifndef INCLUDE_uxTaskGetStackHighWaterMark #ifndef INCLUDE_uxTaskGetStackHighWaterMark
#define INCLUDE_uxTaskGetStackHighWaterMark 0 #define INCLUDE_uxTaskGetStackHighWaterMark 0
#endif #endif
@ -215,6 +201,40 @@ extern "C" {
#define INCLUDE_eTaskGetState 0 #define INCLUDE_eTaskGetState 0
#endif #endif
#ifndef INCLUDE_xTaskResumeFromISR
#define INCLUDE_xTaskResumeFromISR 1
#endif
#ifndef INCLUDE_xTimerPendFunctionCall
#define INCLUDE_xTimerPendFunctionCall 0
#endif
#ifndef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 0
#endif
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#endif
#if configUSE_CO_ROUTINES != 0
#ifndef configMAX_CO_ROUTINE_PRIORITIES
#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
#endif
#endif
#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
#endif
#ifndef configUSE_APPLICATION_TASK_TAG
#define configUSE_APPLICATION_TASK_TAG 0
#endif
#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
#endif
#ifndef configUSE_RECURSIVE_MUTEXES #ifndef configUSE_RECURSIVE_MUTEXES
#define configUSE_RECURSIVE_MUTEXES 0 #define configUSE_RECURSIVE_MUTEXES 0
#endif #endif
@ -251,14 +271,6 @@ extern "C" {
#error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
#endif #endif
#ifndef INCLUDE_xTaskResumeFromISR
#define INCLUDE_xTaskResumeFromISR 1
#endif
#ifndef INCLUDE_xTimerPendFunctionCall
#define INCLUDE_xTimerPendFunctionCall 0
#endif
#ifndef configASSERT #ifndef configASSERT
#define configASSERT( x ) #define configASSERT( x )
#define configASSERT_DEFINED 0 #define configASSERT_DEFINED 0
@ -283,15 +295,6 @@ extern "C" {
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
#ifndef INCLUDE_xTaskGetSchedulerState
#define INCLUDE_xTaskGetSchedulerState 0
#endif
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#endif
#ifndef portSET_INTERRUPT_MASK_FROM_ISR #ifndef portSET_INTERRUPT_MASK_FROM_ISR
#define portSET_INTERRUPT_MASK_FROM_ISR() 0 #define portSET_INTERRUPT_MASK_FROM_ISR() 0
#endif #endif
@ -515,7 +518,7 @@ extern "C" {
#endif #endif
#ifndef traceTASK_DELAY_UNTIL #ifndef traceTASK_DELAY_UNTIL
#define traceTASK_DELAY_UNTIL() #define traceTASK_DELAY_UNTIL( x )
#endif #endif
#ifndef traceTASK_DELAY #ifndef traceTASK_DELAY
@ -877,12 +880,6 @@ typedef struct xSTATIC_LIST
StaticMiniListItem_t xDummy3; StaticMiniListItem_t xDummy3;
} StaticList_t; } StaticList_t;
/* For data hiding purposes. */
typedef enum
{
eNothing = 0
} eDummy;
/* /*
* In line with software engineering best practice, especially when supplying a * In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a * library that is likely to change in future versions, FreeRTOS implements a
@ -932,7 +929,7 @@ typedef struct xSTATIC_TCB
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18; uint32_t ulDummy18;
eDummy eDummy19; uint8_t ucDummy19;
#endif #endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
uint8_t uxDummy20; uint8_t uxDummy20;

View File

@ -185,14 +185,6 @@ typedef enum
eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */
} eSleepModeStatus; } eSleepModeStatus;
/* Value that can be assigned to the eNotifyState member of the TCB. */
typedef enum
{
eNotWaitingNotification = 0,
eWaitingNotification,
eNotified
} eNotifyValue;
/** /**
* Defines the priority used by the idle task. This must not be modified. * Defines the priority used by the idle task. This must not be modified.
* *
@ -2105,7 +2097,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte
* indefinitely, whereas vTaskPlaceOnEventList() does. * indefinitely, whereas vTaskPlaceOnEventList() does.
* *
*/ */
void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
/* /*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN

View File

@ -129,6 +129,11 @@ deleted. */
#define taskSTATICALLY_ALLOCATED_STACK ( ( uint8_t ) 0x01 ) #define taskSTATICALLY_ALLOCATED_STACK ( ( uint8_t ) 0x01 )
#define taskSTATICALLY_ALLOCATED_TCB ( ( uint8_t ) 0x02 ) #define taskSTATICALLY_ALLOCATED_TCB ( ( uint8_t ) 0x02 )
/* Values that can be assigned to the ucNotifyState member of the TCB. */
#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 )
#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
/* /*
* Task control block. A task control block (TCB) is allocated for each task, * Task control block. A task control block (TCB) is allocated for each task,
* and stores task state information, including a pointer to the task's context * and stores task state information, including a pointer to the task's context
@ -174,7 +179,7 @@ typedef struct tskTaskControlBlock
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif #endif
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif #endif
@ -189,16 +194,16 @@ typedef struct tskTaskControlBlock
struct _reent xNewLib_reent; struct _reent xNewLib_reent;
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue; volatile uint32_t ulNotifiedValue;
volatile eNotifyValue eNotifyState; volatile uint8_t ucNotifyState;
#endif #endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
uint8_t ucStaticAllocationFlags; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */ uint8_t ucStaticAllocationFlags; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */
#endif #endif
} tskTCB; } tskTCB;
/* The old tskTCB name is maintained above then typedefed to the new TCB_t name /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
below to enable the use of older kernel aware debuggers. */ below to enable the use of older kernel aware debuggers. */
@ -489,7 +494,7 @@ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
* The currently executing task is entering the Blocked state. Add the task to * The currently executing task is entering the Blocked state. Add the task to
* either the current or the overflow delayed task list. * either the current or the overflow delayed task list.
*/ */
static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION; static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
/* /*
* Allocates memory from the heap for a TCB and associated stack. Checks the * Allocates memory from the heap for a TCB and associated stack. Checks the
@ -615,7 +620,7 @@ StackType_t *pxTopOfStack;
/* If we want to use stack checking on architectures that use /* If we want to use stack checking on architectures that use
a positive stack growth direction then we also need to store the a positive stack growth direction then we also need to store the
other extreme of the stack space. */ other extreme of the stack space. */
pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
} }
#endif /* portSTACK_GROWTH */ #endif /* portSTACK_GROWTH */
@ -889,23 +894,11 @@ StackType_t *pxTopOfStack;
if( xShouldDelay != pdFALSE ) if( xShouldDelay != pdFALSE )
{ {
traceTASK_DELAY_UNTIL(); traceTASK_DELAY_UNTIL( xTimeToWake );
/* Remove the task from the ready list before adding it to the /* prvAddCurrentTaskToDelayedList() needs the block time, not
blocked list as the same list item is used for both lists. */ the time to wake, so subtract the current tick count. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
{
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
else else
{ {
@ -933,10 +926,8 @@ StackType_t *pxTopOfStack;
void vTaskDelay( const TickType_t xTicksToDelay ) void vTaskDelay( const TickType_t xTicksToDelay )
{ {
TickType_t xTimeToWake;
BaseType_t xAlreadyYielded = pdFALSE; BaseType_t xAlreadyYielded = pdFALSE;
/* A delay time of zero just forces a reschedule. */ /* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( TickType_t ) 0U ) if( xTicksToDelay > ( TickType_t ) 0U )
{ {
@ -952,26 +943,7 @@ StackType_t *pxTopOfStack;
This task cannot be in an event list as it is the currently This task cannot be in an event list as it is the currently
executing task. */ executing task. */
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
/* Calculate the time to wake - this may overflow but this is
not a problem. */
xTimeToWake = xTickCount + xTicksToDelay;
/* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for
both lists. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
prvAddCurrentTaskToDelayedList( xTimeToWake );
} }
xAlreadyYielded = xTaskResumeAll(); xAlreadyYielded = xTaskResumeAll();
} }
@ -2447,8 +2419,6 @@ void vTaskSwitchContext( void )
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
{ {
TickType_t xTimeToWake;
configASSERT( pxEventList ); configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
@ -2460,54 +2430,12 @@ TickType_t xTimeToWake;
list is locked, preventing simultaneous access from interrupts. */ list is locked, preventing simultaneous access from interrupts. */
vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
/* The task must be removed from from the ready list before it is added to prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
the blocked list as the same list item is used for both lists. Exclusive
access to the ready lists guaranteed because the scheduler is locked. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead of a delayed task
list to ensure the task is not woken by a timing event. It will
block indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the
scheduler will handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter, the scheduler
will handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
{ {
TickType_t xTimeToWake;
configASSERT( pxEventList ); configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
@ -2526,56 +2454,14 @@ TickType_t xTimeToWake;
the task level). */ the task level). */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
/* The task must be removed from the ready list before it is added to the prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
blocked list. Exclusive access can be assured to the ready list as the
scheduler is locked. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead of a delayed task
list to ensure it is not woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the
kernel will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter, the kernel
will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TIMERS == 1 #if( configUSE_TIMERS == 1 )
void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
{ {
TickType_t xTimeToWake;
configASSERT( pxEventList ); configASSERT( pxEventList );
/* This function should not be called by application code hence the /* This function should not be called by application code hence the
@ -2590,59 +2476,16 @@ TickType_t xTimeToWake;
can be used in place of vListInsert. */ can be used in place of vListInsert. */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
/* We must remove this task from the ready list before adding it to the /* If the task should block indefinitely then set the block time to a
blocked list as the same list item is used for both lists. This value that will be recognised as an indefinite delay inside the
function is called with the scheduler locked so interrupts will not prvAddCurrentTaskToDelayedList() function. */
access the lists at the same time. */ if( xWaitIndefinitely == pdTRUE )
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{ {
/* The current task must be in a ready list, so there is no need to xTicksToWait = portMAX_DELAY;
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
} }
/* If vTaskSuspend() is available then the suspended task list is also traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
available and a task that is blocking indefinitely can enter the prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
suspended state (it is not really suspended as it will re-enter the
Ready state when the event it is waiting indefinitely for occurs).
Blocking indefinitely is useful when using tickless idle mode as when
all tasks are blocked indefinitely all timers can be turned off. */
#if( INCLUDE_vTaskSuspend == 1 )
{
if( xWaitIndefinitely == pdTRUE )
{
/* Add the task to the suspended task list instead of a delayed
task list to ensure the task is not woken by a timing event. It
will block indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be woken if the
event does not occur. This may overflow but this doesn't
matter. */
xTimeToWake = xTickCount + xTicksToWait;
traceTASK_DELAY_UNTIL();
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else
{
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter. */
xTimeToWake = xTickCount + xTicksToWait;
traceTASK_DELAY_UNTIL();
prvAddCurrentTaskToDelayedList( xTimeToWake );
/* Remove compiler warnings when INCLUDE_vTaskSuspend() is not
defined. */
( void ) xWaitIndefinitely;
}
#endif
} }
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
@ -2782,9 +2625,9 @@ BaseType_t xReturn;
const TickType_t xConstTickCount = xTickCount; const TickType_t xConstTickCount = xTickCount;
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified
the maximum block time then the task should block indefinitely, and is the maximum block time then the task should block indefinitely,
therefore never time out. */ and therefore never time out. */
if( *pxTicksToWait == portMAX_DELAY ) if( *pxTicksToWait == portMAX_DELAY )
{ {
xReturn = pdFALSE; xReturn = pdFALSE;
@ -2794,16 +2637,17 @@ BaseType_t xReturn;
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
{ {
/* The tick count is greater than the time at which vTaskSetTimeout() /* The tick count is greater than the time at which
was called, but has also overflowed since vTaskSetTimeOut() was called. vTaskSetTimeout() was called, but has also overflowed since
It must have wrapped all the way around and gone past us again. This vTaskSetTimeOut() was called. It must have wrapped all the way
passed since vTaskSetTimeout() was called. */ around and gone past again. This passed since vTaskSetTimeout()
was called. */
xReturn = pdTRUE; xReturn = pdTRUE;
} }
else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait ) else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait )
{ {
/* Not a genuine timeout. Adjust parameters for time remaining. */ /* Not a genuine timeout. Adjust parameters for time remaining. */
*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
vTaskSetTimeOutState( pxTimeOut ); vTaskSetTimeOutState( pxTimeOut );
xReturn = pdFALSE; xReturn = pdFALSE;
} }
@ -3117,7 +2961,7 @@ UBaseType_t x;
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
{ {
pxTCB->ulNotifiedValue = 0; pxTCB->ulNotifiedValue = 0;
pxTCB->eNotifyState = eNotWaitingNotification; pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
} }
#endif #endif
@ -3126,7 +2970,7 @@ UBaseType_t x;
/* Initialise this task's Newlib reent structure. */ /* Initialise this task's Newlib reent structure. */
_REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
} }
#endif /* configUSE_NEWLIB_REENTRANT */ #endif
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -3261,36 +3105,6 @@ static void prvCheckTasksWaitingTermination( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
{
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so the current block list is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
/* If the task entering the blocked state was placed at the head of the
list of blocked tasks then xNextTaskUnblockTime needs to be updated
too. */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
/*-----------------------------------------------------------*/
static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer, TCB_t * const pxTaskBuffer ) static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer, TCB_t * const pxTaskBuffer )
{ {
TCB_t *pxNewTCB; TCB_t *pxNewTCB;
@ -4190,7 +4004,6 @@ TickType_t uxReturn;
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
{ {
TickType_t xTimeToWake;
uint32_t ulReturn; uint32_t ulReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
@ -4199,55 +4012,11 @@ TickType_t uxReturn;
if( pxCurrentTCB->ulNotifiedValue == 0UL ) if( pxCurrentTCB->ulNotifiedValue == 0UL )
{ {
/* Mark this task as waiting for a notification. */ /* Mark this task as waiting for a notification. */
pxCurrentTCB->eNotifyState = eWaitingNotification; pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 ) if( xTicksToWait > ( TickType_t ) 0 )
{ {
/* The task is going to block. First it must be removed prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
from the ready list. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead
of a delayed task list to ensure the task is not
woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be
woken if no notification events occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be
woken if the event does not occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
traceTASK_NOTIFY_TAKE_BLOCK(); traceTASK_NOTIFY_TAKE_BLOCK();
/* All ports are written to allow a yield in a critical /* All ports are written to allow a yield in a critical
@ -4289,7 +4058,7 @@ TickType_t uxReturn;
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
pxCurrentTCB->eNotifyState = eNotWaitingNotification; pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -4303,13 +4072,12 @@ TickType_t uxReturn;
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
{ {
TickType_t xTimeToWake;
BaseType_t xReturn; BaseType_t xReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* Only block if a notification is not already pending. */ /* Only block if a notification is not already pending. */
if( pxCurrentTCB->eNotifyState != eNotified ) if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
{ {
/* Clear bits in the task's notification value as bits may get /* Clear bits in the task's notification value as bits may get
set by the notifying task or interrupt. This can be used to set by the notifying task or interrupt. This can be used to
@ -4317,55 +4085,11 @@ TickType_t uxReturn;
pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry; pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
/* Mark this task as waiting for a notification. */ /* Mark this task as waiting for a notification. */
pxCurrentTCB->eNotifyState = eWaitingNotification; pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 ) if( xTicksToWait > ( TickType_t ) 0 )
{ {
/* The task is going to block. First it must be removed prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
from the ready list. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is
no need to check, and the port reset macro can be called
directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( xTicksToWait == portMAX_DELAY )
{
/* Add the task to the suspended task list instead
of a delayed task list to ensure the task is not
woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be
woken if no notification events occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be
woken if the event does not occur. This may
overflow but this doesn't matter, the scheduler will
handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
#endif /* INCLUDE_vTaskSuspend */
traceTASK_NOTIFY_WAIT_BLOCK(); traceTASK_NOTIFY_WAIT_BLOCK();
/* All ports are written to allow a yield in a critical /* All ports are written to allow a yield in a critical
@ -4397,11 +4121,11 @@ TickType_t uxReturn;
*pulNotificationValue = pxCurrentTCB->ulNotifiedValue; *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
} }
/* If eNotifyValue is set then either the task never entered the /* If ucNotifyValue is set then either the task never entered the
blocked state (because a notification was already pending) or the blocked state (because a notification was already pending) or the
task unblocked because of a notification. Otherwise the task task unblocked because of a notification. Otherwise the task
unblocked because of a timeout. */ unblocked because of a timeout. */
if( pxCurrentTCB->eNotifyState == eWaitingNotification ) if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
{ {
/* A notification was not received. */ /* A notification was not received. */
xReturn = pdFALSE; xReturn = pdFALSE;
@ -4414,7 +4138,7 @@ TickType_t uxReturn;
xReturn = pdTRUE; xReturn = pdTRUE;
} }
pxCurrentTCB->eNotifyState = eNotWaitingNotification; pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -4429,8 +4153,8 @@ TickType_t uxReturn;
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
eNotifyValue eOriginalNotifyState;
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
uint8_t ucOriginalNotifyState;
configASSERT( xTaskToNotify ); configASSERT( xTaskToNotify );
pxTCB = ( TCB_t * ) xTaskToNotify; pxTCB = ( TCB_t * ) xTaskToNotify;
@ -4442,9 +4166,9 @@ TickType_t uxReturn;
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue; *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
} }
eOriginalNotifyState = pxTCB->eNotifyState; ucOriginalNotifyState = pxTCB->ucNotifyState;
pxTCB->eNotifyState = eNotified; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
switch( eAction ) switch( eAction )
{ {
@ -4461,7 +4185,7 @@ TickType_t uxReturn;
break; break;
case eSetValueWithoutOverwrite : case eSetValueWithoutOverwrite :
if( eOriginalNotifyState != eNotified ) if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{ {
pxTCB->ulNotifiedValue = ulValue; pxTCB->ulNotifiedValue = ulValue;
} }
@ -4482,7 +4206,7 @@ TickType_t uxReturn;
/* If the task is in the blocked state specifically to wait for a /* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */ notification then unblock it now. */
if( eOriginalNotifyState == eWaitingNotification ) if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{ {
( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB ); prvAddTaskToReadyList( pxTCB );
@ -4535,7 +4259,7 @@ TickType_t uxReturn;
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
eNotifyValue eOriginalNotifyState; uint8_t ucOriginalNotifyState;
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
UBaseType_t uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
@ -4568,8 +4292,8 @@ TickType_t uxReturn;
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue; *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
} }
eOriginalNotifyState = pxTCB->eNotifyState; ucOriginalNotifyState = pxTCB->ucNotifyState;
pxTCB->eNotifyState = eNotified; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
switch( eAction ) switch( eAction )
{ {
@ -4586,7 +4310,7 @@ TickType_t uxReturn;
break; break;
case eSetValueWithoutOverwrite : case eSetValueWithoutOverwrite :
if( eOriginalNotifyState != eNotified ) if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{ {
pxTCB->ulNotifiedValue = ulValue; pxTCB->ulNotifiedValue = ulValue;
} }
@ -4607,7 +4331,7 @@ TickType_t uxReturn;
/* If the task is in the blocked state specifically to wait for a /* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */ notification then unblock it now. */
if( eOriginalNotifyState == eWaitingNotification ) if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{ {
/* The task should not have been on an event list. */ /* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
@ -4659,7 +4383,7 @@ TickType_t uxReturn;
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
eNotifyValue eOriginalNotifyState; uint8_t ucOriginalNotifyState;
UBaseType_t uxSavedInterruptStatus; UBaseType_t uxSavedInterruptStatus;
configASSERT( xTaskToNotify ); configASSERT( xTaskToNotify );
@ -4686,8 +4410,8 @@ TickType_t uxReturn;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
eOriginalNotifyState = pxTCB->eNotifyState; ucOriginalNotifyState = pxTCB->ucNotifyState;
pxTCB->eNotifyState = eNotified; pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
/* 'Giving' is equivalent to incrementing a count in a counting /* 'Giving' is equivalent to incrementing a count in a counting
semaphore. */ semaphore. */
@ -4697,7 +4421,7 @@ TickType_t uxReturn;
/* If the task is in the blocked state specifically to wait for a /* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */ notification then unblock it now. */
if( eOriginalNotifyState == eWaitingNotification ) if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{ {
/* The task should not have been on an event list. */ /* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
@ -4756,9 +4480,9 @@ TickType_t uxReturn;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( pxTCB->eNotifyState == eNotified ) if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
{ {
pxTCB->eNotifyState = eNotWaitingNotification; pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
@ -4775,6 +4499,109 @@ TickType_t uxReturn;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, BaseType_t xCanBlockIndefinitely )
{
TickType_t xTimeToWake;
/* Remove the task from the ready list before adding it to the blocked list
as the same list item is used for both lists. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* The current task must be in a ready list, so there is no need to
check, and the port reset macro can be called directly. */
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#if ( INCLUDE_vTaskSuspend == 1 )
{
if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
{
/* Add the task to the suspended task list instead of a delayed task
list to ensure it is not woken by a timing event. It will block
indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the
kernel will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait;
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the overflow
list. */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so the current block list
is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
/* If the task entering the blocked state was placed at the
head of the list of blocked tasks then xNextTaskUnblockTime
needs to be updated too. */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
}
#else /* INCLUDE_vTaskSuspend */
{
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the kernel
will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait;
/* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
if( xTimeToWake < xTickCount )
{
/* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* The wake time has not overflowed, so the current block list is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
/* If the task entering the blocked state was placed at the head of the
list of blocked tasks then xNextTaskUnblockTime needs to be updated
too. */
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
( void ) xCanBlockIndefinitely;
}
#endif /* INCLUDE_vTaskSuspend */
}
#ifdef FREERTOS_MODULE_TEST #ifdef FREERTOS_MODULE_TEST
#include "tasks_test_access_functions.h" #include "tasks_test_access_functions.h"
#endif #endif