/*\r
- FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
- All rights reserved\r
-\r
- VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
- This file is part of the FreeRTOS distribution.\r
-\r
- FreeRTOS is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License (version 2) as published by the\r
- Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
-\r
- ***************************************************************************\r
- >>! NOTE: The modification to the GPL is included to allow you to !<<\r
- >>! distribute a combined work that includes FreeRTOS without being !<<\r
- >>! obliged to provide the source code for proprietary components !<<\r
- >>! outside of the FreeRTOS kernel. !<<\r
- ***************************************************************************\r
-\r
- FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
- link: http://www.freertos.org/a00114.html\r
-\r
- ***************************************************************************\r
- * *\r
- * FreeRTOS provides completely free yet professionally developed, *\r
- * robust, strictly quality controlled, supported, and cross *\r
- * platform software that is more than just the market leader, it *\r
- * is the industry's de facto standard. *\r
- * *\r
- * Help yourself get started quickly while simultaneously helping *\r
- * to support the FreeRTOS project by purchasing a FreeRTOS *\r
- * tutorial book, reference manual, or both: *\r
- * http://www.FreeRTOS.org/Documentation *\r
- * *\r
- ***************************************************************************\r
-\r
- http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
- the FAQ page "My application does not run, what could be wrong?". Have you\r
- defined configASSERT()?\r
-\r
- http://www.FreeRTOS.org/support - In return for receiving this top quality\r
- embedded software for free we request you assist our global community by\r
- participating in the support forum.\r
-\r
- http://www.FreeRTOS.org/training - Investing in training allows your team to\r
- be as productive as possible as early as possible. Now you can receive\r
- FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
- Ltd, and the world's leading authority on the world's leading RTOS.\r
-\r
- http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
- including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
- compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
- http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
- Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
-\r
- http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
- Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
- licenses offer ticketed support, indemnification and commercial middleware.\r
-\r
- http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
- engineered and independently SIL3 certified version for use in safety and\r
- mission critical applications that require provable dependability.\r
-\r
- 1 tab == 4 spaces!\r
-*/\r
+ * FreeRTOS Kernel V10.0.1\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
\r
/* Standard includes. */\r
#include <stdlib.h>\r
#include "FreeRTOS.h"\r
#include "task.h"\r
#include "timers.h"\r
-#include "StackMacros.h"\r
+#include "stack_macros.h"\r
\r
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a\r
task to be created using either statically or dynamically allocated RAM. Note\r
that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with\r
-a statically allocated stack and a dynamically allocated TCB. */\r
-#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )\r
+a statically allocated stack and a dynamically allocated TCB.\r
+!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is\r
+changed then the definition of StaticTask_t must also be updated. */\r
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )\r
#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )\r
#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )\r
\r
+/* If any of the following are set then task stacks are filled with a known\r
+value so the high water mark can be determined. If none of the following are\r
+set then don't fill the stack so there is no unnecessary dependency on memset. */\r
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
+ #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1\r
+#else\r
+ #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0\r
+#endif\r
+\r
/*\r
* Macros used by vListTask to indicate which state a task is in.\r
*/\r
+#define tskRUNNING_CHAR ( 'X' )\r
#define tskBLOCKED_CHAR ( 'B' )\r
#define tskREADY_CHAR ( 'R' )\r
#define tskDELETED_CHAR ( 'D' )\r
#define static\r
#endif\r
\r
+/* The name allocated to the Idle task. This can be overridden by defining\r
+configIDLE_TASK_NAME in FreeRTOSConfig.h. */\r
+#ifndef configIDLE_TASK_NAME\r
+ #define configIDLE_TASK_NAME "IDLE"\r
+#endif\r
+\r
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )\r
\r
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is\r
StackType_t *pxStack; /*< Points to the start of the stack. */\r
char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
\r
- #if ( portSTACK_GROWTH > 0 )\r
- StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */\r
+ #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )\r
+ StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */\r
#endif\r
\r
#if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
#endif\r
\r
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )\r
- void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
+ void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
#endif\r
\r
#if( configGENERATE_RUN_TIME_STATS == 1 )\r
below to enable the use of older kernel aware debuggers. */\r
typedef tskTCB TCB_t;\r
\r
-/*lint -e956 A manual analysis and inspection has been used to determine which\r
-static variables must be declared volatile. */\r
+/*lint -save -e956 A manual analysis and inspection has been used to determine\r
+which static variables must be declared volatile. */\r
\r
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;\r
\r
\r
/* Other file private variables. --------------------------------*/\r
PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;\r
-PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;\r
+PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;\r
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;\r
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;\r
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;\r
\r
#endif\r
\r
-/*lint +e956 */\r
+/*lint -restore */\r
\r
/*-----------------------------------------------------------*/\r
\r
/* Callback function prototypes. --------------------------*/\r
#if( configCHECK_FOR_STACK_OVERFLOW > 0 )\r
+\r
extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );\r
+\r
#endif\r
\r
#if( configUSE_TICK_HOOK > 0 )\r
+\r
extern void vApplicationTickHook( void );\r
+\r
#endif\r
\r
#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+\r
extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );\r
+\r
#endif\r
\r
/* File private functions. --------------------------------*/\r
* is in any other state.\r
*/\r
#if ( INCLUDE_vTaskSuspend == 1 )\r
+\r
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;\r
+\r
#endif /* INCLUDE_vTaskSuspend */\r
\r
/*\r
*/\r
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;\r
\r
+/*\r
+ * freertos_tasks_c_additions_init() should only be called if the user definable\r
+ * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro\r
+ * called by the function.\r
+ */\r
+#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT\r
+\r
+ static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;\r
+\r
+#endif\r
+\r
/*-----------------------------------------------------------*/\r
\r
#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
configASSERT( puxStackBuffer != NULL );\r
configASSERT( pxTaskBuffer != NULL );\r
\r
+ #if( configASSERT_DEFINED == 1 )\r
+ {\r
+ /* Sanity check that the size of the structure used to declare a\r
+ variable of type StaticTask_t equals the size of the real task\r
+ structure. */\r
+ volatile size_t xSize = sizeof( StaticTask_t );\r
+ configASSERT( xSize == sizeof( TCB_t ) );\r
+ }\r
+ #endif /* configASSERT_DEFINED */\r
+\r
+\r
if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )\r
{\r
/* The memory used for the task's TCB and stack are passed into this\r
#endif /* SUPPORT_STATIC_ALLOCATION */\r
/*-----------------------------------------------------------*/\r
\r
-#if( portUSING_MPU_WRAPPERS == 1 )\r
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
+\r
+ BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )\r
+ {\r
+ TCB_t *pxNewTCB;\r
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;\r
+\r
+ configASSERT( pxTaskDefinition->puxStackBuffer != NULL );\r
+ configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );\r
+\r
+ if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )\r
+ {\r
+ /* Allocate space for the TCB. Where the memory comes from depends\r
+ on the implementation of the port malloc function and whether or\r
+ not static allocation is being used. */\r
+ pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;\r
+\r
+ /* Store the stack location in the TCB. */\r
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;\r
+\r
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )\r
+ {\r
+ /* Tasks can be created statically or dynamically, so note this\r
+ task was created statically in case the task is later deleted. */\r
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;\r
+ }\r
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
+\r
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,\r
+ pxTaskDefinition->pcName,\r
+ ( uint32_t ) pxTaskDefinition->usStackDepth,\r
+ pxTaskDefinition->pvParameters,\r
+ pxTaskDefinition->uxPriority,\r
+ pxCreatedTask, pxNewTCB,\r
+ pxTaskDefinition->xRegions );\r
+\r
+ prvAddNewTaskToReadyList( pxNewTCB );\r
+ xReturn = pdPASS;\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
\r
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )\r
{\r
/* Store the stack location in the TCB. */\r
pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;\r
\r
- /* Tasks can be created statically or dynamically, so note\r
- this task had a statically allocated stack in case it is\r
- later deleted. The TCB was allocated dynamically. */\r
- pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;\r
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
+ {\r
+ /* Tasks can be created statically or dynamically, so note\r
+ this task had a statically allocated stack in case it is\r
+ later deleted. The TCB was allocated dynamically. */\r
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;\r
+ }\r
+ #endif\r
\r
prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,\r
pxTaskDefinition->pcName,\r
\r
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,\r
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
- const uint16_t usStackDepth,\r
+ const configSTACK_DEPTH_TYPE usStackDepth,\r
void * const pvParameters,\r
UBaseType_t uxPriority,\r
TaskHandle_t * const pxCreatedTask )\r
#endif /* portUSING_MPU_WRAPPERS == 1 */\r
\r
/* Avoid dependency on memset() if it is not required. */\r
- #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
+ #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )\r
{\r
/* Fill the stack with a known value to assist debugging. */\r
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );\r
}\r
- #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */\r
+ #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */\r
\r
/* Calculate the top of stack address. This depends on whether the stack\r
grows from high memory to low (as per the 80x86) or vice versa.\r
\r
/* Check the alignment of the calculated top of stack is correct. */\r
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\r
+\r
+ #if( configRECORD_STACK_HIGH_ADDRESS == 1 )\r
+ {\r
+ /* Also record the stack's high address, which may assist\r
+ debugging. */\r
+ pxNewTCB->pxEndOfStack = pxTopOfStack;\r
+ }\r
+ #endif /* configRECORD_STACK_HIGH_ADDRESS */\r
}\r
#else /* portSTACK_GROWTH */\r
{\r
/* Initialize the TCB stack to look as if the task was already running,\r
but had been interrupted by the scheduler. The return address is set\r
to the start of the task function. Once the stack has been initialised\r
- the top of stack variable is updated. */\r
+ the top of stack variable is updated. */\r
#if( portUSING_MPU_WRAPPERS == 1 )\r
{\r
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
}\r
\r
/* If the task is in the blocked or suspended list we need do\r
- nothing more than change it's priority variable. However, if\r
+ nothing more than change its priority variable. However, if\r
the task is in a ready list it needs to be removed and placed\r
in the list appropriate to its new priority. */\r
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )\r
{\r
- /* The task is currently in its ready list - remove before adding\r
- it to it's new ready list. As we are in a critical section we\r
- can do this even if the scheduler is suspended. */\r
+ /* The task is currently in its ready list - remove before\r
+ adding it to it's new ready list. As we are in a critical\r
+ section we can do this even if the scheduler is suspended. */\r
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
{\r
/* It is known that the task is in its ready list so\r
}\r
\r
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );\r
+\r
+ #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+ {\r
+ if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )\r
+ {\r
+ /* The task was blocked to wait for a notification, but is\r
+ now suspended, so no notification was received. */\r
+ pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;\r
+ }\r
+ }\r
+ #endif\r
}\r
taskEXIT_CRITICAL();\r
\r
{\r
traceTASK_RESUME( pxTCB );\r
\r
- /* As we are in a critical section we can access the ready\r
- lists even if the scheduler is suspended. */\r
+ /* The ready list can be accessed even if the scheduler is\r
+ suspended because this is inside a critical section. */\r
( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
prvAddTaskToReadyList( pxTCB );\r
\r
- /* We may have just resumed a higher priority task. */\r
+ /* A higher priority task may have just been resumed. */\r
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
{\r
/* This yield may not cause the task just resumed to run,\r
address of the RAM then create the idle task. */\r
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );\r
xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,\r
- "IDLE",\r
+ configIDLE_TASK_NAME,\r
ulIdleTaskStackSize,\r
( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */\r
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),\r
{\r
/* The Idle task is being created using dynamically allocated RAM. */\r
xReturn = xTaskCreate( prvIdleTask,\r
- "IDLE", configMINIMAL_STACK_SIZE,\r
+ configIDLE_TASK_NAME,\r
+ configMINIMAL_STACK_SIZE,\r
( void * ) NULL,\r
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),\r
&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
\r
if( xReturn == pdPASS )\r
{\r
+ /* freertos_tasks_c_additions_init() should only be called if the user\r
+ definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is\r
+ the only macro called by the function. */\r
+ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT\r
+ {\r
+ freertos_tasks_c_additions_init();\r
+ }\r
+ #endif\r
+\r
/* Interrupts are turned off here, to ensure a tick does not occur\r
before or during the call to xPortStartScheduler(). The stacks of\r
the created tasks contain a status word with interrupts switched on\r
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )\r
{\r
TCB_t *pxTCB = ( TCB_t * ) xTask;\r
- BaseType_t xReturn = pdFALSE;\r
+ BaseType_t xReturn;\r
\r
configASSERT( pxTCB );\r
\r
it is actually in the Blocked state. */\r
if( eTaskGetState( xTask ) == eBlocked )\r
{\r
+ xReturn = pdPASS;\r
+\r
/* Remove the reference to the task from the blocked list. An\r
interrupt won't touch the xStateListItem because the\r
scheduler is suspended. */\r
}\r
else\r
{\r
- mtCOVERAGE_TEST_MARKER();\r
+ xReturn = pdFAIL;\r
}\r
}\r
( void ) xTaskResumeAll();\r
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )\r
{\r
configASSERT( pxTimeOut );\r
+ taskENTER_CRITICAL();\r
+ {\r
+ pxTimeOut->xOverflowCount = xNumOfOverflows;\r
+ pxTimeOut->xTimeOnEntering = xTickCount;\r
+ }\r
+ taskEXIT_CRITICAL();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )\r
+{\r
+ /* For internal use only as it does not use a critical section. */\r
pxTimeOut->xOverflowCount = xNumOfOverflows;\r
pxTimeOut->xTimeOnEntering = xTickCount;\r
}\r
{\r
/* Minor optimisation. The tick count cannot change in this block. */\r
const TickType_t xConstTickCount = xTickCount;\r
+ const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;\r
\r
#if( INCLUDE_xTaskAbortDelay == 1 )\r
if( pxCurrentTCB->ucDelayAborted != pdFALSE )\r
was called. */\r
xReturn = pdTRUE;\r
}\r
- else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */\r
+ else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */\r
{\r
/* Not a genuine timeout. Adjust parameters for time remaining. */\r
- *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );\r
- vTaskSetTimeOutState( pxTimeOut );\r
+ *pxTicksToWait -= xElapsedTime;\r
+ vTaskInternalSetTimeOutState( pxTimeOut );\r
xReturn = pdFALSE;\r
}\r
else\r
{\r
+ *pxTicksToWait = 0;\r
xReturn = pdTRUE;\r
}\r
}\r
/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE\r
SCHEDULER IS STARTED. **/\r
\r
+ /* In case a task that has a secure context deletes itself, in which case\r
+ the idle task is responsible for deleting the task's secure context, if\r
+ any. */\r
+ portTASK_CALLS_SECURE_FUNCTIONS();\r
+\r
for( ;; )\r
{\r
/* See if any tasks have deleted themselves - if so then the idle task\r
configASSERT( xNextTaskUnblockTime >= xTickCount );\r
xExpectedIdleTime = prvGetExpectedIdleTime();\r
\r
+ /* Define the following macro to set xExpectedIdleTime to 0\r
+ if the application does not want\r
+ portSUPPRESS_TICKS_AND_SLEEP() to be called. */\r
+ configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );\r
+\r
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )\r
{\r
traceLOW_POWER_IDLE_BEGIN();\r
\r
#if ( INCLUDE_vTaskDelete == 1 )\r
{\r
- BaseType_t xListIsEmpty;\r
+ TCB_t *pxTCB;\r
\r
- /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called\r
- too often in the idle task. */\r
+ /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()\r
+ being called too often in the idle task. */\r
while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )\r
{\r
- vTaskSuspendAll();\r
+ taskENTER_CRITICAL();\r
{\r
- xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );\r
+ pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );\r
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
+ --uxCurrentNumberOfTasks;\r
+ --uxDeletedTasksWaitingCleanUp;\r
}\r
- ( void ) xTaskResumeAll();\r
-\r
- if( xListIsEmpty == pdFALSE )\r
- {\r
- TCB_t *pxTCB;\r
-\r
- taskENTER_CRITICAL();\r
- {\r
- pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );\r
- ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
- --uxCurrentNumberOfTasks;\r
- --uxDeletedTasksWaitingCleanUp;\r
- }\r
- taskEXIT_CRITICAL();\r
+ taskEXIT_CRITICAL();\r
\r
- prvDeleteTCB( pxTCB );\r
- }\r
- else\r
- {\r
- mtCOVERAGE_TEST_MARKER();\r
- }\r
+ prvDeleteTCB( pxTCB );\r
}\r
}\r
#endif /* INCLUDE_vTaskDelete */\r
pxTaskStatus->pxStackBase = pxTCB->pxStack;\r
pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;\r
\r
- #if ( INCLUDE_vTaskSuspend == 1 )\r
- {\r
- /* If the task is in the suspended list then there is a chance it is\r
- actually just blocked indefinitely - so really it should be reported as\r
- being in the Blocked state. */\r
- if( pxTaskStatus->eCurrentState == eSuspended )\r
- {\r
- vTaskSuspendAll();\r
- {\r
- if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
- {\r
- pxTaskStatus->eCurrentState = eBlocked;\r
- }\r
- }\r
- ( void ) xTaskResumeAll();\r
- }\r
- }\r
- #endif /* INCLUDE_vTaskSuspend */\r
-\r
#if ( configUSE_MUTEXES == 1 )\r
{\r
pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;\r
}\r
#endif\r
\r
- /* Obtaining the task state is a little fiddly, so is only done if the value\r
- of eState passed into this function is eInvalid - otherwise the state is\r
- just set to whatever is passed in. */\r
+ /* Obtaining the task state is a little fiddly, so is only done if the\r
+ value of eState passed into this function is eInvalid - otherwise the\r
+ state is just set to whatever is passed in. */\r
if( eState != eInvalid )\r
{\r
- pxTaskStatus->eCurrentState = eState;\r
+ if( pxTCB == pxCurrentTCB )\r
+ {\r
+ pxTaskStatus->eCurrentState = eRunning;\r
+ }\r
+ else\r
+ {\r
+ pxTaskStatus->eCurrentState = eState;\r
+\r
+ #if ( INCLUDE_vTaskSuspend == 1 )\r
+ {\r
+ /* If the task is in the suspended list then there is a\r
+ chance it is actually just blocked indefinitely - so really\r
+ it should be reported as being in the Blocked state. */\r
+ if( eState == eSuspended )\r
+ {\r
+ vTaskSuspendAll();\r
+ {\r
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
+ {\r
+ pxTaskStatus->eCurrentState = eBlocked;\r
+ }\r
+ }\r
+ ( void ) xTaskResumeAll();\r
+ }\r
+ }\r
+ #endif /* INCLUDE_vTaskSuspend */\r
+ }\r
}\r
else\r
{\r
- pxTaskStatus->eCurrentState = eTaskGetState( xTask );\r
+ pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );\r
}\r
\r
/* Obtaining the stack space takes some time, so the xGetFreeStackSpace\r
{\r
/* Neither the stack nor the TCB were allocated dynamically, so\r
nothing needs to be freed. */\r
- configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )\r
+ configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );\r
mtCOVERAGE_TEST_MARKER();\r
}\r
}\r
\r
#if ( configUSE_MUTEXES == 1 )\r
\r
- void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )\r
+ BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )\r
{\r
- TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
+ TCB_t * const pxMutexHolderTCB = ( TCB_t * ) pxMutexHolder;\r
+ BaseType_t xReturn = pdFALSE;\r
\r
/* If the mutex was given back by an interrupt while the queue was\r
- locked then the mutex holder might now be NULL. */\r
+ locked then the mutex holder might now be NULL. _RB_ Is this still\r
+ needed as interrupts can no longer use mutexes? */\r
if( pxMutexHolder != NULL )\r
{\r
/* If the holder of the mutex has a priority below the priority of\r
the task attempting to obtain the mutex then it will temporarily\r
inherit the priority of the task attempting to obtain the mutex. */\r
- if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )\r
+ if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )\r
{\r
/* Adjust the mutex holder state to account for its new\r
priority. Only reset the event list item value if the value is\r
- not being used for anything else. */\r
- if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
+ not being used for anything else. */\r
+ if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
{\r
- listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
+ listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
}\r
else\r
{\r
\r
/* If the task being modified is in the ready state it will need\r
to be moved into a new list. */\r
- if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )\r
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )\r
{\r
- if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
+ if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
{\r
- taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
+ taskRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority );\r
}\r
else\r
{\r
}\r
\r
/* Inherit the priority before being moved into the new list. */\r
- pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
- prvAddTaskToReadyList( pxTCB );\r
+ pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;\r
+ prvAddTaskToReadyList( pxMutexHolderTCB );\r
}\r
else\r
{\r
/* Just inherit the priority. */\r
- pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
+ pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;\r
}\r
\r
- traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );\r
+ traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );\r
+\r
+ /* Inheritance occurred. */\r
+ xReturn = pdTRUE;\r
}\r
else\r
{\r
- mtCOVERAGE_TEST_MARKER();\r
+ if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )\r
+ {\r
+ /* The base priority of the mutex holder is lower than the\r
+ priority of the task attempting to take the mutex, but the\r
+ current priority of the mutex holder is not lower than the\r
+ priority of the task attempting to take the mutex.\r
+ Therefore the mutex holder must have already inherited a\r
+ priority, but inheritance would have occurred if that had\r
+ not been the case. */\r
+ xReturn = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
}\r
}\r
else\r
{\r
mtCOVERAGE_TEST_MARKER();\r
}\r
+\r
+ return xReturn;\r
}\r
\r
#endif /* configUSE_MUTEXES */\r
interrupt, and if a mutex is given by the holding task then it must\r
be the running state task. */\r
configASSERT( pxTCB == pxCurrentTCB );\r
-\r
configASSERT( pxTCB->uxMutexesHeld );\r
( pxTCB->uxMutexesHeld )--;\r
\r
/* A task can only have an inherited priority if it holds\r
the mutex. If the mutex is held by a task then it cannot be\r
given from an interrupt, and if a mutex is given by the\r
- holding task then it must be the running state task. Remove\r
- the holding task from the ready list. */\r
+ holding task then it must be the running state task. Remove\r
+ the holding task from the ready list. */\r
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
{\r
taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
#endif /* configUSE_MUTEXES */\r
/*-----------------------------------------------------------*/\r
\r
+#if ( configUSE_MUTEXES == 1 )\r
+\r
+ void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask )\r
+ {\r
+ TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
+ UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;\r
+ const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;\r
+\r
+ if( pxMutexHolder != NULL )\r
+ {\r
+ /* If pxMutexHolder is not NULL then the holder must hold at least\r
+ one mutex. */\r
+ configASSERT( pxTCB->uxMutexesHeld );\r
+\r
+ /* Determine the priority to which the priority of the task that\r
+ holds the mutex should be set. This will be the greater of the\r
+ holding task's base priority and the priority of the highest\r
+ priority task that is waiting to obtain the mutex. */\r
+ if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )\r
+ {\r
+ uxPriorityToUse = uxHighestPriorityWaitingTask;\r
+ }\r
+ else\r
+ {\r
+ uxPriorityToUse = pxTCB->uxBasePriority;\r
+ }\r
+\r
+ /* Does the priority need to change? */\r
+ if( pxTCB->uxPriority != uxPriorityToUse )\r
+ {\r
+ /* Only disinherit if no other mutexes are held. This is a\r
+ simplification in the priority inheritance implementation. If\r
+ the task that holds the mutex is also holding other mutexes then\r
+ the other mutexes may have caused the priority inheritance. */\r
+ if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )\r
+ {\r
+ /* If a task has timed out because it already holds the\r
+ mutex it was trying to obtain then it cannot of inherited\r
+ its own priority. */\r
+ configASSERT( pxTCB != pxCurrentTCB );\r
+\r
+ /* Disinherit the priority, remembering the previous\r
+ priority to facilitate determining the subject task's\r
+ state. */\r
+ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );\r
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;\r
+ pxTCB->uxPriority = uxPriorityToUse;\r
+\r
+ /* Only reset the event list item value if the value is not\r
+ being used for anything else. */\r
+ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
+ {\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ /* If the running task is not the task that holds the mutex\r
+ then the task that holds the mutex could be in either the\r
+ Ready, Blocked or Suspended states. Only remove the task\r
+ from its current state list if it is in the Ready state as\r
+ the task's priority is going to change and there is one\r
+ Ready list per priority. */\r
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )\r
+ {\r
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
+ {\r
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ prvAddTaskToReadyList( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+\r
+#endif /* configUSE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
#if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
\r
void vTaskEnterCritical( void )\r
#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */\r
/*-----------------------------------------------------------*/\r
\r
-#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )\r
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
\r
void vTaskList( char * pcWriteBuffer )\r
{\r
{\r
switch( pxTaskStatusArray[ x ].eCurrentState )\r
{\r
+ case eRunning: cStatus = tskRUNNING_CHAR;\r
+ break;\r
+\r
case eReady: cStatus = tskREADY_CHAR;\r
break;\r
\r
}\r
}\r
\r
-#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */\r
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */\r
/*----------------------------------------------------------*/\r
\r
-#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )\r
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
\r
void vTaskGetRunTimeStats( char *pcWriteBuffer )\r
{\r
}\r
}\r
\r
-#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */\r
+#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */\r
/*-----------------------------------------------------------*/\r
\r
TickType_t uxTaskResetEventItemValue( void )\r
blocked state (because a notification was already pending) or the\r
task unblocked because of a notification. Otherwise the task\r
unblocked because of a timeout. */\r
- if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )\r
+ if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )\r
{\r
/* A notification was not received. */\r
xReturn = pdFALSE;\r
#endif /* INCLUDE_vTaskSuspend */\r
}\r
\r
+/* Code below here allows additional code to be inserted into this source file,\r
+especially where access to file scope functions and data is needed (for example\r
+when performing module tests). */\r
\r
#ifdef FREERTOS_MODULE_TEST\r
#include "tasks_test_access_functions.h"\r
#endif\r
\r
+\r
+#if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )\r
+\r
+ #include "freertos_tasks_c_additions.h"\r
+\r
+ static void freertos_tasks_c_additions_init( void )\r
+ {\r
+ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT\r
+ FREERTOS_TASKS_C_ADDITIONS_INIT();\r
+ #endif\r
+ }\r
+\r
+#endif\r
+\r
+\r