doc: Added group definitions for most common modules.
[bertos.git] / bertos / kern / msg.h
index e4ee21f9b1ab5f2ae7a136aa5f7eaba2953aa257..6cbcc444e371a98bb540a46bbca97af60f157fe8 100644 (file)
  * the GNU General Public License.
  *
  * Copyright 2004 Develer S.r.l. (http://www.develer.com/)
- * Copyright 1999,2001 Bernardo Innocenti <bernie@develer.com>
+ * Copyright 1999,2001 Bernie Innocenti <bernie@codewiz.org>
  *
  * -->
  *
  *
- * This module implements a common system for executing
- * a user defined action calling a hook function.
- *
- * \version $Id$
- *
- * \author Bernardo Innocenti <bernie@develer.com>
+ * \defgroup kern_msg Message box IPC
+ * \ingroup kern
+ * \{
  *
  * \brief Simple inter-process messaging system
  *
- * Handle queues of messages associated an action.
+ * 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
  * 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
  *     } TestMsg;
  *
  *
+ *  PROC_DEFINE_STACK(sender_stack, KERN_MINSTACKSIZE);
+ *
  *     // A process that sends two messages and waits for replies.
  *     static void sender_proc(void)
  *     {
  *             TestMsg msg2;
  *             Msg *reply;
  *
- *             msg_initPort(&reply_port,
- *                     event_createSignal(proc_current(), SIGF_SINGLE);
+ *             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_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, &msg1);
+ *             msg_put(&test_port, &msg2.msg);
  *
  *             // Wait for a reply...
  *             sig_wait(SIG_SINGLE);
  *
*             reply = (TestMsg *)msg_get(&test_reply_port);
       reply = containerof(msg_get(&test_reply_port), TestMsg, msg);
  *             ASSERT(reply != NULL);
  *             ASSERT(reply->result == 5);
  *
  *             // Get reply to second message.
- *             while (!(reply = (TestMsg *)msg_get(&test_reply_port))
+ *             while (!(reply = containerof(msg_get(&test_reply_port), TestMsg, msg)))
  *             {
  *                     // Not yet, be patient and wait some more.
  *                     sig_wait(SIG_SINGLE);
  *     static void receiver_proc(void)
  *     {
  *             msg_initPort(&test_port,
- *                     event_createSignal(proc_current(), SIGF_EXAMPLE);
+ *                     event_createSignal(proc_current(), SIG_EXAMPLE);
  *
- *             proc_new(sender_proc, (iptr_t)&test_port,
- *                     sender_stack, sizeof(sender_stack);
+ *             proc_new(sender_proc, NULL,sizeof(sender_stack), sender_stack);
  *
  *             for (;;)
  *             {
- *                     sigmask_t sigs = sig_wait(SIGF_EXAMPLE | more_signals);
+ *                     sigmask_t sigs = sig_wait(SIG_EXAMPLE | more_signals);
  *
- *                     if (sigs & SIGF_EXAMPLE)
+ *                     if (sigs & SIG_EXAMPLE)
  *                     {
  *                             TestMsg *emsg;
- *                             while (emsg = (TestMsg *)msg_get(&test_port)
+ *                             while((emsg = containerof(msg_get(&test_port), TestMsg, msg)))
  *                             {
  *                                     // Do something with the message
  *                                     emsg->result = emsg->x + emsg->y;
- *                                     msg_reply((Msg *)msg);
+ *                                     msg_reply(emsg->msg);
  *                             }
  *                     }
  *             }
  *     }
  * \endcode
+ *
+ * \author Bernie Innocenti <bernie@codewiz.org>
+ *
+ * $WIZ$ module_name = "msg"
+ * $WIZ$ module_depends = "event", "signal", "kernel"
  */
 
- */
 
 #ifndef KERN_MSG_H
 #define KERN_MSG_H
 
-#include "event.h"
-#include <mware/list.h>
-
+#include <mware/event.h>
+#include <struct/list.h>
+#include <kern/proc.h>
 
 typedef struct MsgPort
 {
@@ -214,7 +222,7 @@ typedef struct Msg
  *
  * \see msg_unlockPort()
  */
-INLINE void msg_lockPort(MsgPort *port)
+INLINE void msg_lockPort(UNUSED_ARG(MsgPort *, port))
 {
        proc_forbid();
 }
@@ -224,7 +232,7 @@ INLINE void msg_lockPort(MsgPort *port)
  *
  * \see msg_lockPort()
  */
-INLINE void msg_unlockPort(MsgPort *port)
+INLINE void msg_unlockPort(UNUSED_ARG(MsgPort *, port))
 {
        proc_permit();
 }
@@ -240,9 +248,9 @@ INLINE void msg_initPort(MsgPort *port, Event event)
 /** Queue \a msg into \a port, triggering the associated event */
 INLINE void msg_put(MsgPort *port, Msg *msg)
 {
-       msg_portLock(port);
+       msg_lockPort(port);
        ADDTAIL(&port->queue, &msg->link);
-       msg_portUnlock(port);
+       msg_unlockPort(port);
 
        event_do(&port->event);
 }
@@ -256,9 +264,9 @@ INLINE Msg *msg_get(MsgPort *port)
 {
        Msg *msg;
 
-       msg_portLock(port);
-       msg = (Msg *)REMHEAD(&port->queue);
-       msg_portUnlock(port);
+       msg_lockPort(port);
+       msg = (Msg *)list_remHead(&port->queue);
+       msg_unlockPort(port);
 
        return msg;
 }
@@ -268,11 +276,11 @@ INLINE Msg *msg_peek(MsgPort *port)
 {
        Msg *msg;
 
-       msg_portLock(port);
-       msg = (Msg *)port->queue.head;
-       if (ISLISTEMPTY(&port->queue))
+       msg_lockPort(port);
+       msg = (Msg *)port->queue.head.succ;
+       if (LIST_EMPTY(&port->queue))
                msg = NULL;
-       msg_portUnlock(port);
+       msg_unlockPort(port);
 
        return msg;
 }
@@ -283,4 +291,10 @@ INLINE void msg_reply(Msg *msg)
        msg_put(msg->replyPort, msg);
 }
 
+/** \} */ //defgroup kern_msg
+
+int msg_testRun(void);
+int msg_testSetup(void);
+int msg_testTearDown(void);
+
 #endif /* KERN_MSG_H */