/*\r
- FreeRTOS.org V4.4.0 - Copyright (C) 2003-2007 Richard Barry.\r
+ FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.\r
\r
This file is part of the FreeRTOS.org distribution.\r
\r
and contact details. Please ensure to read the configuration and relevant\r
port sections of the online documentation.\r
\r
- Also see http://www.SafeRTOS.com for an IEC 61508 compliant version, along\r
- with development and support options.\r
+ Also see http://www.SafeRTOS.com a version that has been certified for use\r
+ in safety critical systems, plus commercial licensing, development and\r
+ support options.\r
***************************************************************************\r
*/\r
\r
#define configMAX_TASK_NAME_LEN 16\r
#endif\r
\r
-#ifndef INCLUDE_xTaskGetCurrentTaskHandle\r
- #define INCLUDE_xTaskGetCurrentTaskHandle 0\r
-#endif\r
-\r
#ifndef configIDLE_SHOULD_YIELD\r
#define configIDLE_SHOULD_YIELD 1\r
#endif\r
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */\r
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */\r
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */\r
- unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */\r
signed portCHAR pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */\r
- unsigned portSHORT usStackDepth; /*< Total depth of the stack (when empty). This is defined as the number of variables the stack can hold, not the number of bytes. */\r
+\r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */\r
+ #endif \r
+ \r
+ #if ( configUSE_MUTEXES == 1 )\r
+ unsigned portBASE_TYPE uxBasePriority;\r
+ #endif\r
+ \r
} tskTCB;\r
\r
/*lint -e956 */\r
* Utility to ready a TCB for a given task. Mainly just copies the parameters\r
* into the TCB structure.\r
*/\r
-static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );\r
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority );\r
\r
/*\r
* Utility to ready all the lists used by the scheduler. This is called\r
*/\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );\r
+ static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus );\r
\r
#endif\r
\r
*/\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte );\r
+ unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte );\r
\r
#endif\r
\r
{\r
signed portBASE_TYPE xReturn;\r
tskTCB * pxNewTCB;\r
-static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */\r
+#if ( configUSE_TRACE_FACILITY == 1 )\r
+ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberate - this is guarded before use. */\r
+#endif\r
\r
/* Allocate the memory required by the TCB and stack for the new task.\r
checking that the allocation was successful. */\r
portSTACK_TYPE *pxTopOfStack;\r
\r
/* Setup the newly allocated TCB with the initial state of the task. */\r
- prvInitialiseTCBVariables( pxNewTCB, usStackDepth, pcName, uxPriority );\r
+ prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority );\r
\r
/* Calculate the top of stack address. This depends on whether the\r
stack grows from high memory to low (as per the 80x86) or visa versa.\r
required by the port. */\r
#if portSTACK_GROWTH < 0\r
{\r
- pxTopOfStack = pxNewTCB->pxStack + ( pxNewTCB->usStackDepth - 1 );\r
+ pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );\r
}\r
#else\r
{\r
uxTopUsedPriority = pxNewTCB->uxPriority;\r
}\r
\r
- /* Add a counter into the TCB for tracing only. */\r
- pxNewTCB->uxTCBNumber = uxTaskNumber;\r
- uxTaskNumber++;\r
+ #if ( configUSE_TRACE_FACILITY == 1 )\r
+ {\r
+ /* Add a counter into the TCB for tracing only. */\r
+ pxNewTCB->uxTCBNumber = uxTaskNumber;\r
+ uxTaskNumber++;\r
+ }\r
+ #endif\r
\r
prvAddTaskToReadyQueue( pxNewTCB );\r
\r
\r
#if ( INCLUDE_vTaskDelayUntil == 1 )\r
\r
- void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement )\r
+ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )\r
{\r
portTickType xTimeToWake;\r
portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;\r
/* If null is passed in here then we are changing the\r
priority of the calling function. */\r
pxTCB = prvGetTCBFromHandle( pxTask );\r
- uxCurrentPriority = pxTCB->uxPriority;\r
+ \r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ uxCurrentPriority = pxTCB->uxBasePriority;\r
+ }\r
+ #else\r
+ {\r
+ uxCurrentPriority = pxTCB->uxPriority;\r
+ }\r
+ #endif\r
\r
if( uxCurrentPriority != uxNewPriority )\r
{\r
/* The priority change may have readied a task of higher\r
priority than the calling task. */\r
- if( uxNewPriority > pxCurrentTCB->uxPriority ) \r
+ if( uxNewPriority > uxCurrentPriority ) \r
{\r
if( pxTask != NULL )\r
{\r
xYieldRequired = pdTRUE;\r
}\r
\r
- pxTCB->uxPriority = uxNewPriority;\r
- listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority );\r
+ \r
+\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ /* Only change the priority being used if the task is not\r
+ currently using an inherited priority. */\r
+ if( pxTCB->uxBasePriority == pxTCB->uxPriority )\r
+ {\r
+ pxTCB->uxPriority = uxNewPriority;\r
+ }\r
+ \r
+ /* The base priority gets set whatever. */\r
+ pxTCB->uxBasePriority = uxNewPriority; \r
+ }\r
+ #else\r
+ {\r
+ pxTCB->uxPriority = uxNewPriority;\r
+ }\r
+ #endif\r
+\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );\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
{\r
/* We cannot access the delayed or ready lists, so will hold this\r
task pending until the scheduler is resumed, at which point a\r
- yield will be preformed if necessary. */\r
+ yield will be performed if necessary. */\r
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
}\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vTaskPlaceOnEventList( xList *pxEventList, portTickType xTicksToWait )\r
+void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )\r
{\r
portTickType xTimeToWake;\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-signed portBASE_TYPE xTaskRemoveFromEventList( const xList *pxEventList )\r
+signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )\r
{\r
tskTCB *pxUnblockedTCB;\r
portBASE_TYPE xReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vTaskSetTimeOutState( xTimeOutType *pxTimeOut )\r
+void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )\r
{\r
pxTimeOut->xOverflowCount = xNumOfOverflows;\r
pxTimeOut->xTimeOnEntering = xTickCount;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType *pxTimeOut, portTickType * const pxTicksToWait )\r
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )\r
{\r
portBASE_TYPE xReturn;\r
\r
\r
\r
\r
-static void prvInitialiseTCBVariables( tskTCB *pxTCB, unsigned portSHORT usStackDepth, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority )\r
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority )\r
{\r
- pxTCB->usStackDepth = usStackDepth;\r
-\r
/* Store the function name in the TCB. */\r
strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned portSHORT ) configMAX_TASK_NAME_LEN );\r
pxTCB->pcTaskName[ ( unsigned portSHORT ) configMAX_TASK_NAME_LEN - ( unsigned portSHORT ) 1 ] = '\0';\r
}\r
\r
pxTCB->uxPriority = uxPriority;\r
+ #if ( configUSE_MUTEXES == 1 )\r
+ {\r
+ pxTCB->uxBasePriority = uxPriority;\r
+ }\r
+ #endif\r
\r
vListInitialiseItem( &( pxTCB->xGenericListItem ) );\r
vListInitialiseItem( &( pxTCB->xEventListItem ) );\r
\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- static void prvListTaskWithinSingleList( signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )\r
+ static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus )\r
{\r
volatile tskTCB *pxNextTCB, *pxFirstTCB;\r
static portCHAR pcStatusString[ 50 ];\r
/*-----------------------------------------------------------*/\r
\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
- unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR *pucStackByte )\r
+ unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )\r
{\r
register unsigned portSHORT usCount = 0;\r
\r
\r
#endif\r
\r
+#if ( configUSE_MUTEXES == 1 )\r
+ \r
+ void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )\r
+ {\r
+ tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;\r
+\r
+ if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )\r
+ {\r
+ /* Adjust the mutex holder state to account for its new priority. */\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );\r
+\r
+ /* If the task being modified is in the read state it will need to\r
+ be moved in to a new list. */\r
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )\r
+ {\r
+ vListRemove( &( pxTCB->xGenericListItem ) );\r
+\r
+ /* Inherit the priority before being moved into the new list. */\r
+ pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
+ prvAddTaskToReadyQueue( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ /* Just inherit the priority. */\r
+ pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
+ }\r
+ }\r
+ }\r
+\r
+#endif\r
+\r
+#if ( configUSE_MUTEXES == 1 ) \r
+\r
+ void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )\r
+ {\r
+ tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;\r
+\r
+ if( pxMutexHolder != NULL )\r
+ {\r
+ if( pxTCB->uxPriority != pxTCB->uxBasePriority )\r
+ {\r
+ /* We must be the running task to be able to give the mutex back.\r
+ Remove ourselves from the ready list we currently appear in. */\r
+ vListRemove( &( pxTCB->xGenericListItem ) );\r
+\r
+ /* Disinherit the priority before adding ourselves into the new\r
+ ready list. */\r
+ pxTCB->uxPriority = pxTCB->uxBasePriority;\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );\r
+ prvAddTaskToReadyQueue( pxTCB );\r
+ }\r
+ }\r
+ }\r
+\r
+#endif\r
+\r
+ \r
+\r
+ \r
\r