]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Common/Minimal/GenQTest.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / Common / Minimal / GenQTest.c
index 2a303652d265455f497203a24e8396650eb90d09..07b72967d8a34dbcbff7732be7fbb1b9a6ffef7b 100644 (file)
@@ -1,67 +1,30 @@
 /*\r
-    FreeRTOS V8.1.2 - Copyright (C) 2014 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
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    FreeRTOS provides completely free yet professionally developed,    *\r
-     *    robust, strictly quality controlled, supported, and cross          *\r
-     *    platform software that has become a de facto standard.             *\r
-     *                                                                       *\r
-     *    Help yourself get started quickly and support the FreeRTOS         *\r
-     *    project by purchasing a FreeRTOS tutorial book, reference          *\r
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
-     *                                                                       *\r
-     *    Thank you!                                                         *\r
-     *                                                                       *\r
-    ***************************************************************************\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
-    >>!   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
-    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 from the following\r
-    link: http://www.freertos.org/a00114.html\r
-\r
-    1 tab == 4 spaces!\r
-\r
-    ***************************************************************************\r
-     *                                                                       *\r
-     *    Having a problem?  Start by reading the FAQ "My application does   *\r
-     *    not run, what could be wrong?"                                     *\r
-     *                                                                       *\r
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
-     *                                                                       *\r
-    ***************************************************************************\r
-\r
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
-    license and Real Time Engineers Ltd. contact details.\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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
-    licenses offer ticketed support, indemnification and 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.0\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. If you wish to use our Amazon\r
+ * FreeRTOS name, please do so in a fair use way that does not cause confusion.\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
 \r
 /*\r
@@ -73,7 +36,7 @@
  * prvLowPriorityMutexTask() prototypes below for more information.\r
  */\r
 \r
-\r
+/* Standard includes. */\r
 #include <stdlib.h>\r
 \r
 /* Scheduler include files. */\r
 #include "GenQTest.h"\r
 \r
 #define genqQUEUE_LENGTH               ( 5 )\r
-#define genqNO_BLOCK                   ( 0 )\r
+#define intsemNO_BLOCK                 ( 0 )\r
+#define genqSHORT_BLOCK                        ( pdMS_TO_TICKS( 2 ) )\r
 \r
 #define genqMUTEX_LOW_PRIORITY         ( tskIDLE_PRIORITY )\r
 #define genqMUTEX_TEST_PRIORITY                ( tskIDLE_PRIORITY + 1 )\r
 #define genqMUTEX_MEDIUM_PRIORITY      ( tskIDLE_PRIORITY + 2 )\r
 #define genqMUTEX_HIGH_PRIORITY                ( tskIDLE_PRIORITY + 3 )\r
 \r
-#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -116,33 +79,32 @@ static void prvSendFrontAndBackTest( void *pvParameters );
  * priority task while it holds the inherited high priority.  Once the mutex\r
  * is returned the task with the inherited priority returns to its original\r
  * low priority, and is therefore immediately preempted by first the high\r
- * priority task and then the medium prioroity task before it can continue.\r
+ * priority task and then the medium priority task before it can continue.\r
  */\r
 static void prvLowPriorityMutexTask( void *pvParameters );\r
 static void prvMediumPriorityMutexTask( void *pvParameters );\r
 static void prvHighPriorityMutexTask( void *pvParameters );\r
 \r
 /*\r
- * Exercises the priority inheritance when a task takes two mutexes, returning\r
- * them in a different order to which they were taken.\r
+ * Tests the behaviour when a low priority task inherits the priority of a\r
+ * higher priority task when taking two mutexes, and returns the mutexes in\r
+ * first the same order as the two mutexes were obtained, and second the\r
+ * opposite order as the two mutexes were obtained.\r
  */\r
+static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
 static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
 \r
-/*\r
- * Exercises the priority inheritance when a task takes two mutexes, returning\r
- * them in the same order in which they were taken.\r
- */\r
-static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
+#if( INCLUDE_xTaskAbortDelay == 1 )\r
 \r
