forked from epagris/FreeRTOS-Kernel
		
	Enhanced priority dis-inheritance functionality in the case where a task that caused another task to inherit its priority times out before obtain a mutex.
Added test code to GenQTest to test the new priority dis-inheritance functionality. Allow the default names given to the Idle and Timer tasks to be overwridden by definitions in FreeRTOSConfig.h.
This commit is contained in:
		
							parent
							
								
									883541bc8e
								
							
						
					
					
						commit
						d67dcf9c74
					
				@ -91,6 +91,7 @@
 | 
			
		||||
 | 
			
		||||
#define genqQUEUE_LENGTH		( 5 )
 | 
			
		||||
#define intsemNO_BLOCK			( 0 )
 | 
			
		||||
#define genqSHORT_BLOCK			( pdMS_TO_TICKS( 2 ) )
 | 
			
		||||
 | 
			
		||||
#define genqMUTEX_LOW_PRIORITY		( tskIDLE_PRIORITY )
 | 
			
		||||
#define genqMUTEX_TEST_PRIORITY		( tskIDLE_PRIORITY + 1 )
 | 
			
		||||
@ -125,6 +126,27 @@ static void prvLowPriorityMutexTask( void *pvParameters );
 | 
			
		||||
static void prvMediumPriorityMutexTask( void *pvParameters );
 | 
			
		||||
static void prvHighPriorityMutexTask( void *pvParameters );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tests the behaviour when a low priority task inherits the priority of a
 | 
			
		||||
 * higher priority task when taking two mutexes, and returns the mutexes in
 | 
			
		||||
 * first the same order as the two mutexes were obtained, and second the
 | 
			
		||||
 * opposite order as the two mutexes were obtained.
 | 
			
		||||
 */
 | 
			
		||||
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
 | 
			
		||||
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
 | 
			
		||||
 | 
			
		||||
#if( INCLUDE_xTaskAbortDelay == 1 )
 | 
			
		||||
 | 
			
		||||
	#if( configUSE_PREEMPTION == 0 )
 | 
			
		||||
		#error The additional tests included when INCLUDE_xTaskAbortDelay is 1 expect preemption to be used.
 | 
			
		||||
	#endif
 | 
			
		||||
 | 
			
		||||
	/* Tests the behaviour when a low priority task inherits the priority of a
 | 
			
		||||
	high priority task only for the high priority task to timeout before
 | 
			
		||||
	obtaining the mutex. */
 | 
			
		||||
	static void prvHighPriorityTimeout( SemaphoreHandle_t xMutex );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
 | 
			
		||||
@ -143,6 +165,17 @@ static volatile uint32_t ulGuardedVariable = 0;
 | 
			
		||||
priority mutex test tasks. */
 | 
			
		||||
static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
 | 
			
		||||
 | 
			
		||||
/* If INCLUDE_xTaskAbortDelay is 1 additional tests are performed, requiring an
 | 
			
		||||
additional task. */
 | 
			
		||||
#if( INCLUDE_xTaskAbortDelay == 1 )
 | 
			
		||||
	static TaskHandle_t xSecondMediumPriorityMutexTask;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Lets the high priority semaphore task know that its wait for the semaphore
 | 
			
		||||
was aborted, in which case not being able to obtain the semaphore is not to be
 | 
			
		||||
considered an error. */
 | 
			
		||||
static volatile BaseType_t xBlockWasAborted = pdFALSE;
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vStartGenericQueueTasks( UBaseType_t uxPriority )
 | 
			
		||||
@ -189,13 +222,21 @@ SemaphoreHandle_t xMutex;
 | 
			
		||||
		xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
 | 
			
		||||
		xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
 | 
			
		||||
		xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
 | 
			
		||||
 | 
			
		||||
		/* If INCLUDE_xTaskAbortDelay is set then additional tests are performed,
 | 
			
		||||
		requiring two instances of prvHighPriorityMutexTask(). */
 | 
			
		||||
		#if( INCLUDE_xTaskAbortDelay == 1 )
 | 
			
		||||
		{
 | 
			
		||||
			xTaskCreate( prvHighPriorityMutexTask, "MuHigh2", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_MEDIUM_PRIORITY, &xSecondMediumPriorityMutexTask );
 | 
			
		||||
		}
 | 
			
		||||
		#endif /* INCLUDE_xTaskAbortDelay */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvSendFrontAndBackTest( void *pvParameters )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulData, ulData2;
 | 
			
		||||
uint32_t ulData, ulData2, ulLoopCounterSnapshot;
 | 
			
		||||
QueueHandle_t xQueue;
 | 
			
		||||
 | 
			
		||||
	#ifdef USE_STDIO
 | 
			
		||||
