Professional Documents
Culture Documents
2010
1
dce
2010
Chapter 4
Message Queue Management
4.1 Defining Message Queue
4.2 Message Queue States
BK
TP.HCM 4.3 Message Queue Operations
4.4 Message Queue Usages
4.5 Example: T-Kernel and FreeRTOS
2
dce
2010
Defining a Message Queue
Message Queue
Inter-task data communication mechanism. A message queue is a buffer-like
object through which tasks and ISRs send and receive messages to
communicate and synchronize with data. It temporarily holds messages from
a sender until the intended receiver is ready to read them.
When a message queue is first created, it is assigned an associated queue
control block (QCB), a message queue name, a unique ID, memory buffers, a
queue length, a maximum message length, and one or more task-waiting lists.
A message queue has two associated task-waiting lists. The receiving task-
waiting list consists of tasks that wait on the queue when it is empty. The
sending list consists of tasks that wait on the queue when it is full.
3
dce
2010
Message Queue States
When a message queue is first created, the FSM is in the empty state.
If a task attempts to receive messages from this message queue while the
queue is empty, the task blocks and is held on the message queue's task-
waiting list.
If another task sends a message to the message queue, the message is
delivered directly to the blocked task. The blocked task is then removed from
the task-waiting list and moved to either the ready or the running state.
If another message is sent to the same message queue and no tasks are
waiting in the message queue's task-waiting list, the message queue's state
becomes not empty.
As additional messages arrive at the queue, the queue eventually fills up until
it has exhausted its free space and the message queue's state becomes full.
While a message queue is in this state, any task sending messages to it will
not be successful unless some other task first requests a message from that
queue, thus freeing a queue element.
In some kernel implementations when a task attempts to send a message to a
full message queue, the sending function returns an error code to that task.
Other kernel implementations allow such a task to block, moving the blocked
task into the sending task-waiting list, which is separate from the receiving
task-waiting list
4
dce
2010
Message Queue Operations
• Creating
– Length, maximum message size, waiting order
• Deleting
– Automatically unblock waiting tasks
5
dce
2010
Sending Messages
Sending Messages
When sending messages, a kernel typically fills a message queue from head to tail in FIFO order
6
dce
2010
Sending Messages
7
dce
2010
Sending Messages
• Sending Type
– Not block (ISRs and tasks),
– Block with a timeout (tasks only), and
– Block forever (tasks only).
8
dce
2010
9
dce
2010
10
dce
2010
Receiving Messages
• Receiving Type
– Not blocking
– Blocking with a timeout
– Blocking forever
• Reading Type
– Destructive read
– Non-destructive read
Receiving Messages
The blocking occurs due to the message queue being empty, and wait in
either a FIFO or priority-based order.
Destructive read
When a task successfully receives a message from a queue, the task
permanently removes the message from the message queue’s storage buffer.
Non-destructive read
Receiving task peeks at the message at the head of the queue without
removing it.
11
dce
2010
Message Queue Operations
• Get information
– Get queue information
– Get a list of tasks in queue waiting list
12
dce
2010
Message Queue Usages
• Non-Interlocked, One-Way Data
Communication
13
dce
2010
Interlock One-Way Data Communication
14
dce
2010
15
dce
2010
T-Kernel Message Queue
• Characteristic
– Variable message size
– FIFO buffer
• Functions
– Creating, Deleting, Sending, Receiving messages,
and referencing message buffer status.
16
dce
2010
T-Kernel Message Queue
• Creating
– Message queue size
– Maximum message size
– FIFO or priority-based task-waiting list
• Sending and Receiving
– Non-block
– Block with a timeout
– Block forever
17
dce
2010
FreeRTOS Message Queue
• Characteristic
– Fixed message size
– FIFO buffer
• Reading and Writing
– Non-blocking, block for a timeout, block forever
– Priority-based task-waiting list
– Send to back or head
18
dce
2010
Example 7
• Using message queue
• Two task does not blocks on sending
• A task blocks for a timeout on receiving
19
dce
2010
Example 7
static void vSenderTask( void *pvParameters ) {
long lValueToSend;
portBASE_TYPE xStatus;
for( ;; ) {
xStatus = xQueueSendToBack( xQueue,
&lValueToSend, 0 );
20
dce
2010
Example 7
static void vReceiverTask( void *pvParameters ) {
const portTickType xTicksToWait = 100 / portTICK_RATE_MS;
for( ;; ) {
if( uxQueueMessagesWaiting( xQueue ) != 0 ) {
vPrintString("Queue should be empty!\r\n" );
}
xStatus = xQueueReceive(xQueue,
&lReceivedValue, xTicksToWait);
if( xStatus == pdPASS ) {
vPrintStringAndNumber( "Received=",
lReceivedValue );
} else {
vPrintString( "Could not receive.\r\n" );
}
}
}
21
dce
2010
Example 7
int main( void ) {
xQueue = xQueueCreate( 5, sizeof( long ) );
if( xQueue != NULL ) {
xTaskCreate( vSenderTask, "Sender1", 1000, (
void * ) 100, 1, NULL );
xTaskCreate( vSenderTask, "Sender2", 1000, (
void * ) 200, 1, NULL );
vTaskStartScheduler();
}
for( ;; );
}
22
dce
2010
Example 7
23
dce
2010
24
dce
2010
Example 8
• Using 2 queue
• Interrupt generator task
– Run each 200ms
– Send 5 integer number to queue
– Generate interrupt
• Interrupt handler
– Receives number from queue
– Sends string to another queue
• Print task
– Receive string and print
25
dce
2010
Example 8
static void __interrupt __far vExampleInterruptHandler( void ) {
static const char *pcStrings[] = {
"String 0\n", "String 1\n", "String 2\n", "String 3\n"
};
xHigherPriorityTaskWoken = pdFALSE;
while( xQueueReceiveFromISR( xIntegerQueue,
&ulReceivedNumber,
&xHigherPriorityTaskWoken ) != errQUEUE_EMPTY ) {
ulReceivedNumber &= 0x03;
xQueueSendToBackFromISR( xStringQueue,
&pcStrings[ ulReceivedNumber ],
&xHigherPriorityTaskWoken );
}
if( xHigherPriorityTaskWoken == pdTRUE ) {
portSWITCH_CONTEXT();
}
}
26
dce
2010
Example 8
static void vStringPrinter( void *pvParameters ) {
char *pcString;
for( ;; ) {
xQueueReceive( xStringQueue, &pcString, portMAX_DELAY
);
vPrintString( pcString );
}
}
27
dce
2010
Example 8
static void vIntegerGenerator( void *pvParameters ) {
xLastExecutionTime = xTaskGetTickCount();
for( ;; ) {
vTaskDelayUntil( &xLastExecutionTime, 200 /
portTICK_RATE_MS );
for( i = 0; i < 5; i++ ) {
xQueueSendToBack( xIntegerQueue,
&ulValueToSend, 0 );
ulValueToSend++;
}
vPrintString( "Generator task - About to
generate an interrupt.\r\n" );
__asm{ int 0x82 }
vPrintString( "Generator task - Interrupt
generated.\r\n\r\n\r\n" );
}
}
28
dce
2010
Example 8
int main( void ) {
xIntegerQueue = xQueueCreate(10, sizeof(unsigned long));
xStringQueue = xQueueCreate(10, sizeof( char * ) );
_dos_setvect(0x82, vExampleInterruptHandler );
xTaskCreate(vIntegerGenerator,"IntGen",1000,NULL, 1, NULL );
xTaskCreate(vStringPrinter, "String", 1000, NULL, 2, NULL );
vTaskStartScheduler();
for( ;; );
}
29
dce
2010
Example 8
30
dce
2010
31