-/*\r
- * Task that receives an a mutex that is given from an interrupt - although\r
- * generally mutexes should not be used given in interrupts (and definitely\r
- * never taken in an interrupt) there are some circumstances when it may be\r
- * desirable.  NOTE:  This function is not declared static to prevent compiler\r
- * warnings being generated in demos where the function is declared but not\r
- * used.\r
- */\r
-void vInterruptMutexTask( void *pvParameters );\r
+       #if( configUSE_PREEMPTION == 0 )\r
+               #error The additional tests included when INCLUDE_xTaskAbortDelay is 1 expect preemption to be used.\r
+       #endif\r
+\r
+       /* Tests the behaviour when a low priority task inherits the priority of a\r
+       high priority task only for the high priority task to timeout before\r
+       obtaining the mutex. */\r
+       static void prvHighPriorityTimeout( SemaphoreHandle_t xMutex );\r
+#endif\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -158,14 +120,20 @@ static volatile uint32_t ulLoopCounter2 = 0;
 /* The variable that is guarded by the mutex in the mutex demo tasks. */\r
 static volatile uint32_t ulGuardedVariable = 0;\r
 \r
-/* Handles used in the mutext test to suspend and resume the high and medium\r
+/* Handles used in the mutex test to suspend and resume the high and medium\r
 priority mutex test tasks. */\r
 static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;\r
 \r
-/* A mutex which is given from an interrupt - although generally mutexes should\r
-not be used given in interrupts (and definitely never taken in an interrupt)\r
-there are some circumstances when it may be desirable. */\r
-static SemaphoreHandle_t xISRMutex = NULL;\r
+/* If INCLUDE_xTaskAbortDelay is 1 additional tests are performed, requiring an\r
+additional task. */\r
+#if( INCLUDE_xTaskAbortDelay == 1 )\r
+       static TaskHandle_t xSecondMediumPriorityMutexTask;\r
+#endif\r
+\r
+/* Lets the high priority semaphore task know that its wait for the semaphore\r
+was aborted, in which case not being able to obtain the semaphore is not to be\r
+considered an error. */\r
+static volatile BaseType_t xBlockWasAborted = pdFALSE;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -174,57 +142,60 @@ void vStartGenericQueueTasks( UBaseType_t uxPriority )
 QueueHandle_t xQueue;\r
 SemaphoreHandle_t xMutex;\r
 \r
-       xISRMutex = xSemaphoreCreateMutex();\r
-       configASSERT( xISRMutex );\r
-\r
        /* Create the queue that we are going to use for the\r
        prvSendFrontAndBackTest demo. */\r
        xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );\r
 \r
