BeRTOS
Functions
Message box IPC
Kernel facilities

Simple inter-process messaging system. More...

Functions

void msg_lockPort (UNUSED_ARG(MsgPort *, port))
 Lock a message port.
void msg_unlockPort (UNUSED_ARG(MsgPort *, port))
 Unlock a message port.
void msg_initPort (MsgPort *port, Event event)
 Initialize a message port.
void msg_put (MsgPort *port, Msg *msg)
 Queue msg into port, triggering the associated event.
Msg * msg_get (MsgPort *port)
 Get the first message from the queue of port.
Msg * msg_peek (MsgPort *port)
 Peek the first message in the queue of port, or NULL if the port is empty.
void msg_reply (Msg *msg)
 Send back (reply) msg to its sender.

Detailed Description

Simple inter-process messaging system.

This module implements a common system for executing a user defined action calling a hook function.

A message port is an abstraction used to exchange information asynchronously between processes or other entities such as interrupts and call-back functions.

This form of IPC is higher-level than bare signals and semaphores, because it sets a policy for exchanging structured data with well-defined synchronization and ownership semantics.

Before using it, a message port must be initialized by calling msg_initPort(), which associates the port with an Event object, which can be setup to signal a process or invoke a call-back hook.

A process or interrupt routine can deliver messages to any message port by calling msg_put(). By sending a message, the sender temporarly or permanently transfers ownership of its associated data to the receiver.

Queuing a message to a port automatically triggers the associated Event to notify the receiver. When the receiver wakes up, it usually invokes msg_get() to pick the next message from the port.

Note:
When you put a message into a port, such message becomes unavailable until you retrieve it using msg_get(), eg. you must not delete it or put it into another port.

Message ports can hold any number of pending messages, and receivers usually process them in FIFO order. Other scheduling policies are possible, but not implemented in this API.

After the receiver has done processing a message, it replies it back to the sender with msg_reply(), which transfer ownership back to the original sender. Replies are delivered to a reply port, which is nothing more than another MsgPort structure designated by the sender.

Returning messages to senders is not mandatory, but it provides a convenient way to provide some kind of result and simplify the resource allocation scheme at the same time.

When using signals to receive messages in a process, you call sig_wait() in an event-loop to wake up when messages are delivered to any of your ports. When your process wakes up with the port signal active, multiple messages may already have queued up at the message port, and the process must process them all before returning to sleep. Signals don't keep a nesting count.

A simple message loop works like this:

    // Our message port.
    static MsgPort test_port;

    // A test message with two parameters and a result.
    typedef struct
    {
        Msg msg;

        int x, y;
        int result;
    } TestMsg;


  PROC_DEFINE_STACK(sender_stack, KERN_MINSTACKSIZE);

    // A process that sends two messages and waits for replies.
    static void sender_proc(void)
    {
        MsgPort test_reply_port;
        TestMsg msg1;
        TestMsg msg2;
        Msg *reply;

        msg_initPort(&test_reply_port,
            event_createSignal(proc_current(), SIG_SINGLE);

        // Fill-in first message and send it out.
        msg1.x = 3;
        msg1.y = 2;
        msg1.msg.replyPort = &test_reply_port;
        msg_put(&test_port, &msg1.msg);

        // Fill-in second message and send it out too.
        msg2.x = 5;
        msg2.y = 4;
        msg2.msg.replyPort = &test_reply_port;
        msg_put(&test_port, &msg2.msg);

        // Wait for a reply...
        sig_wait(SIG_SINGLE);

        reply = containerof(msg_get(&test_reply_port), TestMsg, msg);
        ASSERT(reply != NULL);
        ASSERT(reply->result == 5);

        // Get reply to second message.
        while (!(reply = containerof(msg_get(&test_reply_port), TestMsg, msg)))
        {
            // Not yet, be patient and wait some more.
            sig_wait(SIG_SINGLE);
        }

        ASSERT(reply->result == 9);
    }


    // Receive messages and do something boring with them.
    static void receiver_proc(void)
    {
        msg_initPort(&test_port,
            event_createSignal(proc_current(), SIG_EXAMPLE);

        proc_new(sender_proc, NULL,sizeof(sender_stack), sender_stack);

        for (;;)
        {
            sigmask_t sigs = sig_wait(SIG_EXAMPLE | more_signals);

            if (sigs & SIG_EXAMPLE)
            {
                TestMsg *emsg;
                while((emsg = containerof(msg_get(&test_port), TestMsg, msg)))
                {
                    // Do something with the message
                    emsg->result = emsg->x + emsg->y;
                    msg_reply(emsg->msg);
                }
            }
        }
    }
Author:
Bernie Innocenti <bernie@codewiz.org>

Function Documentation

Msg* msg_get ( MsgPort *  port) [inline]

Get the first message from the queue of port.

Returns:
Pointer to the message or NULL if the port was empty.

Definition at line 263 of file msg.h.

void msg_lockPort ( UNUSED_ARG(MsgPort *, port)  ) [inline]

Lock a message port.

This is required before reading or manipulating any field of the MsgPort structure.

Note:
Ports may be locked multiple times and each call to msg_lockPort() must be paired with a corresponding call to msg_unlockPort().
See also:
msg_unlockPort()

Definition at line 225 of file msg.h.

Msg* msg_peek ( MsgPort *  port) [inline]

Peek the first message in the queue of port, or NULL if the port is empty.

Definition at line 275 of file msg.h.

void msg_reply ( Msg *  msg) [inline]

Send back (reply) msg to its sender.

Definition at line 289 of file msg.h.

void msg_unlockPort ( UNUSED_ARG(MsgPort *, port)  ) [inline]

Unlock a message port.

See also:
msg_lockPort()

Definition at line 235 of file msg.h.