X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=Source%2Ftasks.c;h=91b749bf1502421a21d5e82de97563aaea5d517e;hb=8df96fdeb2fe1aed0e88d339b994d1ee3209e1c0;hp=01d7565ec6fb10b6a1ad11e404d2074dca672f92;hpb=b3e247836e4b16da26bef339173b40434ddb33cb;p=freertos diff --git a/Source/tasks.c b/Source/tasks.c index 01d7565ec..91b749bf1 100644 --- a/Source/tasks.c +++ b/Source/tasks.c @@ -1,11 +1,5 @@ /* - FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd. - - - FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by: - Atollic AB - Atollic provides professional embedded systems development - tools for C/C++ development, code analysis and test automation. - See http://www.atollic.com + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. *************************************************************************** @@ -106,7 +100,8 @@ typedef struct tskTaskControlBlock #endif #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ + unsigned portBASE_TYPE uxTCBNumber; /*< This stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + unsigned portBASE_TYPE uxTaskNumber; /*< This stores a number specifically for use by third party trace code. */ #endif #if ( configUSE_MUTEXES == 1 ) @@ -157,7 +152,7 @@ PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been r #endif -#if ( INCLUDE_xTaskIdleTaskHandleGet == 1 ) +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; @@ -173,7 +168,7 @@ PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static unsigned portBASE_TYPE uxTCBNumber = ( unsigned portBASE_TYPE ) 0U; PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY; #if ( configGENERATE_RUN_TIME_STATS == 1 ) @@ -200,58 +195,6 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) #define tskDELETED_CHAR ( ( signed char ) 'D' ) #define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) -/* - * Macros and private variables used by the trace facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) ) - PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer; - PRIVILEGED_DATA static signed char *pcTraceBufferStart; - PRIVILEGED_DATA static signed char *pcTraceBufferEnd; - PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE; - static unsigned portBASE_TYPE uxPreviousTask = 255U; - PRIVILEGED_DATA static char pcStatusString[ 50 ]; - -#endif - -/*-----------------------------------------------------------*/ - -/* - * Macro that writes a trace of scheduler activity to a buffer. This trace - * shows which task is running when and is very useful as a debugging tool. - * As this macro is called each context switch it is a good idea to undefine - * it if not using the facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define vWriteTraceToBuffer() \ - { \ - if( xTracing != pdFALSE ) \ - { \ - if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ - { \ - if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ - { \ - uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \ - pcTraceBuffer += sizeof( unsigned long ); \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \ - pcTraceBuffer += sizeof( unsigned long ); \ - } \ - else \ - { \ - xTracing = pdFALSE; \ - } \ - } \ - } \ - } - -#else - - #define vWriteTraceToBuffer() - -#endif /*-----------------------------------------------------------*/ /* @@ -473,7 +416,7 @@ tskTCB * pxNewTCB; #if( portSTACK_GROWTH < 0 ) { pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 ); - pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) ); + pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /* Check the alignment of the calculated top of stack is correct. */ configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); @@ -510,7 +453,7 @@ tskTCB * pxNewTCB; #endif /* Check the alignment of the initialised stack. */ - configASSERT( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + portALIGNMENT_ASSERT_pxCurrentTCB( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); if( ( void * ) pxCreatedTask != NULL ) { @@ -563,10 +506,10 @@ tskTCB * pxNewTCB; #if ( configUSE_TRACE_FACILITY == 1 ) { /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; + pxNewTCB->uxTCBNumber = uxTCBNumber; } #endif - uxTaskNumber++; + uxTCBNumber++; prvAddTaskToReadyQueue( pxNewTCB ); @@ -637,7 +580,7 @@ tskTCB * pxNewTCB; /* Increment the uxTaskNumberVariable also so kernel aware debuggers can detect that the task lists need re-generating. */ - uxTaskNumber++; + uxTCBNumber++; traceTASK_DELETE( pxTCB ); } @@ -824,7 +767,7 @@ tskTCB * pxNewTCB; priority of the calling function. */ pxTCB = prvGetTCBFromHandle( pxTask ); - traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); + traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); #if ( configUSE_MUTEXES == 1 ) { @@ -950,7 +893,7 @@ tskTCB * pxNewTCB; /* The scheduler is not running, but the task that was pointed to by pxCurrentTCB has just been suspended and pxCurrentTCB must be adjusted to point to a different task. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) { /* No other tasks are ready, so set pxCurrentTCB back to NULL so when the next task is created pxCurrentTCB will @@ -1054,29 +997,34 @@ tskTCB * pxNewTCB; { portBASE_TYPE xYieldRequired = pdFALSE; tskTCB *pxTCB; + unsigned portBASE_TYPE uxSavedInterruptStatus; configASSERT( pxTaskToResume ); pxTCB = ( tskTCB * ) pxTaskToResume; - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - else + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed, at which point a - yield will be performed if necessary. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + traceTASK_RESUME_FROM_ISR( pxTCB ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed, at which point a + yield will be performed if necessary. */ + vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } } } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); return xYieldRequired; } @@ -1096,10 +1044,10 @@ void vTaskStartScheduler( void ) portBASE_TYPE xReturn; /* Add the idle task at the lowest priority. */ - #if ( INCLUDE_xTaskIdleTaskHandleGet == 1 ) + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) { /* Create the idle task, storing its handle in xIdleTaskHandle so it can - be returned by the xTaskIdleTaskHandleGet() function. */ + be returned by the xTaskGetIdleTaskHandle() function. */ xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); } #else @@ -1298,9 +1246,9 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) } /*-----------------------------------------------------------*/ -#if ( INCLUDE_pcTaskNameGet == 1 ) +#if ( INCLUDE_pcTaskGetTaskName == 1 ) - signed char *pcTaskNameGet( xTaskHandle xTaskToQuery ) + signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ) { tskTCB *pxTCB; @@ -1451,49 +1399,11 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) #endif /*----------------------------------------------------------*/ -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) - { - configASSERT( pcBuffer ); - configASSERT( ulBufferSize ); - - taskENTER_CRITICAL(); - { - pcTraceBuffer = ( signed char * )pcBuffer; - pcTraceBufferStart = pcBuffer; - pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE ); - xTracing = pdTRUE; - } - taskEXIT_CRITICAL(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - unsigned long ulTaskEndTrace( void ) - { - unsigned long ulBufferLength; - - taskENTER_CRITICAL(); - xTracing = pdFALSE; - taskEXIT_CRITICAL(); - - ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart ); - - return ulBufferLength; - } - -#endif -/*----------------------------------------------------------*/ - -#if ( INCLUDE_xTaskIdleTaskHandleGet == 1 ) +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - xTaskHandle xTaskIdleTaskHandleGet( void ) + xTaskHandle xTaskGetIdleTaskHandle( void ) { - /* If xTaskIdleTaskHandleGet() is called before the scheduler has been + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been started, then xIdleTaskHandle will be NULL. */ configASSERT( ( xIdleTaskHandle != NULL ) ); return xIdleTaskHandle; @@ -1532,18 +1442,18 @@ tskTCB * pxTCB; if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) { - /* The new current delayed list is empty. Set - xNextTaskUnblockTime to the maximum possible value so it is + /* The new current delayed list is empty. Set + xNextTaskUnblockTime to the maximum possible value so it is extremely unlikely that the - if( xTickCount >= xNextTaskUnblockTime ) test will pass until + if( xTickCount >= xNextTaskUnblockTime ) test will pass until there is an item in the delayed list. */ xNextTaskUnblockTime = portMAX_DELAY; } else { - /* The new current delayed list is not empty, get the value of - the item at the head of the delayed list. This is the time at - which the task at the head of the delayed list should be removed + /* The new current delayed list is not empty, get the value of + the item at the head of the delayed list. This is the time at + which the task at the head of the delayed list should be removed from the Blocked state. */ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); @@ -1715,7 +1625,6 @@ void vTaskSwitchContext( void ) listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); traceTASK_SWITCHED_IN(); - vWriteTraceToBuffer(); } } /*-----------------------------------------------------------*/ @@ -1911,6 +1820,42 @@ void vTaskMissedYield( void ) { xMissedYield = pdTRUE; } +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ) + { + unsigned portBASE_TYPE uxReturn; + tskTCB *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( tskTCB * ) xTask; + uxReturn = pxTCB->uxTaskNumber; + } + else + { + uxReturn = 0U; + } + + return uxReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ) + { + tskTCB *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( tskTCB * ) xTask; + pxTCB->uxTaskNumber = uxHandle; + } + } +#endif + /* * ----------------------------------------------------------- @@ -2205,6 +2150,7 @@ tskTCB *pxNewTCB; { volatile tskTCB *pxNextTCB, *pxFirstTCB; unsigned short usStackRemaining; + PRIVILEGED_DATA static char pcStatusString[ 50 ]; /* Write the details of all the TCB's in pxList into the buffer. */ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); @@ -2353,6 +2299,10 @@ tskTCB *pxNewTCB; static void prvDeleteTCB( tskTCB *pxTCB ) { + /* This call is required specifically for the TriCore port. It must be + above the vPortFree() calls. */ + portCLEAN_UP_TCB( pxTCB ); + /* Free up the memory allocated by the scheduler for the task. It is up to the task to free any memory allocated at the application level. */ vPortFreeAligned( pxTCB->pxStack ); @@ -2438,6 +2388,8 @@ tskTCB *pxNewTCB; /* Just inherit the priority. */ pxTCB->uxPriority = pxCurrentTCB->uxPriority; } + + traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); } } @@ -2458,8 +2410,9 @@ tskTCB *pxNewTCB; Remove ourselves from the ready list we currently appear in. */ vListRemove( &( pxTCB->xGenericListItem ) ); - /* Disinherit the priority before adding ourselves into the new + /* Disinherit the priority before adding the task into the new ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); pxTCB->uxPriority = pxTCB->uxBasePriority; listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); prvAddTaskToReadyQueue( pxTCB );