-       /* vQueueAddToRegistry() adds the queue to the queue registry, if one is\r
-       in use.  The queue registry is provided as a means for kernel aware\r
-       debuggers to locate queues and has no purpose if a kernel aware debugger\r
-       is not being used.  The call to vQueueAddToRegistry() will be removed\r
-       by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is\r
-       defined to be less than 1. */\r
-       vQueueAddToRegistry( xQueue, "Gen_Queue_Test" );\r
+       if( xQueue != NULL )\r
+       {\r
+               /* vQueueAddToRegistry() adds the queue to the queue registry, if one\r
+               is in use.  The queue registry is provided as a means for kernel aware\r
+               debuggers to locate queues and has no purpose if a kernel aware debugger\r
+               is not being used.  The call to vQueueAddToRegistry() will be removed\r
+               by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is\r
+               defined to be less than 1. */\r
+               vQueueAddToRegistry( xQueue, "Gen_Queue_Test" );\r
 \r
-       /* Create the demo task and pass it the queue just created.  We are\r
-       passing the queue handle by value so it does not matter that it is\r
-       declared on the stack here. */\r
-       xTaskCreate( prvSendFrontAndBackTest, "GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );\r
+               /* Create the demo task and pass it the queue just created.  We are\r
+               passing the queue handle by value so it does not matter that it is\r
+               declared on the stack here. */\r
+               xTaskCreate( prvSendFrontAndBackTest, "GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );\r
+       }\r
 \r
        /* Create the mutex used by the prvMutexTest task. */\r
        xMutex = xSemaphoreCreateMutex();\r
 \r
-       /* vQueueAddToRegistry() adds the mutex to the registry, if one is\r
-       in use.  The registry is provided as a means for kernel aware\r
-       debuggers to locate mutexes and has no purpose if a kernel aware debugger\r
-       is not being used.  The call to vQueueAddToRegistry() will be removed\r
-       by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is\r
-       defined to be less than 1. */\r
-       vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" );\r
-\r
-       /* Create the mutex demo tasks and pass it the mutex just created.  We are\r
-       passing the mutex handle by value so it does not matter that it is declared\r
-       on the stack here. */\r
-       xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
-       xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
-       xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
-\r
-       /* Only when the windows simulator is being used - create the task that\r
-       receives a mutex from an interrupt. */\r
-       #ifdef _WINDOWS_\r
-       {\r
-               xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL );\r
+       if( xMutex != NULL )\r
+       {\r
+               /* vQueueAddToRegistry() adds the mutex to the registry, if one is\r
+               in use.  The registry is provided as a means for kernel aware\r
+               debuggers to locate mutexes and has no purpose if a kernel aware\r
+               debugger is not being used.  The call to vQueueAddToRegistry() will be\r
+               removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not\r
+               defined or is defined to be less than 1. */\r
+               vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" );\r
+\r
+               /* Create the mutex demo tasks and pass it the mutex just created.  We\r
+               are passing the mutex handle by value so it does not matter that it is\r
+               declared on the stack here. */\r
+               xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
+               xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
+               xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
+\r
+               /* If INCLUDE_xTaskAbortDelay is set then additional tests are performed,\r
+               requiring two instances of prvHighPriorityMutexTask(). */\r
+               #if( INCLUDE_xTaskAbortDelay == 1 )\r
+               {\r
+                       xTaskCreate( prvHighPriorityMutexTask, "MuHigh2", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_MEDIUM_PRIORITY, &xSecondMediumPriorityMutexTask );\r
+               }\r
+               #endif /* INCLUDE_xTaskAbortDelay */\r
        }\r
-       #endif /* __WINDOWS__ */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 static void prvSendFrontAndBackTest( void *pvParameters )\r
 {\r
-uint32_t ulData, ulData2;\r
+uint32_t ulData, ulData2, ulLoopCounterSnapshot;\r
 QueueHandle_t xQueue;\r
 \r
        #ifdef USE_STDIO\r
@@ -244,14 +215,15 @@ QueueHandle_t xQueue;
                should have the same efect as sending it to the front of the queue.\r
 \r
                First send to the front and check everything is as expected. */\r
-               xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+               ulLoopCounterSnapshot = ulLoopCounter;\r
+               xQueueSendToFront( xQueue, ( void * ) &ulLoopCounterSnapshot, intsemNO_BLOCK );\r
 \r
                if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueReceive( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -270,14 +242,15 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );\r
+               ulLoopCounterSnapshot = ulLoopCounter;\r
+               xQueueSendToBack( xQueue, ( void * ) &ulLoopCounterSnapshot, intsemNO_BLOCK );\r
 \r
                if( uxQueueMessagesWaiting( xQueue ) != 1 )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueReceive( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -287,8 +260,8 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               /* The data we sent to the queue should equal the data we just received\r
-               from the queue. */\r
+               /* The data sent to the queue should equal the data just received from\r
+               the queue. */\r
                if( ulLoopCounter != ulData )\r
                {\r
                        xErrorDetected = pdTRUE;\r
@@ -303,7 +276,7 @@ QueueHandle_t xQueue;
                /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */\r
                for( ulData = 2; ulData < 5; ulData++ )\r
                {\r
-                       xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+                       xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK );\r
                }\r
 \r
                /* Now the order in the queue should be 2, 3, 4, with 2 being the first\r
@@ -313,9 +286,9 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
                ulData = 1;\r
-               xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+               xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );\r
                ulData = 0;\r
-               xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );\r
+               xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );\r
 \r
                /* Now the queue should be full, and when we read the data out we\r
                should receive 0, 1, 2, 3, 4. */\r
@@ -324,12 +297,12 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -342,7 +315,7 @@ QueueHandle_t xQueue;
                for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )\r
                {\r
                        /* Try peeking the data first. */\r
-                       if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueuePeek( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -356,7 +329,7 @@ QueueHandle_t xQueue;
                        /* Now try receiving the data for real.  The value should be the\r
                        same.  Clobber the value first so we know we really received it. */\r
                        ulData2 = ~ulData2;\r
-                       if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -380,12 +353,12 @@ QueueHandle_t xQueue;
 \r
                /* Our queue is empty once more, add 10, 11 to the back. */\r
                ulData = 10;\r
-               if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
                ulData = 11;\r
-               if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )\r
+               if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -399,7 +372,7 @@ QueueHandle_t xQueue;
                front. */\r
                for( ulData = 9; ulData >= 7; ulData-- )\r
                {\r
-                       if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -412,12 +385,12 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
-               if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )\r
+               if( xQueueSendToBack( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != errQUEUE_FULL )\r
                {\r
                        xErrorDetected = pdTRUE;\r
                }\r
@@ -429,7 +402,7 @@ QueueHandle_t xQueue;
                /* Check the data we read out is in the expected order. */\r
                for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )\r
                {\r
-                       if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )\r
+                       if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )\r
                        {\r
                                xErrorDetected = pdTRUE;\r
                        }\r
@@ -445,15 +418,208 @@ QueueHandle_t xQueue;
                        xErrorDetected = pdTRUE;\r
                }\r
 \r
+               /* Increment the loop counter to indicate these tasks are still\r
+               executing. */\r
                ulLoopCounter++;\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if( INCLUDE_xTaskAbortDelay == 1 )\r
+\r
+       static void prvHighPriorityTimeout( SemaphoreHandle_t xMutex )\r
+       {\r
+       static UBaseType_t uxLoopCount = 0;\r
+\r
+               /* The tests in this function are very similar, the slight variations\r
+               are for code coverage purposes. */\r
+\r
+               /* Take the mutex.  It should be available now. */\r
+               if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This task's priority should be as per that assigned when the task was\r
+               created. */\r
+               if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Now unsuspend the high priority task.  This will attempt to take the\r
+               mutex, and block when it finds it cannot obtain it. */\r
+               vTaskResume( xHighPriorityMutexTask );\r
+\r
+               /* This task should now have inherited the priority of the high priority\r
+               task as by now the high priority task will have attempted to obtain the\r
+               mutex. */\r
+               if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* Unblock a second medium priority task.  It too will attempt to take\r
+               the mutex and enter the Blocked state - it won't run yet though as this\r
+               task has inherited a priority above it. */\r
+               vTaskResume( xSecondMediumPriorityMutexTask );\r
+\r
+               /* This task should still have the priority of the high priority task as\r
+               that had already been inherited as is the highest priority of the three\r
+               tasks using the mutex. */\r
+               if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* On some loops, block for a short while to provide additional\r
+               code coverage.  Blocking here will allow the medium priority task to\r
+               execute and so also block on the mutex so when the high priority task\r
+               causes this task to disinherit the high priority it is inherited down to\r
+               the priority of the medium priority task.  When there is no delay the\r
+               medium priority task will not run until after the disinheritance, so\r
+               this task will disinherit back to its base priority, then only up to the\r
+               medium priority after the medium priority has executed. */\r
+               vTaskDelay( uxLoopCount & ( UBaseType_t ) 0x07 );\r
+\r
+               /* Now force the high priority task to unblock.  It will fail to obtain\r
+               the mutex and go back to the suspended state - allowing this task to\r
+               execute again.  xBlockWasAborted is set to pdTRUE so the higher priority\r
+               task knows that its failure to obtain the semaphore is not an error. */\r
+               xBlockWasAborted = pdTRUE;\r
+               if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This task has inherited the priority of xHighPriorityMutexTask so\r
+               could still be running even though xHighPriorityMutexTask is no longer\r
+               blocked.  Delay for a short while to ensure xHighPriorityMutexTask gets\r
+               a chance to run - indicated by this task changing priority.  It should\r
+               disinherit the high priority task, but then inherit the priority of the\r
+               medium priority task that is waiting for the same mutex. */\r
+               while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )\r
+               {\r
+                       /* If this task gets stuck here then the check variables will stop\r
+                       incrementing and the check task will detect the error. */\r
+                       vTaskDelay( genqSHORT_BLOCK );\r
+               }\r
+\r
+               /* Now force the medium priority task to unblock.  xBlockWasAborted is\r
+               set to pdTRUE so the medium priority task knows that its failure to\r
+               obtain the semaphore is not an error. */\r
+               xBlockWasAborted = pdTRUE;\r
+               if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This time no other tasks are waiting for the mutex, so this task\r
+               should return to its base priority.  This might not happen straight\r
+               away as it is running at the same priority as the task it just\r
+               unblocked. */\r
+               while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+               {\r
+                       /* If this task gets stuck here then the check variables will stop\r
+                       incrementing and the check task will detect the error. */\r
+                       vTaskDelay( genqSHORT_BLOCK );\r
+               }\r
+\r
+               /* Give the semaphore back ready for the next test. */\r
+               xSemaphoreGive( xMutex );\r
+\r
+               configASSERT( xErrorDetected == pdFALSE );\r
+\r
+\r
+\r
+               /* Now do the same again, but this time unsuspend the tasks in the\r
+               opposite order.  This takes a different path though the code because\r
+               when the high priority task has its block aborted there is already\r
+               another task in the list of tasks waiting for the mutex, and the\r
+               low priority task drops down to that priority, rather than dropping\r
+               down to its base priority before inheriting the priority of the medium\r
+               priority task. */\r
+               if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This time unsuspend the medium priority task first.  This will\r
+               attempt to take the mutex, and block when it finds it cannot obtain it. */\r
+               vTaskResume( xSecondMediumPriorityMutexTask );\r
+\r
+               /* This time this task should now have inherited the priority of the\r
+               medium task. */\r
+               if( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This time the high priority task in unsuspended second. */\r
+               vTaskResume( xHighPriorityMutexTask );\r
+\r
+               /* The high priority task should already have run, causing this task to\r
+               inherit a priority for the second time. */\r
+               if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               /* This time, when the high priority task has its delay aborted and it\r
+               fails to obtain the mutex this task will immediately have its priority\r
+               lowered down to that of the highest priority task waiting on the mutex,\r
+               which is the medium priority task. */\r
+               xBlockWasAborted = pdTRUE;\r
+               if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )\r
+               {\r
+                       /* If this task gets stuck here then the check variables will stop\r
+                       incrementing and the check task will detect the error. */\r
+                       vTaskDelay( genqSHORT_BLOCK );\r
+               }\r
+\r
+               /* And finally, when the medium priority task also have its delay\r
+               aborted there are no other tasks waiting for the mutex so this task\r
+               returns to its base priority. */\r
+               xBlockWasAborted = pdTRUE;\r
+               if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+\r
+               while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+               {\r
+                       /* If this task gets stuck here then the check variables will stop\r
+                       incrementing and the check task will detect the error. */\r
+                       vTaskDelay( genqSHORT_BLOCK );\r
+               }\r
+\r
+               /* Give the semaphore back ready for the next test. */\r
+               xSemaphoreGive( xMutex );\r
+\r
+               configASSERT( xErrorDetected == pdFALSE );\r
+\r
+               /* uxLoopCount is used to add a variable delay, and in-so-doing provide\r
+               additional code coverage. */\r
+               uxLoopCount++;\r
+       }\r
+\r
+#endif /* INCLUDE_xTaskAbortDelay == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
 static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )\r
 {\r
        /* Take the mutex.  It should be available now. */\r
-       if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -484,15 +650,16 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
        }\r
        #endif /* INCLUDE_eTaskGetState */\r
 \r
