INtime SDK Help
Mailboxes
INtime SDK v7.1 > About INtime > INtime Kernel > Mailboxes

Overview

Threads exchange information by sending messages to and receiving messages from mailboxes. A message can contain either an object handle or a data stream.

You can create two kinds of mailboxes:

Sending and receiving data uses different system calls than sending and receiving object handles.

When you create a low-level mailbox, you can reserve one slot in the mailbox message queue for a high priority message. This enables the mailbox to accommodate at least one high priority message even if the queue is full.

Object mailboxes (for object handles)

You use an object mailbox to pass an object handle to another thread. The most common objects to pass are RT handles for other exchanges (mailboxes or semaphores) or RT handles for shared memory sections. (See Memory management) An object mailbox can only pass valid objects.

Data mailboxes

Use data mailboxes to pass small (up to 128 bytes) amounts of information. Data mailboxes are simple to use and consume less resource (memory, GDT entries, and so on).

Creating a mailbox

When you create a mailbox using CreateRtMailbox, the INtime kernel takes resources that it needs from the thread's process. You must specify these parameters when creating a mailbox:

Low-level mailboxes

Create mailboxes with knCreateRtMailbox. To create a mailbox specify:

Mailbox queues

Each mailbox has two queues: a thread queue and a message queue. At any given time, at least one queue is empty because the INtime kernel ensures that waiting threads receive messages as soon as they are available.

Queues for object mailboxes

By specifying a high-performance queue large enough to contain all objects queued during normal operations, you improve the performance of SendRtHandle and ReceiveRtHandle calls when these calls get or place objects in the queue. The INtime kernel permanently allocates memory for a high-performance queue even if no objects are stored in it, so memory does not have to be allocated dynamically.

The INtime kernel automatically handles overflow. When more objects arrive than the high-performance queue can hold, the INtime kernel creates a temporary overflow queue that holds up to 100 messages. The overflow queue is not deleted until it empties. Because the overflow queue is created once for every additional 100 messages, performance is only affected when a SendRtHandle system call causes the allocation of an overflow queue. The allocation then requires extra time.

Queues for data mailboxes

Data mailboxes have a default queue size of three messages, 128 bytes each. When more messages arrive than the queue can hold, the INtime kernel creates a temporary overflow queue that holds up to 400 bytes. The overflow queue is deleted when the queue empties.

Queues for low-level data mailboxes

When you create a low-level Data Mailbox using knCreateRtMailbox, you may reserve one of the slots in the mailbox message queue for a high priority message. This enables the mailbox to accommodate at least one high priority message even if the queue is full.

Handling low-level mailbox overflow

If a mailbox contains its maximum number of messages when a message is sent, the Kernel returns an exception stating that the mailbox limit was exceeded. The mailbox enforces flow control by rejecting messages when the queue is full. Depending on your application, there are several ways to handle mailbox overflow:

If you reserved a slot for a high priority message, mailbox overflow may be indicated when sending an ordinary message, even though the mailbox can still accept a high priority message.

Deleting a mailbox

When you delete a mailbox using DeleteRtMailbox or knDeleteRtMailbox, the INtime kernel:

Exchanging data between threads in different processes

The next figure shows a server thread that does similar services for several client threads in different processes. The server and clients have their own mailboxes. The server should catalog its mailbox in the root process's object directory. Each client sends the handle for its mailbox to the server in the data message so the server knows where to reply.

  1. The server thread S creates a data mailbox using CreateRtMailbox and catalogs it in the root process's object directory using CatalogRtHandle. The server thread waits for requests from clients using ReceiveRtData with a WAIT_FOREVER time limit parameter.
  2. Each client thread creates its own mailbox. Each client thread looks up the handle for the server thread's mailbox using LookupRtHandle.
  3. When either client (thread B in this example) sends data using SendRtData, the client includes the handle for its mailbox in the call.
  4. When a message from either client arrives, the server thread wakes up and processes the data. It sends a reply to the appropriate client thread's mailbox (thread B in this example) using the mailbox handle included in SendRtData.

Sending and receiving mailbox messages with low-level calls

Send ordinary messages to a mailbox with knSendRtData. If a thread is waiting at the mailbox, it receives the message. Otherwise, the message is queued. If the mailbox is full, an exception returns.

Send high priority messages with knSendRtPriorityData. If a thread is waiting at the mailbox, it receives the message. Otherwise, the message is placed at the head of the queue. If the mailbox is full, an exception returns.

Specify the actual message size, which must be less than or equal to the maximum message size for the mailbox. The maximum message size is the size you specified when creating the mailbox. The knSendRtData and knSendRtPriorityData system calls return a status value indicating either that the message was accepted or the mailbox was full.

Receive data from a mailbox with knWaitForRtData. If the mailbox contains at least one message, the message at the head of the queue is returned to the caller. This is either the oldest message or the latest high-priority message. You must provide a message area equal to the maximum message size of the mailbox for the thread.

The call returns the actual size of the received message and a status value indicating:

If no messages are available and the thread is willing to wait, the thread is put to sleep in the thread queue.

System calls

This lists common operations on mailboxes and the mailbox system calls that do the operations:

To . . . Use this system call . . .
Create a mailbox ntxCreateRtMailbox
CreateRtMailbox
knCreateRtMailbox
Delete a mailbox ntxDeleteRtMailbox
DeleteRtMailbox
knDeleteRtMailbox
Send data

ntxSendRtData
SendRtData
knSendRtData

Send priority data knSendRtPriorityData
Receive data ntxReceiveRtData
ReceiveRtData
knWaitForRtData
Send a handle ntxSendRtHandle
SendRtHandle
Receive a handle ntxReceiveRtHandle
ReceiveRtHandle

This shows the order to make queue system calls and lists calls that queues frequently use:

  1. Make these calls from a thread in the process that needs to receive messages from the new queue.
  2. Make this call from the thread that needs to send information to the queue.
  3. Typically, make the ReceiveRtData and ReceiveRtHandle calls from a thread in the process that created the queue. Make the SendRtData and SendRtHandle calls from any thread that has the queue handle.
  4. Make these calls from the thread that created the queue.

These are the rules for queues:

Note:   If you try to pass information with the wrong system call, for example sending an object with SendRtData, the INtime kernel issues an E_TYPE status code. Use the SendRtData and ReceiveRtData system calls with data mailboxes. Use the SendRtHandle and ReceiveRtHandle with object mailboxes.
See Also