// VXWMsgQ/vxwMsgQLib.h - message queue classes // Copyright 1995-1999 Wind River Systems, Inc. // modification history // -------------------- // 01b,23feb99,fle doc : made it refgen compliant // 01c,21feb99,jdi added library section, checked in documentation. // 01b,03oct95,rhp documented. // 01a,15jun95,srh written. // DESCRIPTION // The `VXWMsgQ' class provides message queues, the primary intertask // communication mechanism within a single CPU. Message queues allow // a variable number of messages (varying in length) to be queued in // first-in-first-out (FIFO) order. Any task or interrupt service // routine can send messages to a message queue. Any task can receive // messages from a message queue. Multiple tasks can send to and // receive from the same message queue. Full-duplex communication // between two tasks generally requires two message queues, one for // each direction. // // CREATING AND USING MESSAGE QUEUES // The message-queue constructor takes parameters to specify the // maximum number of messages that can be queued to that message queue and // the maximum length in bytes of each message. Enough buffer space is // pre-allocated to accommodate the specified number of messages of // specified length. // // A task or interrupt service routine sends a message to a message // queue with VXWMsgQ::send(). If no tasks are waiting for messages // on the message queue, the message is simply added to the buffer of // messages for that queue. If any tasks are already waiting to // receive a message from the message queue, the message is // immediately delivered to the first waiting task. // // A task receives a message from a message queue with VXWMsgQ::receive(). // If any messages are already available in the message queue's buffer, // the first message is immediately dequeued and returned to the caller. // If no messages are available, the calling task blocks and joins // a queue of tasks waiting for messages. This queue of waiting tasks can // be ordered either by task priority or FIFO, as specified in an option // parameter when the queue is created. // // TIMEOUTS // Both VXWMsgQ::send() and VXWMsgQ::receive() take timeout // parameters. When sending a message, if no buffer space is // available to queue the message, the timeout specifies how many // ticks to wait for space to become available. When receiving a // message, the timeout specifies how many ticks to wait if no message // is immediately available. The parameter can have the // special values NO_WAIT (0) or WAIT_FOREVER (-1). NO_WAIT means the // routine should return immediately; WAIT_FOREVER means the routine // should never time out. // // URGENT MESSAGES // The VXWMsgQ::send() routine allows the priority of a message to be specified // as either normal (MSG_PRI_NORMAL) or urgent (MSG_PRI_URGENT). Normal // priority messages are added to the tail of the list of queued messages, // while urgent priority messages are added to the head of the list. // // INCLUDE FILES: vxwMsgQLib.h // // SEE ALSO: pipeDrv, msgQSmLib, // .pG "Basic OS" // // SECTION: 1C // #ifndef vxwMsgQLib_h #define vxwMsgQLib_h #include "vxWorks.h" #include "msgQLib.h" #include "vxwObject.h" #include "vxwErr.h" class VXWMsgQ : virtual public VXWIdObject { public: //_ VXWMsgQ Public Constructors /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::VXWMsgQ - create and initialize a message queue // // This constructor creates a message queue capable of holding up to // messages, each up to bytes long. The queue can be created // with the following options specified as : // .iP MSG_Q_FIFO 20 // queue pended tasks in FIFO order. // .iP MSG_Q_PRIORITY // queue pended tasks in priority order. // // RETURNS: N/A. // // ERRNO: // S_memLib_NOT_ENOUGH_MEMORY // - unable to allocate memory for message queue and message buffers. // // S_intLib_NOT_ISR_CALLABLE // - called from an interrupt service routine. // // SEE ALSO: vxwSmLib VXWMsgQ (int maxMsgs, int maxMsgLen, int opts) : msgq_ (msgQCreate (maxMsgs, maxMsgLen, opts)) { if (msgq_ == 0) vxwThrowErrno (); } /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::VXWMsgQ - build message-queue object from ID // // Use this constructor to manipulate a message queue that was not created // using C++ interfaces. The argument is the message-queue // identifier returned and used by the C interface to the VxWorks // message queue facility. // // RETURNS: N/A. // // SEE ALSO: msgQLib VXWMsgQ (MSG_Q_ID id) : msgq_ (id) { } /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::~VXWMsgQ - delete message queue // // This destructor deletes a message queue. Any task blocked on either // a VXWMsgQ::send() or VXWMsgQ::receive() is unblocked and receives an error // from the call with `errno' set to S_objLib_OBJECT_DELETED. // // RETURNS: N/A. // // ERRNO: // S_objLib_OBJ_ID_ERROR // - is invalid. // // S_intLib_NOT_ISR_CALLABLE // - called from an interrupt service routine. virtual ~VXWMsgQ () { if (msgQDelete (msgq_) != OK) vxwThrowErrno (); } //_ VXWMsgQ Public Member Functions /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::send - send a message to message queue // // This routine sends the message in of length to // its message queue. If any tasks are already waiting to receive // messages on the queue, the message is immediately delivered to the // first waiting task. If no task is waiting to receive messages, the // message is saved in the message queue. // // The parameter specifies the number of ticks to wait for free // space if the message queue is full. The parameter can also have // the following special values: // .iP NO_WAIT 22 // return immediately, even if the message has not been sent. // .iP WAIT_FOREVER // never time out. // .LP // // The parameter specifies the priority of the message being sent. // The possible values are: // .iP MSG_PRI_NORMAL 22 // normal priority; add the message to the tail of the list of queued // messages. // .iP MSG_PRI_URGENT // urgent priority; add the message to the head of the list of queued messages. // .LP // // USE BY INTERRUPT SERVICE ROUTINES // This routine can be called by interrupt service routines as well as // by tasks. This is one of the primary means of communication // between an interrupt service routine and a task. When called from an // interrupt service routine, must be NO_WAIT. // // RETURNS: OK or ERROR. // // ERRNO: // S_objLib_OBJ_DELETED // - the message queue was deleted while waiting to a send message. // // S_objLib_OBJ_UNAVAILABLE // - is set to NO_WAIT, and the queue is full. // // S_objLib_OBJ_TIMEOUT // - the queue is full for ticks. // // S_msgQLib_INVALID_MSG_LENGTH // - is larger than the set for the message queue. // // S_msgQLib_NON_ZERO_TIMEOUT_AT_INT_LEVEL // - called from an ISR, with not set to NO_WAIT. STATUS send (char * buffer, UINT nBytes, int timeout, int pri) { return msgQSend (msgq_, buffer, nBytes, timeout, pri); } /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::receive - receive a message from message queue // // This routine receives a message from its message queue. // The received message is copied into the specified , which is // in length. If the message is longer than , // the remainder of the message is discarded (no error indication // is returned). // // The parameter specifies the number of ticks to wait for // a message to be sent to the queue, if no message is available when // VXWMsgQ::receive() is called. The parameter can also have // the following special values: // .iP NO_WAIT 22 // return immediately, even if the message has not been sent. // .iP WAIT_FOREVER // never time out. // .LP // // WARNING: This routine must not be called by interrupt service routines. // // RETURNS: // The number of bytes copied to , or ERROR. // // ERRNO: // S_objLib_OBJ_DELETED // - the message queue was deleted while waiting to receive a message. // // S_objLib_OBJ_UNAVAILABLE // - is set to NO_WAIT, and no messages are available. // // S_objLib_OBJ_TIMEOUT // - no messages were received in ticks. // // S_msgQLib_INVALID_MSG_LENGTH // - is less than 0. int receive (char * buffer, UINT nBytes, int timeout) { return msgQReceive (msgq_, buffer, nBytes, timeout); } /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::numMsgs - report the number of messages queued // // This routine returns the number of messages currently queued to the // message queue. // // RETURNS: // The number of messages queued, or ERROR. // // ERRNO: // S_objLib_OBJ_ID_ERROR // - is invalid. int numMsgs () const { return msgQNumMsgs (msgq_); } /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::info - get information about message queue // // This routine gets information about the state and contents of its message // queue. The parameter is a pointer to a structure of type MSG_Q_INFO // defined in msgQLib.h as follows: // // .CS // typedef struct /@ MSG_Q_INFO @/ // { // int numMsgs; /@ OUT: number of messages queued @/ // int numTasks; /@ OUT: number of tasks waiting on msg q @/ // int sendTimeouts; /@ OUT: count of send timeouts @/ // int recvTimeouts; /@ OUT: count of receive timeouts @/ // int options; /@ OUT: options with which msg q was created @/ // int maxMsgs; /@ OUT: max messages that can be queued @/ // int maxMsgLength; /@ OUT: max byte length of each message @/ // int taskIdListMax; /@ IN: max tasks to fill in taskIdList @/ // int * taskIdList; /@ PTR: array of task IDs waiting on msg q @/ // int msgListMax; /@ IN: max msgs to fill in msg lists @/ // char ** msgPtrList; /@ PTR: array of msg ptrs queued to msg q @/ // int * msgLenList; /@ PTR: array of lengths of msgs @/ // } MSG_Q_INFO; // .CE // // If the message queue is empty, there may be tasks blocked on receiving. // If the message queue is full, there may be tasks blocked on sending. // This can be determined as follows: // .iP "" 4 // If is 0, then indicates the number of tasks blocked // on receiving. // .iP // If is equal to , then is the number of // tasks blocked on sending. // .iP // If is greater than 0 but less than , then // will be 0. // .LP // // A list of pointers to the messages queued and their lengths can be // obtained by setting and to the addresses of // arrays to receive the respective lists, and setting to // the maximum number of elements in those arrays. If either list pointer // is NULL, no data is returned for that array. // // No more than message pointers and lengths are returned, // although is always returned with the actual number of messages // queued. // // For example, if the caller supplies a and // with room for 10 messages and sets to 10, but there are 20 // messages queued, then the pointers and lengths of the first 10 messages in // the queue are returned in and , but is // returned with the value 20. // // A list of the task IDs of tasks blocked on the message queue can be obtained // by setting to the address of an array to receive the list, and // setting to the maximum number of elements in that array. // If is NULL, then no task IDs are returned. No more than // task IDs are returned, although is always // returned with the actual number of tasks blocked. // // For example, if the caller supplies a with room for 10 task IDs // and sets to 10, but there are 20 tasks blocked on the // message queue, then the IDs of the first 10 tasks in the blocked queue // are returned in , but is returned with // the value 20. // // Note that the tasks returned in may be blocked for either send // or receive. As noted above this can be determined by examining . // The variables and are the counts of // the number of times VXWMsgQ::send() and VXWMsgQ::receive() (or // their equivalents in other language bindings) respectively returned // with a timeout. // // The variables , , and are the parameters // with which the message queue was created. // // WARNING // The information returned by this routine is not static and may be // obsolete by the time it is examined. In particular, the lists of // task IDs and/or message pointers may no longer be valid. However, // the information is obtained atomically, thus it is an accurate // snapshot of the state of the message queue at the time of the call. // This information is generally used for debugging purposes only. // // WARNING // The current implementation of this routine locks out interrupts while // obtaining the information. This can compromise the overall interrupt // latency of the system. Generally this routine is used for debugging // purposes only. // // RETURNS: OK or ERROR. STATUS info (MSG_Q_INFO *pInfo) const { return msgQInfoGet (msgq_, pInfo); } /////////////////////////////////////////////////////////////////////////////// // // VXWMsgQ::show - show information about a message queue // // This routine displays the state and optionally the contents of a message // queue. // // A summary of the state of the message queue is displayed as follows: // .CS // Message Queue Id : 0x3f8c20 // Task Queuing : FIFO // Message Byte Len : 150 // Messages Max : 50 // Messages Queued : 0 // Receivers Blocked : 1 // Send timeouts : 0 // Receive timeouts : 0 // .CE // // If is 1, more detailed information is displayed. // If messages are queued, they are displayed as follows: // .CS // Messages queued: // # address length value // 1 0x123eb204 4 0x00000001 0x12345678 // .CE // // If tasks are blocked on the queue, they are displayed as follows: // .CS // Receivers blocked: // // NAME TID PRI DELAY // ---------- -------- --- ----- // tExcTask 3fd678 0 21 // .CE // // RETURNS: OK or ERROR. STATUS show (int level) const { return msgQShow (msgq_, level); } protected: VXWMsgQ () { } VXWMsgQ (const VXWMsgQ & aMsgQ) : msgq_ (aMsgQ.msgq_) { } VXWMsgQ & operator = (const VXWMsgQ & aMsgQ) { msgq_ = aMsgQ.msgq_; return *this; } virtual void * myValue (); MSG_Q_ID msgq_; }; #endif // ifndef vxwMsgQLib_h