2 * FreeRTOS Kernel V10.0.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software. If you wish to use our Amazon
\r
14 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
30 * This file contains some test scenarios that ensure tasks respond correctly
\r
31 * to xTaskAbortDelay() calls.
\r
34 /* Standard includes. */
\r
37 /* Kernel includes. */
\r
38 #include "FreeRTOS.h"
\r
42 #include "event_groups.h"
\r
44 /* Demo includes. */
\r
45 #include "AbortDelay.h"
\r
47 /* This file can only be used if the functionality it tests is included in the
\r
48 build. Remove the whole file if this is not the case. */
\r
49 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
51 #if( INCLUDE_xTaskGetHandle != 1 )
\r
52 #error This test file uses the xTaskGetHandle() API function so INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h.
\r
55 /* Task priorities. Allow these to be overridden. */
\r
56 #ifndef abtCONTROLLING_PRIORITY
\r
57 #define abtCONTROLLING_PRIORITY ( configMAX_PRIORITIES - 3 )
\r
60 #ifndef abtBLOCKING_PRIORITY
\r
61 #define abtBLOCKING_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
64 /* The tests that are performed. */
\r
65 #define abtNOTIFY_WAIT_ABORTS 0
\r
66 #define abtNOTIFY_TAKE_ABORTS 1
\r
67 #define abtDELAY_ABORTS 2
\r
68 #define abtDELAY_UNTIL_ABORTS 3
\r
69 #define abtSEMAPHORE_TAKE_ABORTS 4
\r
70 #define abtEVENT_GROUP_ABORTS 5
\r
71 #define abtQUEUE_SEND_ABORTS 6
\r
72 #define abtMAX_TESTS 7
\r
74 /*-----------------------------------------------------------*/
\r
77 * The two test tasks. The controlling task specifies which test to executed.
\r
78 * More information is provided in the comments within the tasks.
\r
80 static void prvControllingTask( void *pvParameters );
\r
81 static void prvBlockingTask( void *pvParameters );
\r
84 * Test functions called by the blocking task. Each function follows the same
\r
85 * pattern, but the way the task blocks is different in each case.
\r
87 * In each function three blocking calls are made. The first and third
\r
88 * blocking call is expected to time out, while the middle blocking call is
\r
89 * expected to be aborted by the controlling task half way through the block
\r
92 static void prvTestAbortingTaskNotifyWait( void );
\r
93 static void prvTestAbortingTaskNotifyTake( void );
\r
94 static void prvTestAbortingTaskDelay( void );
\r
95 static void prvTestAbortingTaskDelayUntil( void );
\r
96 static void prvTestAbortingSemaphoreTake( void );
\r
97 static void prvTestAbortingEventGroupWait( void );
\r
98 static void prvTestAbortingQueueSend( void );
\r
101 * Checks the amount of time a task spent in the Blocked state is within the
\r
104 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );
\r
106 /*-----------------------------------------------------------*/
\r
108 /* Used to ensure that tasks are still executing without error. */
\r
109 static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;
\r
110 static volatile BaseType_t xErrorOccurred = pdFALSE;
\r
112 /* Each task needs to know the other tasks handle so they can send signals to
\r
113 each other. The handle is obtained from the task's name. */
\r
114 static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";
\r
116 /* The maximum amount of time a task will block for. */
\r
117 const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );
\r
118 const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );
\r
120 /* The actual block time is dependent on the priority of other tasks in the
\r
121 system so the actual block time might be greater than that expected, but it
\r
122 should be within an acceptable upper bound. */
\r
123 const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );
\r
125 /*-----------------------------------------------------------*/
\r
127 void vCreateAbortDelayTasks( void )
\r
129 /* Create the two test tasks described above. */
\r
130 xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );
\r
131 xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );
\r
133 /*-----------------------------------------------------------*/
\r
135 static void prvControllingTask( void *pvParameters )
\r
137 TaskHandle_t xBlockingTask;
\r
138 uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;
\r
139 TickType_t xTimeAtStart;
\r
140 const TickType_t xStartMargin = 2UL;
\r
142 /* Just to remove compiler warnings. */
\r
143 ( void ) pvParameters;
\r
145 xBlockingTask = xTaskGetHandle( pcBlockingTaskName );
\r
146 configASSERT( xBlockingTask );
\r
150 /* Tell the secondary task to perform the next test. */
\r
151 xTimeAtStart = xTaskGetTickCount();
\r
152 xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
\r
154 /* The secondary task has a higher priority, so will now be in the
\r
155 Blocked state to wait for a maximum of xMaxBlockTime. It expects that
\r
156 period to complete with a timeout. It will then block for
\r
157 xMaxBlockTimeAgain, but this time it expects to the block time to abort
\r
158 half way through. Block until it is time to send the abort to the
\r
159 secondary task. xStartMargin is used because this task takes timing
\r
160 from the beginning of the test, whereas the blocking task takes timing
\r
161 from the entry into the Blocked state - and as the tasks run at
\r
162 different priorities, there may be some discrepancy. Also, temporarily
\r
163 raise the priority of the controlling task to that of the blocking
\r
164 task to minimise discrepancies. */
\r
165 vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );
\r
166 vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
\r
167 if( xTaskAbortDelay( xBlockingTask ) != pdPASS )
\r
169 xErrorOccurred = pdTRUE;
\r
172 /* Reset the priority to the normal controlling priority. */
\r
173 vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
\r
175 /* Now wait to be notified that the secondary task has completed its
\r
177 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
\r
179 /* Did the entire test run for the expected time, which is two full
\r
180 block times plus the half block time caused by calling
\r
181 xTaskAbortDelay()? */
\r
182 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
\r
184 /* Move onto the next test. */
\r
187 if( ulTestToPerform >= abtMAX_TESTS )
\r
189 ulTestToPerform = 0;
\r
192 /* To indicate this task is still executing. */
\r
193 xControllingCycles++;
\r
196 /*-----------------------------------------------------------*/
\r
198 static void prvBlockingTask( void *pvParameters )
\r
200 TaskHandle_t xControllingTask;
\r
201 uint32_t ulNotificationValue;
\r
202 const uint32_t ulMax = 0xffffffffUL;
\r
204 /* Just to remove compiler warnings. */
\r
205 ( void ) pvParameters;
\r
207 xControllingTask = xTaskGetHandle( pcControllingTaskName );
\r
208 configASSERT( xControllingTask );
\r
212 /* Wait to be notified of the test that is to be performed next. */
\r
213 xTaskNotifyWait( 0, ulMax, &ulNotificationValue, portMAX_DELAY );
\r
215 switch( ulNotificationValue )
\r
217 case abtNOTIFY_WAIT_ABORTS:
\r
218 prvTestAbortingTaskNotifyWait();
\r
221 case abtNOTIFY_TAKE_ABORTS:
\r
222 prvTestAbortingTaskNotifyTake();
\r
225 case abtDELAY_ABORTS:
\r
226 prvTestAbortingTaskDelay();
\r
229 case abtDELAY_UNTIL_ABORTS:
\r
230 prvTestAbortingTaskDelayUntil();
\r
233 case abtSEMAPHORE_TAKE_ABORTS:
\r
234 prvTestAbortingSemaphoreTake();
\r
237 case abtEVENT_GROUP_ABORTS:
\r
238 prvTestAbortingEventGroupWait();
\r
241 case abtQUEUE_SEND_ABORTS:
\r
242 prvTestAbortingQueueSend();
\r
246 /* Should not get here. */
\r
250 /* Let the primary task know the test is complete. */
\r
251 xTaskNotifyGive( xControllingTask );
\r
253 /* To indicate this task is still executing. */
\r
257 /*-----------------------------------------------------------*/
\r
259 static void prvTestAbortingTaskDelayUntil( void )
\r
261 TickType_t xTimeAtStart, xLastBlockTime;
\r
263 /* Note the time before the delay so the length of the delay is known. */
\r
264 xTimeAtStart = xTaskGetTickCount();
\r
266 /* Take a copy of the time as it is updated in the call to
\r
267 vTaskDelayUntil() but its original value is needed to determine the actual
\r
268 time spend in the Blocked state. */
\r
269 xLastBlockTime = xTimeAtStart;
\r
271 /* This first delay should just time out. */
\r
272 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
273 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
275 /* This second delay should be aborted by the primary task half way
\r
276 through. Again take a copy of the time as it is updated in the call to
\r
277 vTaskDelayUntil() buts its original value is needed to determine the amount
\r
278 of time actually spent in the Blocked state. */
\r
279 xTimeAtStart = xTaskGetTickCount();
\r
280 xLastBlockTime = xTimeAtStart;
\r
281 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
282 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
284 /* As with the other tests, the third block period should not time out. */
\r
285 xTimeAtStart = xTaskGetTickCount();
\r
286 xLastBlockTime = xTimeAtStart;
\r
287 vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
\r
288 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
290 /*-----------------------------------------------------------*/
\r
292 static void prvTestAbortingTaskDelay( void )
\r
294 TickType_t xTimeAtStart;
\r
296 /* Note the time before the delay so the length of the delay is known. */
\r
297 xTimeAtStart = xTaskGetTickCount();
\r
299 /* This first delay should just time out. */
\r
300 vTaskDelay( xMaxBlockTime );
\r
301 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
303 /* Note the time before the delay so the length of the delay is known. */
\r
304 xTimeAtStart = xTaskGetTickCount();
\r
306 /* This second delay should be aborted by the primary task half way
\r
308 vTaskDelay( xMaxBlockTime );
\r
309 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
311 /* Note the time before the delay so the length of the delay is known. */
\r
312 xTimeAtStart = xTaskGetTickCount();
\r
314 /* This third delay should just time out again. */
\r
315 vTaskDelay( xMaxBlockTime );
\r
316 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
318 /*-----------------------------------------------------------*/
\r
320 static void prvTestAbortingTaskNotifyTake( void )
\r
322 TickType_t xTimeAtStart;
\r
325 /* Note the time before the delay so the length of the delay is known. */
\r
326 xTimeAtStart = xTaskGetTickCount();
\r
328 /* This first delay should just time out. */
\r
329 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
330 if( ulReturn != 0 )
\r
332 xErrorOccurred = pdTRUE;
\r
334 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
336 /* Note the time before the delay so the length of the delay is known. */
\r
337 xTimeAtStart = xTaskGetTickCount();
\r
339 /* This second delay should be aborted by the primary task half way
\r
341 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
342 if( ulReturn != 0 )
\r
344 xErrorOccurred = pdTRUE;
\r
346 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
348 /* Note the time before the delay so the length of the delay is known. */
\r
349 xTimeAtStart = xTaskGetTickCount();
\r
351 /* This third delay should just time out again. */
\r
352 ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
\r
353 if( ulReturn != 0 )
\r
355 xErrorOccurred = pdTRUE;
\r
357 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
359 /*-----------------------------------------------------------*/
\r
361 static void prvTestAbortingEventGroupWait( void )
\r
363 TickType_t xTimeAtStart;
\r
364 EventGroupHandle_t xEventGroup;
\r
365 EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
\r
367 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
369 static StaticEventGroup_t xEventGroupBuffer;
\r
371 /* Create the event group. Statically allocated memory is used so the
\r
372 creation cannot fail. */
\r
373 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
377 xEventGroup = xEventGroupCreate();
\r
378 configASSERT( xEventGroup );
\r
382 /* Note the time before the delay so the length of the delay is known. */
\r
383 xTimeAtStart = xTaskGetTickCount();
\r
385 /* This first delay should just time out. */
\r
386 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
387 if( xReturn != 0x00 )
\r
389 xErrorOccurred = pdTRUE;
\r
391 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
393 /* Note the time before the delay so the length of the delay is known. */
\r
394 xTimeAtStart = xTaskGetTickCount();
\r
396 /* This second delay should be aborted by the primary task half way
\r
398 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
399 if( xReturn != 0x00 )
\r
401 xErrorOccurred = pdTRUE;
\r
403 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
405 /* Note the time before the delay so the length of the delay is known. */
\r
406 xTimeAtStart = xTaskGetTickCount();
\r
408 /* This third delay should just time out again. */
\r
409 xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
\r
410 if( xReturn != 0x00 )
\r
412 xErrorOccurred = pdTRUE;
\r
414 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
416 /* Not really necessary in this case, but for completeness. */
\r
417 vEventGroupDelete( xEventGroup );
\r
419 /*-----------------------------------------------------------*/
\r
421 static void prvTestAbortingQueueSend( void )
\r
423 TickType_t xTimeAtStart;
\r
424 BaseType_t xReturn;
\r
425 const UBaseType_t xQueueLength = ( UBaseType_t ) 1;
\r
426 QueueHandle_t xQueue;
\r
427 uint8_t ucItemToQueue;
\r
429 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
431 static StaticQueue_t xQueueBuffer;
\r
432 static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
\r
434 /* Create the queue. Statically allocated memory is used so the
\r
435 creation cannot fail. */
\r
436 xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
\r
440 xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
\r
441 configASSERT( xQueue );
\r
445 /* This function tests aborting when in the blocked state waiting to send,
\r
446 so the queue must be full. There is only one space in the queue. */
\r
447 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
448 if( xReturn != pdPASS )
\r
450 xErrorOccurred = pdTRUE;
\r
453 /* Note the time before the delay so the length of the delay is known. */
\r
454 xTimeAtStart = xTaskGetTickCount();
\r
456 /* This first delay should just time out. */
\r
457 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
458 if( xReturn != pdFALSE )
\r
460 xErrorOccurred = pdTRUE;
\r
462 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
464 /* Note the time before the delay so the length of the delay is known. */
\r
465 xTimeAtStart = xTaskGetTickCount();
\r
467 /* This second delay should be aborted by the primary task half way
\r
469 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
470 if( xReturn != pdFALSE )
\r
472 xErrorOccurred = pdTRUE;
\r
474 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
476 /* Note the time before the delay so the length of the delay is known. */
\r
477 xTimeAtStart = xTaskGetTickCount();
\r
479 /* This third delay should just time out again. */
\r
480 xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
\r
481 if( xReturn != pdFALSE )
\r
483 xErrorOccurred = pdTRUE;
\r
485 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
487 /* Not really necessary in this case, but for completeness. */
\r
488 vQueueDelete( xQueue );
\r
490 /*-----------------------------------------------------------*/
\r
492 static void prvTestAbortingSemaphoreTake( void )
\r
494 TickType_t xTimeAtStart;
\r
495 BaseType_t xReturn;
\r
496 SemaphoreHandle_t xSemaphore;
\r
498 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
500 static StaticSemaphore_t xSemaphoreBuffer;
\r
502 /* Create the semaphore. Statically allocated memory is used so the
\r
503 creation cannot fail. */
\r
504 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
508 xSemaphore = xSemaphoreCreateBinary();
\r
512 /* Note the time before the delay so the length of the delay is known. */
\r
513 xTimeAtStart = xTaskGetTickCount();
\r
515 /* This first delay should just time out. */
\r
516 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
517 if( xReturn != pdFALSE )
\r
519 xErrorOccurred = pdTRUE;
\r
521 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
523 /* Note the time before the delay so the length of the delay is known. */
\r
524 xTimeAtStart = xTaskGetTickCount();
\r
526 /* This second delay should be aborted by the primary task half way
\r
528 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
529 if( xReturn != pdFALSE )
\r
531 xErrorOccurred = pdTRUE;
\r
533 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
535 /* Note the time before the delay so the length of the delay is known. */
\r
536 xTimeAtStart = xTaskGetTickCount();
\r
538 /* This third delay should just time out again. */
\r
539 xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
\r
540 if( xReturn != pdFALSE )
\r
542 xErrorOccurred = pdTRUE;
\r
544 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
546 /* Not really necessary in this case, but for completeness. */
\r
547 vSemaphoreDelete( xSemaphore );
\r
549 /*-----------------------------------------------------------*/
\r
551 static void prvTestAbortingTaskNotifyWait( void )
\r
553 TickType_t xTimeAtStart;
\r
554 BaseType_t xReturn;
\r
556 /* Note the time before the delay so the length of the delay is known. */
\r
557 xTimeAtStart = xTaskGetTickCount();
\r
559 /* This first delay should just time out. */
\r
560 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
561 if( xReturn != pdFALSE )
\r
563 xErrorOccurred = pdTRUE;
\r
565 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
567 /* Note the time before the delay so the length of the delay is known. */
\r
568 xTimeAtStart = xTaskGetTickCount();
\r
570 /* This second delay should be aborted by the primary task half way
\r
572 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
573 if( xReturn != pdFALSE )
\r
575 xErrorOccurred = pdTRUE;
\r
577 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
\r
579 /* Note the time before the delay so the length of the delay is known. */
\r
580 xTimeAtStart = xTaskGetTickCount();
\r
582 /* This third delay should just time out again. */
\r
583 xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
\r
584 if( xReturn != pdFALSE )
\r
586 xErrorOccurred = pdTRUE;
\r
588 prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
\r
590 /*-----------------------------------------------------------*/
\r
592 static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
\r
594 TickType_t xTimeNow, xActualBlockTime;
\r
596 xTimeNow = xTaskGetTickCount();
\r
597 xActualBlockTime = xTimeNow - xStartTime;
\r
599 /* The actual block time should not be less than the expected block time. */
\r
600 if( xActualBlockTime < xExpectedBlockTime )
\r
602 xErrorOccurred = pdTRUE;
\r
605 /* The actual block time can be greater than the expected block time, as it
\r
606 depends on the priority of the other tasks, but it should be within an
\r
607 acceptable margin. */
\r
608 if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
\r
610 xErrorOccurred = pdTRUE;
\r
613 /*-----------------------------------------------------------*/
\r
615 BaseType_t xAreAbortDelayTestTasksStillRunning( void )
\r
617 static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
\r
618 BaseType_t xReturn = pdPASS;
\r
620 /* Have both tasks performed at least one cycle since this function was
\r
622 if( xControllingCycles == xLastControllingCycleCount )
\r
627 if( xBlockingCycles == xLastBlockingCycleCount )
\r
632 if( xErrorOccurred == pdTRUE )
\r
637 xLastBlockingCycleCount = xBlockingCycles;
\r
638 xLastControllingCycleCount = xControllingCycles;
\r
643 #endif /* INCLUDE_xTaskAbortDelay == 1 */
\r