/*\r
- FreeRTOS.org V4.4.0 - Copyright (C) 2003-2007 Richard Barry.\r
+ FreeRTOS.org V4.7.1 - Copyright (C) 2003-2008 Richard Barry.\r
\r
This file is part of the FreeRTOS.org distribution.\r
\r
can be applied.\r
\r
***************************************************************************\r
- See http://www.FreeRTOS.org for documentation, latest information, license\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
+ Please ensure to read the configuration and relevant port sections of the \r
+ online documentation.\r
+\r
+ +++ http://www.FreeRTOS.org +++\r
+ Documentation, latest information, license and contact details. \r
+\r
+ +++ http://www.SafeRTOS.com +++\r
+ A version that is certified for use in safety critical systems.\r
+\r
+ +++ http://www.OpenRTOS.com +++\r
+ Commercial support, development, porting, licensing and training services.\r
+\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
/* As we have processed some ticks it is appropriate to yield\r
to ensure the highest priority task that is ready to run is\r
the task actually running. */\r
- xYieldRequired = pdTRUE;\r
+ #if configUSE_PREEMPTION == 1\r
+ {\r
+ xYieldRequired = pdTRUE;\r
+ }\r
+ #endif\r
}\r
\r
if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )\r
{\r
portENTER_CRITICAL();\r
{\r
- pcTraceBuffer = ( volatile signed portCHAR * volatile )pcBuffer;\r
+ pcTraceBuffer = ( signed portCHAR * )pcBuffer;\r
pcTraceBufferStart = pcBuffer;\r
pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE );\r
xTracing = pdTRUE;\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 ready 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