-       /* The priority of the high priority task should now have been inherited\r
-       as by now it will have attempted to get the mutex. */\r
+       /* This task should now have inherited the priority of the high priority\r
+       task as by now the high priority task will have attempted to obtain the\r
+       mutex. */\r
        if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
 \r
        /* Attempt to set the priority of this task to the test priority -\r
-       between the     idle priority and the medium/high test priorities, but the\r
+       between the idle priority and the medium/high test priorities, but the\r
        actual priority should remain at the high priority. */\r
        vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );\r
        if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
@@ -513,7 +680,7 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
        }\r
 \r
        /* Take the local mutex too, so two mutexes are now held. */\r
-       if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xLocalMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -583,7 +750,7 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
 static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )\r
 {\r
        /* Take the mutex.  It should be available now. */\r
-       if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
@@ -614,8 +781,9 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
        }\r
        #endif /* INCLUDE_eTaskGetState */\r
 \r
-       /* The priority of the high priority task should now have been inherited\r
-       as by now it will have attempted to get the mutex. */\r
+       /* This task should now have inherited the priority of the high priority\r
+       task as by now the high priority task will have attempted to obtain the\r
+       mutex. */\r
        if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
        {\r
                xErrorDetected = pdTRUE;\r
@@ -634,13 +802,13 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
        }\r
 \r
        /* Take the local mutex too, so two mutexes are now held. */\r
