Several embedded processor vendors provide support for sRIO in the kernel level software layer. In TI DSPs, sRIO is supported by the Message Queue (MSGQ) module of the DSP/BIOS software kernel foundation.
The MSGQ module has the ability to change which processors read and write messages without having to modify source code. This means that the processor writing a message does not need to know who is reading the message. This allows the programmer to develop an application on a single processor and easily scale to multiple processors. This makes it easy to develop applications such as client/server applications.
The MSGQ module also enables zero-copy transfers of messages. (Zero-copy is basically pointer passing instead of copying the contents of a message.) This can be done on single-processor systems and with processors that share memory. The zero-copy feature makes it easy to provide Quality of Service (QoS) features, such as offering faster performance for critical resources.
The MSGQ module is comprised of the allocators, transports, and the API interface (Figure 2). Allocators provide the interface for allocating messages, transports provide the interface for transporting messages between processors, and the API provides the application interface to the allocators and transporters.
Figure 2. MSGQ Module.
To send a message using the MSGQ module, it must first be allocated. An example of a simple allocator is the static allocation called STATICPOOL. STATICPOOL manages a static buffer supplied by the application. At initialization, STATICPOOL manages the memory address, the buffer length, and the requested message size. The buffer is then divided up into sections the size of the messages, and placed in a link list. This makes it easier to locate messages.
For some applications it may be desirable to separate critical from non-critical messages. This can be done by using multiple allocators to allocate critical messages from one pool and non-critical messages from another pool.
Once a message has been allocated it, the transport sends the message across the physical link to the destination message queue on another processor (Figure 3). The advantage of the transport mechanism is that is allows the underlying communication mechanism to be changed without changing the application. Only the transport, not the application, needs to be reconfigured. This approach hides the technical nuances of the physical link and improves application portability.
(Click to enlarge)
Figure 3: Transport Function.
Message queues have unique system-wide names that allow senders to locate the message queue. All messages that are sent via the MSGQ module must include an MSGQ _MsgHeader. This header specifies which message queue the message is being sent to, as well as any word size or endianness differences between processors. Any required conversion is handled by the transport.
Since different processors may have different scheduling modules, the MSGQ module allows the application writer to specify the type of notification mechanism. This is particularly helpful because the user can specify the notification mechanism and adapt MSGQ accordingly. However, once a message is sent to a reader, the writer loses ownership of the message and cannot modify or free the message. Therefore, it is incredibly important that the message is correct prior to being sent. When the reader receives the message, it must either free or re-use the message.
Locating a Message Queue
In an application, messages are retrieved from the message queue repository. MSGQ maintains one message repository for each opened message queue. If a reader or writer thread needs to be moved to another processor, there are no changes needed to the reader or writer code.
There are two ways to locate a message queue: synchronous or asynchronous. In a synchronous (i.e. potentially blocking) function, a message queries each transport to find the desired message queue location. With an asynchronous function, once the message queue is located, an asynchronous locate message is sent to the specified message queue.
Synchronous operation is easier to implement, but requires that several parameters of the queue be blocked, such as the locating thread. While asynchronous operation does not require blocking, actual implementation is more difficult and harder to use.
Synchronous or asynchronous operations are supported via application specified notification mechanisms. The user can specify the notification mechanism, such as semaphore or posting of an interrupt, thereby avoiding the need to follow a particular scheduling model. The sender of a message can embed a message queue and the reader of the message can extract the message queue and reply back.