Update the queue peek behaviour and add QPeek test files.

pull/1/head
Richard Barry 18 years ago
parent 5f16b0abca
commit c77358491a

@ -0,0 +1,420 @@
/*
FreeRTOS.org V4.4.0 - Copyright (C) 2003-2007 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
with commercial development and support options.
***************************************************************************
*/
/*
* Tests the behaviour when data is peeked from a queue when there are
* multiple tasks blocked on the queue.
*/
#include <stdlib.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Demo program include files. */
#include "QPeek.h"
#define qpeekQUEUE_LENGTH ( 5 )
#define qpeekNO_BLOCK ( 0 )
#define qpeekSHORT_DELAY ( 10 )
#define qpeekLOW_PRIORITY ( tskIDLE_PRIORITY + 0 )
#define qpeekMEDIUM_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define qpeekHIGH_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define qpeekHIGHEST_PRIORITY ( tskIDLE_PRIORITY + 3 )
/*-----------------------------------------------------------*/
/*
* The following three tasks are used to demonstrate the peeking behaviour.
* Each task is given a different priority to demonstrate the order in which
* tasks are woken as data is peeked from a queue.
*/
static void prvLowPriorityPeekTask( void *pvParameters );
static void prvMediumPriorityPeekTask( void *pvParameters );
static void prvHighPriorityPeekTask( void *pvParameters );
static void prvHighestPriorityPeekTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
detected in any of the tasks. */
static portBASE_TYPE xErrorDetected = pdFALSE;
/* Counter that is incremented on each cycle of a test. This is used to
detect a stalled task - a test that is no longer running. */
static volatile unsigned portLONG ulLoopCounter = 0;
/* Handles to the test tasks. */
xTaskHandle xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;
/*-----------------------------------------------------------*/
void vStartQueuePeekTasks( void )
{
xQueueHandle xQueue;
/* Create the queue that we are going to use for the test/demo. */
xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( unsigned portLONG ) );
/* Create the demo tasks and pass it the queue just created. We are
passing the queue handle by value so it does not matter that it is declared
on the stack here. */
xTaskCreate( prvLowPriorityPeekTask, "PeekLow", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
xTaskCreate( prvMediumPriorityPeekTask, "PeekMed", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
xTaskCreate( prvHighPriorityPeekTask, "PeekHigh", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
xTaskCreate( prvHighestPriorityPeekTask, "PeekHighest", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask );
}
/*-----------------------------------------------------------*/
static void prvHighestPriorityPeekTask( void *pvParameters )
{
xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
unsigned portLONG ulValue;
#ifdef USE_STDIO
{
void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
const portCHAR * const pcTaskStartMsg = "Queue peek test started.\r\n";
/* Queue a message for printing to say the task has started. */
vPrintDisplayMessage( &pcTaskStartMsg );
}
#endif
for( ;; )
{
/* Try peeking from the queue. The queue should be empty so we will
block, allowing the high priority task to execute. */
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
{
/* We expected to have received something by the time we unblock. */
xErrorDetected = pdTRUE;
}
/* When we reach here the high and medium priority tasks should still
be blocked on the queue. We unblocked because the low priority task
wrote a value to the queue, which we should have peeked. Peeking the
data (rather than receiving it) will leave the data on the queue, so
the high priority task should then have also been unblocked, but not
yet executed. */
if( ulValue != 0x11223344 )
{
/* We did not receive the expected value. */
xErrorDetected = pdTRUE;
}
if( uxQueueMessagesWaiting( xQueue ) != 1 )
{
/* The message should have been left on the queue. */
xErrorDetected = pdTRUE;
}
/* Now we are going to actually receive the data, so when the high
priority task runs it will find the queue empty and return to the
blocked state. */
ulValue = 0;
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
{
/* We expected to receive the value. */
xErrorDetected = pdTRUE;
}
if( ulValue != 0x11223344 )
{
/* We did not receive the expected value - which should have been
the same value as was peeked. */
xErrorDetected = pdTRUE;
}
/* Now we will block again as the queue is once more empty. The low
priority task can then execute again. */
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
{
/* We expected to have received something by the time we unblock. */
xErrorDetected = pdTRUE;
}
/* When we get here the low priority task should have again written to the
queue. */
if( ulValue != 0x01234567 )
{
/* We did not receive the expected value. */
xErrorDetected = pdTRUE;
}
if( uxQueueMessagesWaiting( xQueue ) != 1 )
{
/* The message should have been left on the queue. */
xErrorDetected = pdTRUE;
}
/* We only peeked the data, so suspending ourselves now should enable
the high priority task to also peek the data. The high priority task
will have been unblocked when we peeked the data as we left the data
in the queue. */
vTaskSuspend( NULL );
/* This time we are going to do the same as the above test, but the
high priority task is going to receive the data, rather than peek it.
This means that the medium priority task should never peek the value. */
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
if( ulValue != 0xaabbaabb )
{
xErrorDetected = pdTRUE;
}
vTaskSuspend( NULL );
}
}
/*-----------------------------------------------------------*/
static void prvHighPriorityPeekTask( void *pvParameters )
{
xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
unsigned portLONG ulValue;
for( ;; )
{
/* Try peeking from the queue. The queue should be empty so we will
block, allowing the medium priority task to execute. Both the high
and highest priority tasks will then be blocked on the queue. */
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
{
/* We expected to have received something by the time we unblock. */
xErrorDetected = pdTRUE;
}
/* When we get here the highest priority task should have peeked the data
(unblocking this task) then suspended (allowing this task to also peek
the data). */
if( ulValue != 0x01234567 )
{
/* We did not receive the expected value. */
xErrorDetected = pdTRUE;
}
if( uxQueueMessagesWaiting( xQueue ) != 1 )
{
/* The message should have been left on the queue. */
xErrorDetected = pdTRUE;
}
/* We only peeked the data, so suspending ourselves now should enable
the medium priority task to also peek the data. The medium priority task
will have been unblocked when we peeked the data as we left the data
in the queue. */
vTaskSuspend( NULL );
/* This time we are going actually receive the value, so the medium
priority task will never peek the data - we removed it from the queue. */
if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
if( ulValue != 0xaabbaabb )
{
xErrorDetected = pdTRUE;
}
vTaskSuspend( NULL );
}
}
/*-----------------------------------------------------------*/
static void prvMediumPriorityPeekTask( void *pvParameters )
{
xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
unsigned portLONG ulValue;
for( ;; )
{
/* Try peeking from the queue. The queue should be empty so we will
block, allowing the low priority task to execute. The highest, high
and medium priority tasks will then all be blocked on the queue. */
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
{
/* We expected to have received something by the time we unblock. */
xErrorDetected = pdTRUE;
}
/* When we get here the high priority task should have peeked the data
(unblocking this task) then suspended (allowing this task to also peek
the data). */
if( ulValue != 0x01234567 )
{
/* We did not receive the expected value. */
xErrorDetected = pdTRUE;
}
if( uxQueueMessagesWaiting( xQueue ) != 1 )
{
/* The message should have been left on the queue. */
xErrorDetected = pdTRUE;
}
/* Just so we know the test is still running. */
ulLoopCounter++;
/* Now we can suspend ourselves so the low priority task can execute
again. */
vTaskSuspend( NULL );
}
}
/*-----------------------------------------------------------*/
static void prvLowPriorityPeekTask( void *pvParameters )
{
xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
unsigned portLONG ulValue;
for( ;; )
{
/* Write some data to the queue. This should unblock the highest
priority task that is waiting to peek data from the queue. */
ulValue = 0x11223344;
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
{
/* We were expecting the queue to be empty so we should not of
had a problem writing to the queue. */
xErrorDetected = pdTRUE;
}
/* By the time we get here the data should have been removed from
the queue. */
if( uxQueueMessagesWaiting( xQueue ) != 0 )
{
xErrorDetected = pdTRUE;
}
/* Write another value to the queue, again waking the highest priority
task that is blocked on the queue. */
ulValue = 0x01234567;
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
{
/* We were expecting the queue to be empty so we should not of
had a problem writing to the queue. */
xErrorDetected = pdTRUE;
}
/* All the other tasks should now have successfully peeked the data.
The data is still in the queue so we should be able to receive it. */
ulValue = 0;
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
{
/* We expected to receive the data. */
xErrorDetected = pdTRUE;
}
if( ulValue != 0x01234567 )
{
/* We did not receive the expected value. */
}
/* Lets just delay a while as this is an intensive test as we don't
want to starve other tests of processing time. */
vTaskDelay( qpeekSHORT_DELAY );
/* Unsuspend the other tasks so we can repeat the test - this time
however not all the other tasks will peek the data as the high
priority task is actually going to remove it from the queue. Send
to front is used just to be different. As the queue is empty it
makes no difference to the result. */
vTaskResume( xMediumPriorityTask );
vTaskResume( xHighPriorityTask );
vTaskResume( xHighestPriorityTask );
ulValue = 0xaabbaabb;
if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
{
/* We were expecting the queue to be empty so we should not of
had a problem writing to the queue. */
xErrorDetected = pdTRUE;
}
/* This time we should find that the queue is empty. The high priority
task actually removed the data rather than just peeking it. */
if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
{
/* We expected to receive the data. */
xErrorDetected = pdTRUE;
}
/* Unsuspend the highest and high priority tasks so we can go back
and repeat the whole thing. The medium priority task should not be
suspended as it was not able to peek the data in this last case. */
vTaskResume( xHighPriorityTask );
vTaskResume( xHighestPriorityTask );
/* Lets just delay a while as this is an intensive test as we don't
want to starve other tests of processing time. */
vTaskDelay( qpeekSHORT_DELAY );
}
}
/*-----------------------------------------------------------*/
/* This is called to check that all the created tasks are still running. */
portBASE_TYPE xAreQueuePeekTasksStillRunning( void )
{
static unsigned portLONG ulLastLoopCounter = 0;
/* If the demo task is still running then we expect the loopcounter to
have incremented since this function was last called. */
if( ulLastLoopCounter == ulLoopCounter )
{
xErrorDetected = pdTRUE;
}
ulLastLoopCounter = ulLoopCounter;
/* Errors detected in the task itself will have latched xErrorDetected
to true. */
return !xErrorDetected;
}

@ -0,0 +1,45 @@
/*
FreeRTOS.org V4.4.0 - Copyright (C) 2003-2007 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
with commercial development and support options.
***************************************************************************
*/
#ifndef Q_PEEK_TEST_H
#define Q_PEEK_TEST_H
void vStartQueuePeekTasks( void );
portBASE_TYPE xAreQueuePeekTasksStillRunning( void );
#endif /* Q_PEEK_TEST_H */

@ -120,6 +120,7 @@ Changes from V3.2.4
#include "crhook.h"
#include "blocktim.h"
#include "GenQTest.h"
#include "QPeek.h"
/* Priority definitions for the tasks in the demo application. */
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
@ -182,6 +183,7 @@ portSHORT main( void )
vStartSemaphoreTasks( mainSEMAPHORE_TASK_PRIORITY );
vStartDynamicPriorityTasks();
vStartMultiEventTasks();
vStartQueuePeekTasks();
/* Create the "Print" task as described at the top of the file. */
xTaskCreate( vErrorChecks, "Print", mainPRINT_STACK_SIZE, NULL, mainPRINT_TASK_PRIORITY, NULL );
@ -399,6 +401,12 @@ static portSHORT sErrorHasOccurred = pdFALSE;
sErrorHasOccurred = pdTRUE;
}
if( xAreQueuePeekTasksStillRunning() != pdTRUE )
{
vDisplayMessage( "Error in queue peek test task!\r\n" );
sErrorHasOccurred = pdTRUE;
}
if( sErrorHasOccurred == pdFALSE )
{
vDisplayMessage( "OK " );

@ -75,7 +75,7 @@ WVList
0
19
WPickList
52
53
20
MItem
3
@ -778,8 +778,8 @@ WVList
0
184
MItem
15
fileio\fileio.c
25
..\COMMON\MINIMAL\QPeek.c
185
WString
4
@ -796,8 +796,8 @@ WVList
0
188
MItem
6
main.c
15
fileio\fileio.c
189
WString
4
@ -814,8 +814,8 @@ WVList
0
192
MItem
17
partest\partest.c
6
main.c
193
WString
4
@ -832,8 +832,8 @@ WVList
0
196
MItem
15
serial\serial.c
17
partest\partest.c
197
WString
4
@ -850,26 +850,26 @@ WVList
0
200
MItem
3
*.h
15
serial\serial.c
201
WString
3
NIL
4
COBJ
202
WVList
0
203
WVList
0
-1
20
1
1
0
0
204
MItem
31
..\..\SOURCE\INCLUDE\croutine.h
3
*.h
205
WString
3
@ -880,14 +880,14 @@ WVList
207
WVList
0
200
1
-1
1
0
0
208
MItem
27
..\..\source\include\list.h
31
..\..\SOURCE\INCLUDE\croutine.h
209
WString
3
@ -898,14 +898,14 @@ WVList
211
WVList
0
200
204
1
1
0
212
MItem
31
..\..\source\include\portable.h
27
..\..\source\include\list.h
213
WString
3
@ -916,14 +916,14 @@ WVList
215
WVList
0
200
204
1
1
0
216
MItem
31
..\..\source\include\projdefs.h
..\..\source\include\portable.h
217
WString
3
@ -934,14 +934,14 @@ WVList
219
WVList
0
200
204
1
1
0
220
MItem
28
..\..\source\include\queue.h
31
..\..\source\include\projdefs.h
221
WString
3
@ -952,14 +952,14 @@ WVList
223
WVList
0
200
204
1
1
0
224
MItem
29
..\..\source\include\semphr.h
28
..\..\source\include\queue.h
225
WString
3
@ -970,14 +970,14 @@ WVList
227
WVList
0
200
204
1
1
0
228
MItem
27
..\..\source\include\task.h
29
..\..\source\include\semphr.h
229
WString
3
@ -988,14 +988,14 @@ WVList
231
WVList
0
200
204
1
1
0
232
MItem
55
..\..\source\portable\owatcom\16bitdos\common\portasm.h
27
..\..\source\include\task.h
233
WString
3
@ -1006,14 +1006,14 @@ WVList
235
WVList
0
200
204
1
1
0
236
MItem
53
..\..\source\portable\owatcom\16bitdos\pc\portmacro.h
55
..\..\source\portable\owatcom\16bitdos\common\portasm.h
237
WString
3
@ -1024,14 +1024,14 @@ WVList
239
WVList
0
200
204
1
1
0
240
MItem
26
..\common\include\blockq.h
53
..\..\source\portable\owatcom\16bitdos\pc\portmacro.h
241
WString
3
@ -1042,14 +1042,14 @@ WVList
243
WVList
0
200
204
1
1
0
244
MItem
28
..\COMMON\INCLUDE\blocktim.h
26
..\common\include\blockq.h
245
WString
3
@ -1060,14 +1060,14 @@ WVList
247
WVList
0
200
204
1
1
0
248
MItem
27
..\common\include\comtest.h
28
..\COMMON\INCLUDE\blocktim.h
249
WString
3
@ -1078,14 +1078,14 @@ WVList
251
WVList
0
200
204
1
1
0
252
MItem
26
..\COMMON\INCLUDE\crhook.h
27
..\common\include\comtest.h
253
WString
3
@ -1096,14 +1096,14 @@ WVList
255
WVList
0
200
204
1
1
0
256
MItem
25
..\common\include\death.h
26
..\COMMON\INCLUDE\crhook.h
257
WString
3
@ -1114,14 +1114,14 @@ WVList
259
WVList
0
200
204
1
1
0
260
MItem
27
..\COMMON\INCLUDE\dynamic.h
25
..\common\include\death.h
261
WString
3
@ -1132,14 +1132,14 @@ WVList
263
WVList
0
200
204
1
1
0
264
MItem
26
..\common\include\fileio.h
27
..\COMMON\INCLUDE\dynamic.h
265
WString
3
@ -1150,14 +1150,14 @@ WVList
267
WVList
0
200
204
1
1
0
268
MItem
25
..\common\include\flash.h
26
..\common\include\fileio.h
269
WString
3
@ -1168,14 +1168,14 @@ WVList
271
WVList
0
200
204
1
1
0
272
MItem
24
..\common\include\flop.h
25
..\common\include\flash.h
273
WString
3
@ -1186,14 +1186,14 @@ WVList
275
WVList
0
200
204
1
1
0
276
MItem
28
..\COMMON\INCLUDE\GenQTest.h
24
..\common\include\flop.h
277
WString
3
@ -1204,14 +1204,14 @@ WVList
279
WVList
0
200
204
1
1
0
280
MItem
27
..\common\include\partest.h
28
..\COMMON\INCLUDE\GenQTest.h
281
WString
3
@ -1222,14 +1222,14 @@ WVList
283
WVList
0
200
204
1
1
0
284
MItem
25
..\common\include\pollq.h
27
..\common\include\partest.h
285
WString
3
@ -1240,14 +1240,14 @@ WVList
287
WVList
0
200
204
1
1
0
288
MItem
25
..\common\include\print.h
..\common\include\pollq.h
289
WString
3
@ -1258,14 +1258,14 @@ WVList
291
WVList
0
200
204
1
1
0
292
MItem
27
..\common\include\semtest.h
25
..\common\include\print.h
293
WString
3
@ -1276,14 +1276,14 @@ WVList
295
WVList
0
200
204
1
1
0
296
MItem
26
..\common\include\serial.h
27
..\common\include\semtest.h
297
WString
3
@ -1294,14 +1294,14 @@ WVList
299
WVList
0
200
204
1
1
0
300
MItem
16
FreeRTOSConfig.h
26
..\common\include\serial.h
301
WString
3
@ -1312,7 +1312,25 @@ WVList
303
WVList
0
200
204
1
1
0
304
MItem
16
FreeRTOSConfig.h
305
WString
3
NIL
306
WVList
0
307
WVList
0
204
1
1
0

@ -31,7 +31,7 @@ WRect
0
0
7168
8523
8474
0
0
9
@ -39,5 +39,5 @@ WFileName
12
rtosdemo.tgt
0
26
24
7

@ -610,7 +610,12 @@ signed portCHAR *pcOriginalReadPosition;
{
/* We are not removing the data, so reset our read
pointer. */
pxQueue->pcReadFrom = pcOriginalReadPosition;
pxQueue->pcReadFrom = pcOriginalReadPosition;
/* The data is being left in the queue, so increment the
lock count so prvUnlockQueue knows to check for other
tasks waiting for the data to be available. */
++( pxQueue->xTxLock );
}
xReturn = pdPASS;

Loading…
Cancel
Save