@ -215,7 +256,8 @@ QueueHandle_t xQueue;
 | 
			
		||||
		should have the same efect as sending it to the front of the queue.
 | 
			
		||||
 | 
			
		||||
		First send to the front and check everything is as expected. */
 | 
			
		||||
		xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, intsemNO_BLOCK );
 | 
			
		||||
		ulLoopCounterSnapshot = ulLoopCounter;
 | 
			
		||||
		xQueueSendToFront( xQueue, ( void * ) &ulLoopCounterSnapshot, intsemNO_BLOCK );
 | 
			
		||||
 | 
			
		||||
		if( uxQueueMessagesWaiting( xQueue ) != 1 )
 | 
			
		||||
		{
 | 
			
		||||
@ -241,7 +283,8 @@ QueueHandle_t xQueue;
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, intsemNO_BLOCK );
 | 
			
		||||
		ulLoopCounterSnapshot = ulLoopCounter;
 | 
			
		||||
		xQueueSendToBack( xQueue, ( void * ) &ulLoopCounterSnapshot, intsemNO_BLOCK );
 | 
			
		||||
 | 
			
		||||
		if( uxQueueMessagesWaiting( xQueue ) != 1 )
 | 
			
		||||
		{
 | 
			
		||||
@ -258,8 +301,8 @@ QueueHandle_t xQueue;
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* The data we sent to the queue should equal the data we just received
 | 
			
		||||
		from the queue. */
 | 
			
		||||
		/* The data sent to the queue should equal the data just received from
 | 
			
		||||
		the queue. */
 | 
			
		||||
		if( ulLoopCounter != ulData )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
@ -416,11 +459,204 @@ QueueHandle_t xQueue;
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Increment the loop counter to indicate these tasks are still
 | 
			
		||||
		executing. */
 | 
			
		||||
		ulLoopCounter++;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if( INCLUDE_xTaskAbortDelay == 1 )
 | 
			
		||||
 | 
			
		||||
	static void prvHighPriorityTimeout( SemaphoreHandle_t xMutex )
 | 
			
		||||
	{
 | 
			
		||||
	static UBaseType_t uxLoopCount = 0;
 | 
			
		||||
 | 
			
		||||
		/* The tests in this function are very similar, the slight variations
 | 
			
		||||
		are for code coverage purposes. */
 | 
			
		||||
 | 
			
		||||
		/* Take the mutex.  It should be available now. */
 | 
			
		||||
		if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* This task's priority should be as per that assigned when the task was
 | 
			
		||||
		created. */
 | 
			
		||||
		if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Now unsuspend the high priority task.  This will attempt to take the
 | 
			
		||||
		mutex, and block when it finds it cannot obtain it. */
 | 
			
		||||
		vTaskResume( xHighPriorityMutexTask );
 | 
			
		||||
 | 
			
		||||
		/* This task should now have inherited the priority of the high priority
 | 
			
		||||
		task as by now the high priority task will have attempted to obtain the
 | 
			
		||||
		mutex. */
 | 
			
		||||
		if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Unblock a second medium priority task.  It too will attempt to take
 | 
			
		||||
		the mutex and enter the Blocked state - it won't run yet though as this
 | 
			
		||||
		task has inherited a priority above it. */
 | 
			
		||||
		vTaskResume( xSecondMediumPriorityMutexTask );
 | 
			
		||||
 | 
			
		||||
		/* This task should still have the priority of the high priority task as
 | 
			
		||||
		that had already been inherited as is the highest priority of the three
 | 
			
		||||
		tasks using the mutex. */
 | 
			
		||||
		if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* On some loops, block for a short while to provide additional
 | 
			
		||||
		code coverage.  Blocking here will allow the medium priority task to
 | 
			
		||||
		execute and so also block on the mutex so when the high priority task
 | 
			
		||||
		causes this task to disinherit the high priority it is inherited down to
 | 
			
		||||
		the priority of the medium priority task.  When there is no delay the
 | 
			
		||||
		medium priority task will not run until after the disinheritance, so
 | 
			
		||||
		this task will disinherit back to its base priority, then only up to the
 | 
			
		||||
		medium priority after the medium priority has executed. */
 | 
			
		||||
		vTaskDelay( uxLoopCount & ( UBaseType_t ) 0x07 );
 | 
			
		||||
 | 
			
		||||
		/* Now force the high priority task to unblock.  It will fail to obtain
 | 
			
		||||
		the mutex and go back to the suspended state - allowing this task to
 | 
			
		||||
		execute again.  xBlockWasAborted is set to pdTRUE so the higher priority
 | 
			
		||||
		task knows that its failure to obtain the semaphore is not an error. */
 | 
			
		||||
		xBlockWasAborted = pdTRUE;
 | 
			
		||||
		if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* This task has inherited the priority of xHighPriorityMutexTask so
 | 
			
		||||
		could still be running even though xHighPriorityMutexTask is no longer
 | 
			
		||||
		blocked.  Delay for a short while to ensure xHighPriorityMutexTask gets
 | 
			
		||||
		a chance to run - indicated by this task changing priority.  It should
 | 
			
		||||
		disinherit the high priority task, but then inherit the priority of the
 | 
			
		||||
		medium priority task that is waiting for the same mutex. */
 | 
			
		||||
		while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			/* If this task gets stuck here then the check variables will stop
 | 
			
		||||
			incrementing and the check task will detect the error. */
 | 
			
		||||
			vTaskDelay( genqSHORT_BLOCK );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Now force the medium priority task to unblock.  xBlockWasAborted is
 | 
			
		||||
		set to pdTRUE so the medium priority task knows that its failure to
 | 
			
		||||
		obtain the semaphore is not an error. */
 | 
			
		||||
		xBlockWasAborted = pdTRUE;
 | 
			
		||||
		if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* This time no other tasks are waiting for the mutex, so this task
 | 
			
		||||
		should return to its base priority.  This might not happen straight
 | 
			
		||||
		away as it is running at the same priority as the task it just
 | 
			
		||||
		unblocked. */
 | 
			
		||||
		while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			/* If this task gets stuck here then the check variables will stop
 | 
			
		||||
			incrementing and the check task will detect the error. */
 | 
			
		||||
			vTaskDelay( genqSHORT_BLOCK );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Give the semaphore back ready for the next test. */
 | 
			
		||||
		xSemaphoreGive( xMutex );
 | 
			
		||||
 | 
			
		||||
		configASSERT( xErrorDetected == pdFALSE );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		/* Now do the same again, but this time unsuspend the tasks in the
 | 
			
		||||
		opposite order.  This takes a different path though the code because
 | 
			
		||||
		when the high priority task has its block aborted there is already
 | 
			
		||||
		another task in the list of tasks waiting for the mutex, and the
 | 
			
		||||
		low priority task drops down to that priority, rather than dropping
 | 
			
		||||
		down to its base priority before inheriting the priority of the medium
 | 
			
		||||
		priority task. */
 | 
			
		||||
		if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* This time unsuspend the medium priority task first.  This will
 | 
			
		||||
		attempt to take the mutex, and block when it finds it cannot obtain it. */
 | 
			
		||||
		vTaskResume( xSecondMediumPriorityMutexTask );
 | 
			
		||||
 | 
			
		||||
		/* This time this task should now have inherited the priority of the
 | 
			
		||||
		medium task. */
 | 
			
		||||
		if( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* This time the high priority task in unsuspended second. */
 | 
			
		||||
		vTaskResume( xHighPriorityMutexTask );
 | 
			
		||||
 | 
			
		||||
		/* The high priority task should already have run, causing this task to
 | 
			
		||||
		inherit a priority for the second time. */
 | 
			
		||||
		if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* This time, when the high priority task has its delay aborted and it
 | 
			
		||||
		fails to obtain the mutex this task will immediately have its priority
 | 
			
		||||
		lowered down to that of the highest priority task waiting on the mutex,
 | 
			
		||||
		which is the medium priority task. */
 | 
			
		||||
		xBlockWasAborted = pdTRUE;
 | 
			
		||||
		if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			/* If this task gets stuck here then the check variables will stop
 | 
			
		||||
			incrementing and the check task will detect the error. */
 | 
			
		||||
			vTaskDelay( genqSHORT_BLOCK );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* And finally, when the medium priority task also have its delay
 | 
			
		||||
		aborted there are no other tasks waiting for the mutex so this task
 | 
			
		||||
		returns to its base priority. */
 | 
			
		||||
		xBlockWasAborted = pdTRUE;
 | 
			
		||||
		if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
 | 
			
		||||
		{
 | 
			
		||||
			/* If this task gets stuck here then the check variables will stop
 | 
			
		||||
			incrementing and the check task will detect the error. */
 | 
			
		||||
			vTaskDelay( genqSHORT_BLOCK );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Give the semaphore back ready for the next test. */
 | 
			
		||||
		xSemaphoreGive( xMutex );
 | 
			
		||||
 | 
			
		||||
		configASSERT( xErrorDetected == pdFALSE );
 | 
			
		||||
 | 
			
		||||
		/* uxLoopCount is used to add a variable delay, and in-so-doing provide
 | 
			
		||||
		additional code coverage. */
 | 
			
		||||
		uxLoopCount++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif /* INCLUDE_xTaskAbortDelay == 1 */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
 | 
			
		||||
{
 | 
			
		||||
	/* Take the mutex.  It should be available now. */
 | 
			
		||||
@ -455,15 +691,16 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
 | 
			
		||||
	}
 | 
			
		||||
	#endif /* INCLUDE_eTaskGetState */
 | 
			
		||||
 | 
			
		||||
	/* The priority of the high priority task should now have been inherited
 | 
			
		||||
	as by now it will have attempted to get the mutex. */
 | 
			
		||||
	/* This task should now have inherited the priority of the high priority
 | 
			
		||||
	task as by now the high priority task will have attempted to obtain the
 | 
			
		||||
	mutex. */
 | 
			
		||||
	if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
 | 
			
		||||
	{
 | 
			
		||||
		xErrorDetected = pdTRUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Attempt to set the priority of this task to the test priority -
 | 
			
		||||
	between the	idle priority and the medium/high test priorities, but the
 | 
			
		||||
	between the idle priority and the medium/high test priorities, but the
 | 
			
		||||
	actual priority should remain at the high priority. */
 | 
			
		||||
	vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
 | 
			
		||||
	if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
 | 
			
		||||
@ -585,8 +822,9 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
 | 
			
		||||
	}
 | 
			
		||||
	#endif /* INCLUDE_eTaskGetState */
 | 
			
		||||
 | 
			
		||||
	/* The priority of the high priority task should now have been inherited
 | 
			
		||||
	as by now it will have attempted to get the mutex. */
 | 
			
		||||
	/* This task should now have inherited the priority of the high priority
 | 
			
		||||
	task as by now the high priority task will have attempted to obtain the
 | 
			
		||||
	mutex. */
 | 
			
		||||
	if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
 | 
			
		||||
	{
 | 
			
		||||
		xErrorDetected = pdTRUE;
 | 
			
		||||
@ -708,6 +946,15 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
 | 
			
		||||
		#if configUSE_PREEMPTION == 0
 | 
			
		||||
			taskYIELD();
 | 
			
		||||
		#endif
 | 
			
		||||
 | 
			
		||||
		#if( INCLUDE_xTaskAbortDelay == 1 )
 | 
			
		||||
		{
 | 
			
		||||
			/* Tests the behaviour when a low priority task inherits the
 | 
			
		||||
			priority of a high priority task only for the high priority task to
 | 
			
		||||
			timeout before obtaining the mutex. */
 | 
			
		||||
			prvHighPriorityTimeout( xMutex );
 | 
			
		||||
		}
 | 
			
		||||
		#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
@ -740,19 +987,30 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
 | 
			
		||||
		priority task will unsuspend this task when required. */
 | 
			
		||||
		vTaskSuspend( NULL );
 | 
			
		||||
 | 
			
		||||
		/* When this task unsuspends all it does is attempt to obtain
 | 
			
		||||
		the mutex.  It should find the mutex is not available so a
 | 
			
		||||
		block time is specified. */
 | 
			
		||||
		/* When this task unsuspends all it does is attempt to obtain the
 | 
			
		||||
		mutex.  It should find the mutex is not available so a block time is
 | 
			
		||||
		specified. */
 | 
			
		||||
		if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
			/* This task would expect to obtain the mutex unless its wait for
 | 
			
		||||
			the mutex was aborted. */
 | 
			
		||||
			if( xBlockWasAborted == pdFALSE )
 | 
			
		||||
			{
 | 
			
		||||
				xErrorDetected = pdTRUE;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				xBlockWasAborted = pdFALSE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* When the mutex is eventually obtained it is just given back before
 | 
			
		||||
		returning to suspend ready for the next cycle. */
 | 
			
		||||
		if( xSemaphoreGive( xMutex ) != pdPASS )
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			xErrorDetected = pdTRUE;
 | 
			
		||||
			/* When the mutex is eventually obtained it is just given back before
 | 
			
		||||
			returning to suspend ready for the next cycle. */
 | 
			
		||||
			if( xSemaphoreGive( xMutex ) != pdPASS )
 | 
			
		||||
			{
 | 
			
		||||
				xErrorDetected = pdTRUE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -314,7 +314,7 @@ static void prvRecursiveMutexPollingTask( void *pvParameters )
 | 
			
		||||
 | 
			
		||||
	for( ;; )
 | 
			
		||||
	{
 | 
			
		||||
		/* Keep attempting to obtain the mutex.  We should only obtain it when
 | 
			
		||||
		/* Keep attempting to obtain the mutex.  It should only be obtained when
 | 
			
		||||
		the blocking task has suspended itself, which in turn should only
 | 
			
		||||
		happen when the controlling task is also suspended. */
 | 
			
		||||
		if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )
 | 
			
		||||
 | 
			
		||||
@ -205,7 +205,7 @@ typedef struct xMINI_LIST_ITEM MiniListItem_t;
 | 
			
		||||
typedef struct xLIST
 | 
			
		||||
{
 | 
			
		||||
	listFIRST_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
 | 
			
		||||
	configLIST_VOLATILE UBaseType_t uxNumberOfItems;
 | 
			
		||||
	volatile UBaseType_t uxNumberOfItems;
 | 
			
		||||
	ListItem_t * configLIST_VOLATILE pxIndex;			/*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
 | 
			
		||||
	MiniListItem_t xListEnd;							/*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
 | 
			
		||||
	listSECOND_LIST_INTEGRITY_CHECK_VALUE				/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
 | 
			
		||||
 | 
			
		||||
@ -2311,6 +2311,16 @@ BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_F
 | 
			
		||||
 */
 | 
			
		||||
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * If a higher priority task attempting to obtain a mutex caused a lower
 | 
			
		||||
 * priority task to inherit the higher priority task's priority - but the higher
 | 
			
		||||
 * priority task then timed out without obtaining the mutex, then the lower
 | 
			
		||||
 * priority task will disinherit the priority again - but only down as far as
 | 
			
		||||
 * the highest priority task that is still waiting for the mutex (if there were
 | 
			
		||||
 * more than one task waiting for the mutex).
 | 
			
		||||
 */
 | 
			
		||||
void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -255,6 +255,16 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
 | 
			
		||||
	static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if( configUSE_MUTEXES == 1 )
 | 
			
		||||
	/*
 | 
			
		||||
	 * If a task waiting for a mutex causes the mutex holder to inherit a
 | 
			
		||||
	 * priority, but the waiting task times out, then the holder should
 | 
			
		||||
	 * disinherit the priority - but only down to the highest priority of any
 | 
			
		||||
	 * other tasks that are waiting for the same mutex.  This function returns
 | 
			
		||||
	 * that priority.
 | 
			
		||||
	 */
 | 
			
		||||
	static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
 | 
			
		||||
#endif
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -1408,6 +1418,10 @@ BaseType_t xEntryTimeSet = pdFALSE;
 | 
			
		||||
TimeOut_t xTimeOut;
 | 
			
		||||
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 | 
			
		||||
 | 
			
		||||
#if( configUSE_MUTEXES == 1 )
 | 
			
		||||
	BaseType_t xInheritanceOccurred = pdFALSE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Check the queue pointer is not NULL. */
 | 
			
		||||
	configASSERT( ( pxQueue ) );
 | 
			
		||||
 | 
			
		||||
@ -1485,6 +1499,11 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 | 
			
		||||
			{
 | 
			
		||||
				if( xTicksToWait == ( TickType_t ) 0 )
 | 
			
		||||
				{
 | 
			
		||||
					/* For inheritance to have occurred there must have been an
 | 
			
		||||
					initial timeout, and an adjusted timeout cannot become 0, as
 | 
			
		||||
					if it were 0 the function would have exited. */
 | 
			
		||||
					configASSERT( xInheritanceOccurred == pdFALSE );
 | 
			
		||||
 | 
			
		||||
					/* The semaphore count was 0 and no block time is specified
 | 
			
		||||
					(or the block time has expired) so exit now. */
 | 
			
		||||
					taskEXIT_CRITICAL();
 | 
			
		||||
@ -1530,7 +1549,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 | 
			
		||||
					{
 | 
			
		||||
						taskENTER_CRITICAL();
 | 
			
		||||
						{
 | 
			
		||||
							xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
 | 
			
		||||
							xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
 | 
			
		||||
						}
 | 
			
		||||
						taskEXIT_CRITICAL();
 | 
			
		||||
					}
 | 
			
		||||
@ -1572,6 +1591,30 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 | 
			
		||||
			queue being empty is equivalent to the semaphore count being 0. */
 | 
			
		||||
			if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
 | 
			
		||||
			{
 | 
			
		||||
				#if ( configUSE_MUTEXES == 1 )
 | 
			
		||||
				{
 | 
			
		||||
					/* xInheritanceOccurred could only have be set if
 | 
			
		||||
					pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
 | 
			
		||||
					test the mutex type again to check it is actually a mutex. */
 | 
			
		||||
					if( xInheritanceOccurred != pdFALSE )
 | 
			
		||||
					{
 | 
			
		||||
						taskENTER_CRITICAL();
 | 
			
		||||
						{
 | 
			
		||||
							UBaseType_t uxHighestWaitingPriority;
 | 
			
		||||
 | 
			
		||||
							/* This task blocking on the mutex caused another
 | 
			
		||||
							task to inherit this task's priority.  Now this task
 | 
			
		||||
							has timed out the priority should be disinherited
 | 
			
		||||
							again, but only as low as the next highest priority
 | 
			
		||||
							task that is waiting for the same mutex. */
 | 
			
		||||
							uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
 | 
			
		||||
							vTaskPriorityDisinheritAfterTimeout( ( void * ) pxQueue->pxMutexHolder, uxHighestWaitingPriority );
 | 
			
		||||
						}
 | 
			
		||||
						taskEXIT_CRITICAL();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				#endif /* configUSE_MUTEXES */
 | 
			
		||||
 | 
			
		||||
				traceQUEUE_RECEIVE_FAILED( pxQueue );
 | 
			
		||||
				return errQUEUE_EMPTY;
 | 
			
		||||
			}
 | 
			
		||||
@ -1997,6 +2040,33 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 | 
			
		||||
#endif /* configUSE_TRACE_FACILITY */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if( configUSE_MUTEXES == 1 )
 | 
			
		||||
 | 
			
		||||
	static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )
 | 
			
		||||
	{
 | 
			
		||||
	UBaseType_t uxHighestPriorityOfWaitingTasks;
 | 
			
		||||
 | 
			
		||||
		/* If a task waiting for a mutex causes the mutex holder to inherit a
 | 
			
		||||
		priority, but the waiting task times out, then the holder should
 | 
			
		||||
		disinherit the priority - but only down to the highest priority of any
 | 
			
		||||
		other tasks that are waiting for the same mutex.  For this purpose,
 | 
			
		||||
		return the priority of the highest priority task that is waiting for the
 | 
			
		||||
		mutex. */
 | 
			
		||||
		if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0 )
 | 
			
		||||
		{
 | 
			
		||||
			uxHighestPriorityOfWaitingTasks = configMAX_PRIORITIES - listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) );
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return uxHighestPriorityOfWaitingTasks;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif /* configUSE_MUTEXES */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
 | 
			
		||||
{
 | 
			
		||||
BaseType_t xReturn = pdFALSE;
 | 
			
		||||
 | 
			
		||||
@ -164,6 +164,12 @@ set then don't fill the stack so there is no unnecessary dependency on memset. *
 | 
			
		||||
	#define static
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The name allocated to the Idle task.  This can be overridden by defining
 | 
			
		||||
tskIDLE_TASK_NAME in FreeRTOSConfig.h. */
 | 
			
		||||
#ifndef tskIDLE_TASK_NAME
 | 
			
		||||
	#define tskIDLE_TASK_NAME "IDLE"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
 | 
			
		||||
 | 
			
		||||
	/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
 | 
			
		||||
@ -713,7 +719,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 | 
			
		||||
#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 | 
			
		||||
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) )
 | 
			
		||||
 | 
			
		||||
	BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
 | 
			
		||||
	{
 | 
			
		||||
@ -1610,14 +1616,14 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* If the task is in the blocked or suspended list we need do
 | 
			
		||||
				nothing more than change it's priority variable. However, if
 | 
			
		||||
				nothing more than change its priority variable. However, if
 | 
			
		||||
				the task is in a ready list it needs to be removed and placed
 | 
			
		||||
				in the list appropriate to its new priority. */
 | 
			
		||||
				if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
 | 
			
		||||
				{
 | 
			
		||||
					/* The task is currently in its ready list - remove before adding
 | 
			
		||||
					it to it's new ready list.  As we are in a critical section we
 | 
			
		||||
					can do this even if the scheduler is suspended. */
 | 
			
		||||
					/* The task is currently in its ready list - remove before
 | 
			
		||||
					adding it to it's new ready list.  As we are in a critical
 | 
			
		||||
					section we can do this even if the scheduler is suspended. */
 | 
			
		||||
					if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 | 
			
		||||
					{
 | 
			
		||||
						/* It is known that the task is in its ready list so
 | 
			
		||||
@ -1944,7 +1950,7 @@ BaseType_t xReturn;
 | 
			
		||||
		address of the RAM then create the idle task. */
 | 
			
		||||
		vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
 | 
			
		||||
		xIdleTaskHandle = xTaskCreateStatic(	prvIdleTask,
 | 
			
		||||
												"IDLE",
 | 
			
		||||
												tskIDLE_TASK_NAME,
 | 
			
		||||
												ulIdleTaskStackSize,
 | 
			
		||||
												( void * ) NULL, /*lint !e961.  The cast is not redundant for all compilers. */
 | 
			
		||||
												( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
 | 
			
		||||
@ -1964,7 +1970,8 @@ BaseType_t xReturn;
 | 
			
		||||
	{
 | 
			
		||||
		/* The Idle task is being created using dynamically allocated RAM. */
 | 
			
		||||
		xReturn = xTaskCreate(	prvIdleTask,
 | 
			
		||||
								"IDLE", configMINIMAL_STACK_SIZE,
 | 
			
		||||
								tskIDLE_TASK_NAME,
 | 
			
		||||
								configMINIMAL_STACK_SIZE,
 | 
			
		||||
								( void * ) NULL,
 | 
			
		||||
								( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
 | 
			
		||||
								&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
 | 
			
		||||
@ -2545,7 +2552,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
 | 
			
		||||
	BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
 | 
			
		||||
	{
 | 
			
		||||
	TCB_t *pxTCB = ( TCB_t * ) xTask;
 | 
			
		||||
	BaseType_t xReturn = pdFALSE;
 | 
			
		||||
	BaseType_t xReturn;
 | 
			
		||||
 | 
			
		||||
		configASSERT( pxTCB );
 | 
			
		||||
 | 
			
		||||
@ -2555,6 +2562,8 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
 | 
			
		||||
			it is actually in the Blocked state. */
 | 
			
		||||
			if( eTaskGetState( xTask ) == eBlocked )
 | 
			
		||||
			{
 | 
			
		||||
				xReturn = pdPASS;
 | 
			
		||||
 | 
			
		||||
				/* Remove the reference to the task from the blocked list.  An
 | 
			
		||||
				interrupt won't touch the xStateListItem because the
 | 
			
		||||
				scheduler is suspended. */
 | 
			
		||||
@ -2603,7 +2612,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
				xReturn = pdFAIL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		( void ) xTaskResumeAll();
 | 
			
		||||
@ -3130,6 +3139,7 @@ BaseType_t xReturn;
 | 
			
		||||
	{
 | 
			
		||||
		/* Minor optimisation.  The tick count cannot change in this block. */
 | 
			
		||||
		const TickType_t xConstTickCount = xTickCount;
 | 
			
		||||
		const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
 | 
			
		||||
 | 
			
		||||
		#if( INCLUDE_xTaskAbortDelay == 1 )
 | 
			
		||||
			if( pxCurrentTCB->ucDelayAborted != pdFALSE )
 | 
			
		||||
@ -3162,10 +3172,10 @@ BaseType_t xReturn;
 | 
			
		||||
			was called. */
 | 
			
		||||
			xReturn = pdTRUE;
 | 
			
		||||
		}
 | 
			
		||||
		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. */
 | 
			
		||||
		else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
 | 
			
		||||
		{
 | 
			
		||||
			/* Not a genuine timeout. Adjust parameters for time remaining. */
 | 
			
		||||
			*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
 | 
			
		||||
			*pxTicksToWait -= xElapsedTime;
 | 
			
		||||
			vTaskSetTimeOutState( pxTimeOut );
 | 
			
		||||
			xReturn = pdFALSE;
 | 
			
		||||
		}
 | 
			
		||||
@ -3817,25 +3827,25 @@ TCB_t *pxTCB;
 | 
			
		||||
 | 
			
		||||
	BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
 | 
			
		||||
	{
 | 
			
		||||
	TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
 | 
			
		||||
	TCB_t * const pxMutexHolderTCB = ( TCB_t * ) pxMutexHolder;
 | 
			
		||||
	BaseType_t xReturn = pdFALSE;
 | 
			
		||||
 | 
			
		||||
		/* If the mutex was given back by an interrupt while the queue was
 | 
			
		||||
		locked then the mutex holder might now be NULL.  _RB_ Is this still
 | 
			
		||||
		needed as interrupt can no longer use mutexes? */
 | 
			
		||||
		needed as interrupts can no longer use mutexes? */
 | 
			
		||||
		if( pxMutexHolder != NULL )
 | 
			
		||||
		{
 | 
			
		||||
			/* If the holder of the mutex has a priority below the priority of
 | 
			
		||||
			the task attempting to obtain the mutex then it will temporarily
 | 
			
		||||
			inherit the priority of the task attempting to obtain the mutex. */
 | 
			
		||||
			if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
 | 
			
		||||
			if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
 | 
			
		||||
			{
 | 
			
		||||
				/* Adjust the mutex holder state to account for its new
 | 
			
		||||
				priority.  Only reset the event list item value if the value is
 | 
			
		||||
				not	being used for anything else. */
 | 
			
		||||
				if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
 | 
			
		||||
				not being used for anything else. */
 | 
			
		||||
				if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
 | 
			
		||||
				{
 | 
			
		||||
					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. */
 | 
			
		||||
					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. */
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
@ -3844,11 +3854,11 @@ TCB_t *pxTCB;
 | 
			
		||||
 | 
			
		||||
				/* If the task being modified is in the ready state it will need
 | 
			
		||||
				to be moved into a new list. */
 | 
			
		||||
				if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
 | 
			
		||||
				if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
 | 
			
		||||
				{
 | 
			
		||||
					if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 | 
			
		||||
					if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 | 
			
		||||
					{
 | 
			
		||||
						taskRESET_READY_PRIORITY( pxTCB->uxPriority );
 | 
			
		||||
						taskRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority );
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
@ -3856,23 +3866,37 @@ TCB_t *pxTCB;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					/* Inherit the priority before being moved into the new list. */
 | 
			
		||||
					pxTCB->uxPriority = pxCurrentTCB->uxPriority;
 | 
			
		||||
					prvAddTaskToReadyList( pxTCB );
 | 
			
		||||
					pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
 | 
			
		||||
					prvAddTaskToReadyList( pxMutexHolderTCB );
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					/* Just inherit the priority. */
 | 
			
		||||
					pxTCB->uxPriority = pxCurrentTCB->uxPriority;
 | 
			
		||||
					pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
 | 
			
		||||
				traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
 | 
			
		||||
 | 
			
		||||
				/* Inheritance occurred. */
 | 
			
		||||
				xReturn = pdTRUE;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
				if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
 | 
			
		||||
				{
 | 
			
		||||
					/* The base priority of the mutex holder is lower than the
 | 
			
		||||
					priority of the task attempting to take the mutex, but the
 | 
			
		||||
					current priority of the mutex holder is not lower than the
 | 
			
		||||
					priority of the task attempting to take the mutex.
 | 
			
		||||
					Therefore the mutex holder must have already inherited a
 | 
			
		||||
					priority, but inheritance would have occurred if that had
 | 
			
		||||
					not been the case. */
 | 
			
		||||
					xReturn = pdTRUE;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
@ -3900,7 +3924,6 @@ TCB_t *pxTCB;
 | 
			
		||||
			interrupt, and if a mutex is given by the holding task then it must
 | 
			
		||||
			be the running state task. */
 | 
			
		||||
			configASSERT( pxTCB == pxCurrentTCB );
 | 
			
		||||
 | 
			
		||||
			configASSERT( pxTCB->uxMutexesHeld );
 | 
			
		||||
			( pxTCB->uxMutexesHeld )--;
 | 
			
		||||
 | 
			
		||||
@ -3914,8 +3937,8 @@ TCB_t *pxTCB;
 | 
			
		||||
					/* A task can only have an inherited priority if it holds
 | 
			
		||||
					the mutex.  If the mutex is held by a task then it cannot be
 | 
			
		||||
					given from an interrupt, and if a mutex is given by the
 | 
			
		||||
					holding	task then it must be the running state task.  Remove
 | 
			
		||||
					the	holding task from the ready	list. */
 | 
			
		||||
					holding task then it must be the running state task.  Remove
 | 
			
		||||
					the holding task from the ready list. */
 | 
			
		||||
					if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 | 
			
		||||
					{
 | 
			
		||||
						taskRESET_READY_PRIORITY( pxTCB->uxPriority );
 | 
			
		||||
@ -3967,6 +3990,108 @@ TCB_t *pxTCB;
 | 
			
		||||
#endif /* configUSE_MUTEXES */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if ( configUSE_MUTEXES == 1 )
 | 
			
		||||
 | 
			
		||||
	void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask )
 | 
			
		||||
	{
 | 
			
		||||
	TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
 | 
			
		||||
	UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
 | 
			
		||||
	const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
 | 
			
		||||
 | 
			
		||||
		if( pxMutexHolder != NULL )
 | 
			
		||||
		{
 | 
			
		||||
			/* If pxMutexHolder is not NULL then the holder must hold at least
 | 
			
		||||
			one mutex. */
 | 
			
		||||
			configASSERT( pxTCB->uxMutexesHeld );
 | 
			
		||||
 | 
			
		||||
			/* Determine the priority to which the priority of the task that
 | 
			
		||||
			holds the mutex should be set.  This will be the greater of the
 | 
			
		||||
			holding task's base priority and the priority of the highest
 | 
			
		||||
			priority task that is waiting to obtain the mutex. */
 | 
			
		||||
			if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
 | 
			
		||||
			{
 | 
			
		||||
				uxPriorityToUse = uxHighestPriorityWaitingTask;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				uxPriorityToUse = pxTCB->uxBasePriority;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Does the priority need to change? */
 | 
			
		||||
			if( pxTCB->uxPriority != uxPriorityToUse )
 | 
			
		||||
			{
 | 
			
		||||
				/* Only disinherit if no other mutexes are held.  This is a
 | 
			
		||||
				simplification in the priority inheritance implementation.  If
 | 
			
		||||
				the task that holds the mutex is also holding other mutexes then
 | 
			
		||||
				the other mutexes may have caused the priority inheritance. */
 | 
			
		||||
				if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
 | 
			
		||||
				{
 | 
			
		||||
					/* If a task has timed out because it already holds the
 | 
			
		||||
					mutex it was trying to obtain then it cannot of inherited
 | 
			
		||||
					its own priority. */
 | 
			
		||||
					configASSERT( pxTCB != pxCurrentTCB );
 | 
			
		||||
 | 
			
		||||
					/* Disinherit the priority, remembering the previous
 | 
			
		||||
					priority to facilitate determining the subject task's
 | 
			
		||||
					state. */
 | 
			
		||||
					traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
 | 
			
		||||
					uxPriorityUsedOnEntry = pxTCB->uxPriority;
 | 
			
		||||
					pxTCB->uxPriority = uxPriorityToUse;
 | 
			
		||||
 | 
			
		||||
					/* Only reset the event list item value if the value is not
 | 
			
		||||
					being used for anything else. */
 | 
			
		||||
					if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
 | 
			
		||||
					{
 | 
			
		||||
						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. */
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					/* If the running task is not the task that holds the mutex
 | 
			
		||||
					then the task that holds the mutex could be in either the
 | 
			
		||||
					Ready, Blocked or Suspended states.  Only remove the task
 | 
			
		||||
					from its current state list if it is in the Ready state as
 | 
			
		||||
					the task's priority is going to change and there is one
 | 
			
		||||
					Ready list per priority. */
 | 
			
		||||
					if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
 | 
			
		||||
					{
 | 
			
		||||
						if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 | 
			
		||||
						{
 | 
			
		||||
							taskRESET_READY_PRIORITY( pxTCB->uxPriority );
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						prvAddTaskToReadyList( pxTCB );
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#endif /* configUSE_MUTEXES */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
 | 
			
		||||
 | 
			
		||||
	void vTaskEnterCritical( void )
 | 
			
		||||
 | 
			
		||||
@ -100,6 +100,12 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
 | 
			
		||||
/* Misc definitions. */
 | 
			
		||||
#define tmrNO_DELAY		( TickType_t ) 0U
 | 
			
		||||
 | 
			
		||||
/* The name assigned to the timer service task.  This can be overridden by
 | 
			
		||||
defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
 | 
			
		||||
#ifndef tmrTIMER_SERVICE_TASK_NAME
 | 
			
		||||
	#define tmrTIMER_SERVICE_TASK_NAME "Tmr Svc"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The definition of the timers themselves. */
 | 
			
		||||
typedef struct tmrTimerControl
 | 
			
		||||
{
 | 
			
		||||
@ -276,7 +282,7 @@ BaseType_t xReturn = pdFAIL;
 | 
			
		||||
 | 
			
		||||
			vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
 | 
			
		||||
			xTimerTaskHandle = xTaskCreateStatic(	prvTimerTask,
 | 
			
		||||
													"Tmr Svc",
 | 
			
		||||
													tmrTIMER_SERVICE_TASK_NAME,
 | 
			
		||||
													ulTimerTaskStackSize,
 | 
			
		||||
													NULL,
 | 
			
		||||
													( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
 | 
			
		||||
@ -291,7 +297,7 @@ BaseType_t xReturn = pdFAIL;
 | 
			
		||||
		#else
 | 
			
		||||
		{
 | 
			
		||||
			xReturn = xTaskCreate(	prvTimerTask,
 | 
			
		||||
									"Tmr Svc",
 | 
			
		||||
									tmrTIMER_SERVICE_TASK_NAME,
 | 
			
		||||
									configTIMER_TASK_STACK_DEPTH,
 | 
			
		||||
									NULL,
 | 
			
		||||
									( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user