msg.h File Reference

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

#include <mware/event.h>
#include <struct/list.h>
#include <kern/proc.h>

Go to the source code of this file.


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

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

Version:
Id
msg.h 2949 2009-09-16 08:04:45Z lottaviano

Author:
Bernie Innocenti <bernie@codewiz.org>
Simple inter-process messaging system Handle queues of messages associated an action.

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.

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);
                }
            }
        }
    }

Definition in file msg.h.


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 258 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 220 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 270 of file msg.h.

void msg_reply ( Msg *  msg  )  [inline]

Send back (reply) msg to its sender.

Definition at line 284 of file msg.h.

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

Unlock a message port.

See also:
msg_lockPort()

Definition at line 230 of file msg.h.