-       if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
+       if( xSemaphoreTake( xLocalMutex, intsemNO_BLOCK ) != pdPASS )\r
        {\r
                xErrorDetected = pdTRUE;\r
        }\r
 \r
        /* When the local semaphore is given back the priority of this task should\r
-       not     yet be disinherited because the shared mutex is still held.  This is a\r
+       not yet be disinherited because the shared mutex is still held.  This is a\r
        simplification to allow FreeRTOS to be integrated with middleware that\r
        attempts to hold multiple mutexes without bloating the code with complex\r
        algorithms.  It is possible that the high priority mutex task will\r
@@ -737,6 +905,15 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
                #if configUSE_PREEMPTION == 0\r
                        taskYIELD();\r
                #endif\r
+\r
+               #if( INCLUDE_xTaskAbortDelay == 1 )\r
+               {\r
+                       /* Tests the behaviour when a low priority task inherits the\r
+                       priority of a high priority task only for the high priority task to\r
+                       timeout before obtaining the mutex. */\r
+                       prvHighPriorityTimeout( xMutex );\r
+               }\r
+               #endif\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -769,64 +946,35 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
                priority task will unsuspend this task when required. */\r
                vTaskSuspend( NULL );\r
 \r
-               /* When this task unsuspends all it does is attempt to obtain\r
-               the mutex.  It should find the mutex is not available so a\r
-               block time is specified. */\r
+               /* When this task unsuspends all it does is attempt to obtain the\r
+               mutex.  It should find the mutex is not available so a block time is\r
+               specified. */\r
                if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )\r
                {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* When the mutex is eventually obtained it is just given back before\r
-               returning to suspend ready for the next cycle. */\r
-               if( xSemaphoreGive( xMutex ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* NOTE: This function is not declared static to prevent compiler warnings in\r
-demos where the function is declared but not used. */\r
-void vInterruptMutexTask( void *pvParameters )\r
-{\r
-const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
-volatile uint32_t ulLoops = 0;\r
-\r
-       /* Just to avoid compiler warnings. */\r
-       ( void ) pvParameters;\r
-\r
-       for( ;; )\r
-       {\r
-               /* Has to wait longer than the time between gives to make sure it\r
-               should definitely have received the mutex. */\r
-               if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
+                       /* This task would expect to obtain the mutex unless its wait for\r
+                       the mutex was aborted. */\r
+                       if( xBlockWasAborted == pdFALSE )\r
+                       {\r
+                               xErrorDetected = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               xBlockWasAborted = pdFALSE;\r
+                       }\r
                }\r
                else\r
                {\r
-                       ulLoops++;\r
+                       /* When the mutex is eventually obtained it is just given back before\r
+                       returning to suspend ready for the next cycle. */\r
+                       if( xSemaphoreGive( xMutex ) != pdPASS )\r
+                       {\r
+                               xErrorDetected = pdTRUE;\r
+                       }\r
                }\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vMutexISRInteractionTest( void )\r
-{\r
-static TickType_t xLastGiveTime = 0;\r
-TickType_t xTimeNow;\r
-\r
-       xTimeNow = xTaskGetTickCountFromISR();\r
-       if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )\r
-       {\r
-               configASSERT( xISRMutex );\r
-               xSemaphoreGiveFromISR( xISRMutex, NULL );\r
-               xLastGiveTime = xTimeNow;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
 \r
 /* This is called to check that all the created tasks are still running. */\r
 BaseType_t xAreGenericQueueTasksStillRunning( void )\r