]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - src/ti/ipc/MessageQ.h
4a6623d2f7a856f44452d29850b9659956f51b5a
[ipc/ipcdev.git] / src / ti / ipc / MessageQ.h
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /** ============================================================================
34  *  @file       MessageQ.h
35  *
36  *  @brief      MessageQ Manager
37  *
38  *  The MessageQ module supports the structured sending and receiving of
39  *  variable length messages. This module can be used for homogeneous
40  *  (DSP to DSP)  or heterogeneous (Arm to DSP) multi-processor messaging.
41  *
42  *  MessageQ provides more sophisticated messaging than other modules. It is
43  *  typically used for complex situations such as multi-processor messaging.
44  *
45  *  The following are key features of the MessageQ module:
46  *  - Writers and readers can be relocated to another processor with no
47  *    runtime code changes.
48  *  - Timeouts are allowed when receiving messages.
49  *  - Readers can determine the writer and reply back.
50  *  - Receiving a message is deterministic when the timeout is zero.
51  *  - Messages can reside on any message queue.
52  *  - Supports zero-copy transfers.
53  *  - Can send and receive from any type of thread.
54  *  - Notification mechanism is specified by application.
55  *  - Allows QoS (quality of service) on message buffer pools. For example,
56  *    using specific buffer pools for specific message queues.
57  *
58  *  Messages are sent and received by being placed on and removed from a
59  *  message queue. A reader is a thread that gets (reads) messages from a
60  *  message queue. A writer is a thread that puts (writes) a message to a
61  *  message queue. Each message queue has one reader and can have many writers.
62  *  A thread may read from or write to multiple message queues.
63  *
64  *  Conceptually, the reader thread owns a message queue. The reader thread
65  *  creates a message queue. The writer threads open a created message queue
66  *  to get access to them.
67  *
68  *  Message queues are identified by a system-wide unique name. Internally,
69  *  MessageQ uses the NameServer module for managing
70  *  these names. The names are used for opening a message queue.
71  *
72  *  Messages must be allocated from the MessageQ module. Once a message is
73  *  allocated, it can be sent to any message queue. Once a message is sent, the
74  *  writer loses ownership of the message and should not attempt to modify the
75  *  message. Once the reader receives the message, it owns the message. It
76  *  may either free the message or re-use the message.
77  *
78  *  Messages in a message queue can be of variable length. The only
79  *  requirement is that the first field in the definition of a message must be a
80  *  #MessageQ_MsgHeader structure. For example:
81  *  @code
82  *  typedef struct MyMsg {
83  *      MessageQ_MsgHeader header;
84  *      ...
85  *  } MyMsg;
86  *  @endcode
87  *
88  *  The MessageQ API uses the MessageQ_MsgHeader internally. Your application
89  *  should not modify or directly access the fields in the MessageQ_MsgHeader.
90  *
91  *  All messages sent via the MessageQ module must be allocated from a
92  *  heap. The heap can also be used for other memory allocation not related to
93  *  MessageQ.
94  *
95  *  An application can use multiple heaps. The purpose of having multiple
96  *  heaps is to allow an application to regulate its message usage. For
97  *  example, an application can allocate critical messages from one heap of fast
98  *  on-chip memory and non-critical messages from another heap of slower
99  *  external memory.
100  *
101  *  The MessageQ_registerHeap() API is used to
102  *  assign a MessageQ heapId to a heap. When allocating a message, the heapId
103  *  is used, not the heap handle. This heapId is actually placed into the
104  *  message (part of the #MessageQ_MsgHeader). Care must be taken when
105  *  assigning heapIds. Refer to the MessageQ_registerHeap() API description for
106  *  more details.
107  *
108  *  MessageQ also supports the usage of messages that are not allocated via the
109  *  MessageQ_alloc() function. Please refer to the MessageQ_staticMsgInit()
110  *  function description for more details.
111  *
112  *  MessageQ supports reads/writes of different thread models. This is
113  *  accomplished by having the creator of the message queue specify a
114  *  synchronizer via the #MessageQ_Params::synchronizer
115  *  configuration parameter. The synchronizer is signaled whenever the
116  *  MessageQ_put() is called. The synchronizer waits if MessageQ_get() is called
117  *  and there are no messages.
118  *
119  *  Since ISyncs are binary, the reader must drain the message queue of all
120  *  messages before waiting for another signal. For example, if the reader
121  *  was a SYSBIOS Swi, the synchronizer instance could be a SyncSwi.
122  *  If a #MessageQ_put was called, the Swi_post() would
123  *  be called. The Swi would run and it must call #MessageQ_get until no
124  *  messages are returned.
125  *
126  *  The MessageQ header should be included in an application as follows:
127  *  @code
128  *  #include <ti/ipc/MessageQ.h>
129  *  @endcode
130  *
131  *  @version        0.00.01
132  *
133  *  ============================================================================
134  */
136 #ifndef ti_ipc_MessageQ__include
137 #define ti_ipc_MessageQ__include
139 #include <ti/ipc/MultiProc.h>
141 #if defined (__cplusplus)
142 extern "C" {
143 #endif
145 /* =============================================================================
146  *  All success and failure codes for the module
147  * =============================================================================
148  */
150 /*!
151  *  @brief  The resource is still in use
152  */
153 #define MessageQ_S_BUSY                  2
155 /*!
156  *  @brief  The module has been already setup
157  */
158 #define MessageQ_S_ALREADYSETUP          1
160 /*!
161  *  @brief  Operation is successful.
162  */
163 #define MessageQ_S_SUCCESS               0
165 /*!
166  *  @brief  Operation is not successful.
167  */
168 #define MessageQ_E_FAIL                 -1
170 /*!
171  *  @brief  There is an invalid argument.
172  */
173 #define MessageQ_E_INVALIDARG           -2
175 /*!
176  *  @brief  Operation resulted in memory failure.
177  */
178 #define MessageQ_E_MEMORY               -3
180 /*!
181  *  @brief  The specified entity already exists.
182  */
183 #define MessageQ_E_ALREADYEXISTS        -4
185 /*!
186  *  @brief  Unable to find the specified entity.
187  */
188 #define MessageQ_E_NOTFOUND             -5
190 /*!
191  *  @brief  Operation timed out.
192  */
193 #define MessageQ_E_TIMEOUT              -6
195 /*!
196  *  @brief  Module is not initialized.
197  */
198 #define MessageQ_E_INVALIDSTATE         -7
200 /*!
201  *  @brief  A failure occurred in an OS-specific call
202  */
203 #define MessageQ_E_OSFAILURE            -8
205 /*!
206  *  @brief  Specified resource is not available
207  */
208 #define MessageQ_E_RESOURCE             -9
210 /*!
211  *  @brief  Operation was interrupted. Please restart the operation
212  */
213 #define MessageQ_E_RESTART              -10
215 /*!
216  *  @brief  An invalid message was encountered
217  */
218 #define MessageQ_E_INVALIDMSG           -11
220 /*!
221  *  @brief  Not the owner
222  */
223 #define MessageQ_E_NOTOWNER             -12
225 /*!
226  *  @brief  Operation resulted in error
227  */
228 #define MessageQ_E_REMOTEACTIVE         -13
230 /*!
231  *  @brief  An invalid heap id was encountered
232  */
233 #define MessageQ_E_INVALIDHEAPID        -14
235 /*!
236  *  @brief  An invalid MultiProc id was encountered
237  */
238 #define MessageQ_E_INVALIDPROCID        -15
240 /*!
241  *  @brief  The max has been reached.
242  */
243 #define MessageQ_E_MAXREACHED           -16
245 /*!
246  *  @brief  Attempting to use an unregistered heap id.
247  */
248 #define MessageQ_E_UNREGISTEREDHEAPID   -17
250 /*!
251  *  @brief  Trying to free a statically initialized message
252  */
253 #define MessageQ_E_CANNOTFREESTATICMSG  -18
255 /*!
256  *  @brief  MessageQ was unblocked
257  */
258 #define MessageQ_E_UNBLOCKED            -19
260 /* =============================================================================
261  *  Macros
262  * =============================================================================
263  */
265 /*!
266  *  @brief      Used as the timeout value to specify wait forever
267  */
268 #define MessageQ_FOREVER                ~(0)
270 /*!
271  *  @brief      Invalid message id
272  */
273 #define MessageQ_INVALIDMSGID           0xffff
275 /*!
276  *  @brief      Invalid message queue
277  */
278 #define MessageQ_INVALIDMESSAGEQ        0xffff
280 /*!
281  *  @brief      Mask to extract priority setting
282  */
283 #define MessageQ_PRIORITYMASK           0x3
285 /*!
286  *  @brief      Extract the destination queue ID from a message.
287  *
288  *  Can only be used on the same processor where the destination queue resides.
289  *  This function should only be used by Message Queue Transport writers.
290  *
291  *  @param[in]  msg     Message of type #MessageQ_Msg
292  *
293  *  @retval  queueId    Destination message queue ID of type #MessageQ_QueueId
294  */
295 #define MessageQ_getDstQueue(msg)                                             \
296         ((msg)->dstId == (MessageQ_QueueIndex)MessageQ_INVALIDMESSAGEQ) ?     \
297             (MessageQ_QueueId)MessageQ_INVALIDMESSAGEQ :                      \
298             (MessageQ_QueueId)(((MessageQ_QueueId)MultiProc_self() << 16u)    \
299             | (((MessageQ_Msg)(msg))->dstId))
302 /*!
303  *  @brief   Retrieves the message ID of a message.
304  *
305  *  This function retrieves the message ID from the message. The
306  *  MessageQ_setMsgId() function is used to insert the message ID.
307  *
308  *  The message id is part of the #MessageQ_MsgHeader header and is in every
309  *  MessageQ message. All message ids are initialized to #MessageQ_INVALIDMSGID
310  *  in the MessageQ_alloc() and MessageQ_staticMsgInit() calls.
311  *
312  *  @param[in]  msg     Message of type #MessageQ_Msg
313  *
314  *  @retval     msgId   16-bit message ID from the message
315  */
316 #define MessageQ_getMsgId(msg) (((MessageQ_Msg) (msg))->msgId)
318 /*!
319  *  @brief   Returns the size of the specified message. This function is helpful
320  *           when re-using a message.
321  *
322  *  @param[in]  msg     Message of type #MessageQ_Msg
323  *
324  *  @retval     size    Size of the message
325  */
326 #define MessageQ_getMsgSize(msg) (((MessageQ_Msg) (msg))->msgSize)
328 /*!
329  *  @brief   Gets the message priority of a message
330  *
331  *  @param[in]  msg     Message of type #MessageQ_Msg
332  *
333  *  @retval priority    Priority of the message
334  */
335 #define MessageQ_getMsgPri(msg)        \
336                  ((((MessageQ_Msg) (msg))->flags & MessageQ_PRIORITYMASK))
338 /*!
339  *  @brief      Returns the MultiProc processor id on which the queue resides
340  *
341  *  Message queues reside on the processor that created them. This function
342  *  allows the caller to determined on which processor the queue resides.
343  *
344  *  @param[in]  queueId      Unique #MessageQ_QueueId that identifies the queue
345  *
346  *  @retval     procId       The MultiProc id on which the queue resides
347  */
348 #define MessageQ_getProcId(queueId)     \
349                  ((UInt16)((queueId) >> 16))
351 /*!
352  *  @brief   Retrieves the message queue ID from a message.
353  *
354  *  This function along with the MessageQ_setReplyQueue() function can  be used
355  *  instead of the open function. The sender of a message can embed a messageQ
356  *  into the message with the MessageQ_setReplyQueue() function. The receiver of
357  *  the message can extract the message queue ID with this function.
358  *
359  *  This method is particularing useful in a client/server relationship where
360  *  the server does not want to know who the clients are. The clients can embed
361  *  their message queue into the message to the server and the server extracts
362  *  it and uses it to reply.
363  *
364  *  @param[in]  msg     Message of type #MessageQ_Msg
365  *
366  *  @retval  queueId    Message queue ID of type #MessageQ_QueueId
367  */
368 #define MessageQ_getReplyQueue(msg)           \
369                 (MessageQ_QueueId)((((MessageQ_Msg) (msg))->replyProc << 16u) \
370                 | ((MessageQ_Msg)(msg))->replyId)
372 /*!
373  *  @brief   Sets the message id in a message.
374  *
375  *  This function sets the message ID in the message. The MessageQ_getMsgId()
376  *  function is used to retrieve the message ID.  The message id is part of the
377  *  #MessageQ_MsgHeader header and is in every MessageQ message. All message ids
378  *  are initialized to #MessageQ_INVALIDMSGID in the MessageQ_alloc() and
379  *  MessageQ_staticMsgInit() calls.
380  *
381  *  @param[in]   msg    Message of type #MessageQ_Msg
382  *  @param[in]   id     16-bit value
383  */
384 #define MessageQ_setMsgId(msg, id) ((MessageQ_Msg) (msg))->msgId = (id)
386 /*!
387  *  @brief   Sets the message priority of a message
388  *
389  *  @param[in]   msg      Message of type #MessageQ_Msg
390  *  @param[in]   priority Priority of message to be set.
391  */
392 #define MessageQ_setMsgPri(msg, priority) \
393         (((MessageQ_Msg) (msg))->flags = ((priority) & MessageQ_PRIORITYMASK))
395 /* =============================================================================
396  *  Structures & Enums
397  * =============================================================================
398  */
400 /*!
401  *  @brief  A 32-bit value that uniquely identifies a message queue
402  */
403 typedef UInt32 MessageQ_QueueId;
405 /*!
406  *  @brief  Local queue index
407  */
408 typedef UInt16 MessageQ_QueueIndex;
410 /*!
411  *  @brief  MessageQ_Handle type
412  */
413 typedef struct MessageQ_Object *MessageQ_Handle;
415 /*!
416  *  @brief  Structure defining parameters for the MessageQ module.
417  */
418 typedef struct {
419     Void *synchronizer;
420     /*!< Synchronizer instance used to signal IO completion
421      *
422      *  The synchronizer is used in MessageQ_put() and MessageQ_get().
423      *  The synchronizer signal is called as part of MessageQ_put().
424      *  The synchronizer waits in MessageQ_get() if there are no messages
425      *  present.
426      */
428 } MessageQ_Params;
430 /*!
431  *  @brief      Required first field in every message
432  */
433 typedef struct {
434     Bits32       reserved0;         /*!< reserved for List.elem->next       */
435     Bits32       reserved1;         /*!< reserved for List.elem->prev       */
436     Bits32       msgSize;           /*!< message size                       */
437     Bits16       flags;             /*!< bitmask of different flags         */
438     Bits16       msgId;             /*!< message id                         */
439     Bits16       dstId;             /*!< destination queue id               */
440     Bits16       dstProc;           /*!< destination processor id           */
441     Bits16       replyId;           /*!< reply id                           */
442     Bits16       replyProc;         /*!< reply processor                    */
443     Bits16       srcProc;           /*!< source processor                   */
444     Bits16       heapId;            /*!< heap id                            */
445     Bits16       seqNum;            /*!< sequence number                    */
446     Bits16       reserved;          /*!< reserved                           */
447 } MessageQ_MsgHeader;
449 /*!
450  *  @brief  Typedef for ease of use
451  */
452 typedef MessageQ_MsgHeader *MessageQ_Msg;
454 /*!
455  *  @brief      Message priority
456  */
457 typedef enum {
458     MessageQ_NORMALPRI      = 0,    /*!< Normal Priority                  */
459     MessageQ_HIGHPRI        = 1,    /*!< High Priority                    */
460     MessageQ_RESERVEDPRI    = 2,    /*!< Reserved Priorit                 */
461     MessageQ_URGENTPRI      = 3     /*!< Urgent Priority                  */
462 } MessageQ_Priority;
465 /* =============================================================================
466  *  MessageQ Module-wide Functions
467  * =============================================================================
468  */
470 /*!
471  *  @brief      Initialize MessageQ_Params
472  *
473  *  @param[in]  params      Parameters required to create a MessageQ
474  */
475 Void MessageQ_Params_init(MessageQ_Params *params);
477 /*!
478  *  @brief      Create a MessageQ instance
479  *
480  *  The name supplied here does not have to be in persistent memory.  The
481  *  maximum length of the string supplied here, including the '\\0' terminator
482  *  is '32' by default.
483  *
484  *  There are no verifications to ensure that the name supplied in
485  *  MessageQ_create() is unique across all processors. Caution must be exercised
486  *  to ensure that each processor uses a unique name.
487  *
488  *  @param[in]  name        Name of the queue
489  *  @param[in]  params      Initialized MessageQ parameters
490  *
491  *  @return     MessageQ Handle
492  */
493 MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params);
495 /*!
496  *  @brief      Delete a created MessageQ instance
497  *
498  *  This function deletes a created message queue instance. If the
499  *  message queue is non-empty, any messages remaining in the queue
500  *  will not be freed and will be lost.
501  *
502  *  @param[in,out]  handlePtr   Pointer to handle to delete.
503  *
504  *  @return     MessageQ status:
505  *              - #MessageQ_E_FAIL: delete failed
506  *              - #MessageQ_S_SUCCESS: delete successful
507  */
508 Int MessageQ_delete(MessageQ_Handle *handlePtr);
510 /*!
511  *  @brief      Open a message queue
512  *
513  *  MessageQ_open() is used to retrieve the queue id for a queue that has been
514  *  created either locally or remotely.  Note that the queueId is simply a
515  *  32 bit value that uniquely identifies a queue.  Therefore, it is also
516  *  possible to put a message on a queue whose queueId has been retrieved using
517  *  any other method.
518  *
519  *  @param[in]  name        Name of queue to open
520  *  @param[out] queueId     QueueId that can be used in MessageQ_put()
521  *
522  *  @return     MessageQ status:
523  *              - #MessageQ_E_NOTFOUND: open failed (name not found on any
524  *                processor)
525  *              - #MessageQ_S_SUCCESS: open successful
526  */
527 Int MessageQ_open(String name, MessageQ_QueueId *queueId);
529 /*!
530  *  @brief      Close the opened handle
531  *
532  *  Only close a queueId that was returned from MessageQ_open().
533  *
534  *  @param[in]  queueId     Pointer to queueId to close
535  *
536  *  @return     MessageQ status:
537  *              - #MessageQ_E_FAIL: close failed
538  *              - #MessageQ_S_SUCCESS: close successful
539  */
540 Int MessageQ_close(MessageQ_QueueId *queueId);
542 /*!
543  *  @brief      Allocates a message from the heap
544  *
545  *  This function allocates a message from the heap associated with the heapId.
546  *  The first field of the message must be a #MessageQ_MsgHeader structure.
547  *  For example:
548  *      @code
549  *      typedef struct MyMsg {
550  *         MessageQ_MsgHeader header;
551  *         ...
552  *      } MyMsg;
553  *      @endcode
554  *
555  *  @param[in]  heapId      heapId
556  *  @param[in]  size        size of requested message (including the
557  *                          #MessageQ_MsgHeader).
558  *
559  *  @pre        @c size must be at least large enough to hold a
560  *              MessageQ_MsgHeader
561  *
562  *  @return    Allocated message or NULL if no memory.
563  */
564 MessageQ_Msg MessageQ_alloc(UInt16 heapId, UInt32 size);
566 /*!
567  *  @brief      Frees a message back to the heap
568  *
569  *  Frees the message back to the heap that was used to allocate it.
570  *
571  *  @param[in]  msg         Message to free.
572  *
573  *  @return     MessageQ status:
574  *              - #MessageQ_E_FAIL: failed to free message
575  *              - #MessageQ_S_SUCCESS: successfully freed the message
576  */
577 Int MessageQ_free(MessageQ_Msg msg);
579 /*!
580  *  @brief      Register a heap with MessageQ
581  *
582  *  This function registers a heap with MessageQ. The user selects a unique
583  *  heapId associated with this heap. When a message is allocated via
584  *  MessageQ_alloc(), the heapId is specified. Internally, MessageQ
585  *  uses the heapId to access the heap.
586  *
587  *  Care must be taken when assigning heapIds. Internally MessageQ stores
588  *  the heapId into the message. When the message is freed
589  *  (via MessageQ_free()), the heapId is used to determine which heap to use.
590  *  On systems with shared memory the heapIds must match on corresponding
591  *  processors. For example, assume there is a heap called myHeap which
592  *  acts on shared memory and processors 0 and 1 both use this heap.
593  *  When you register the heap with MessageQ, the same heapId must be used
594  *  on both processor 0 and 1.
595  *
596  *  If a heap is already registered for the specified heapId, no action is
597  *  taken and #MessageQ_E_ALREADYEXISTS is returned.
598  *
599  *  @param[in]  heap        Heap to register
600  *  @param[in]  heapId      heapId associated with the heap
601  *
602  *  @return     MessageQ status:
603  *              - #MessageQ_S_SUCCESS: heap successfully registered
604  *              - #MessageQ_E_ALREADYEXISTS: heap already exists with heapId
605  */
606 Int MessageQ_registerHeap(Ptr heap, UInt16 heapId);
608 /*!
609  *  @brief      Unregister a heap with MessageQ
610  *
611  *  This function unregisters the heap associated with the heapId.
612  *  Care must be taken to ensure that there are no outstanding messages
613  *  allocated from this heap. If there are outstanding messages, an attempt
614  *  to free the message will result in non-deterministic results.
615  *
616  *  @param[in]  heapId      Heap to unregister
617  *
618  *  @return     MessageQ status:
619  *              - #MessageQ_S_SUCCESS: heap successfully unregistered
620  */
621 Int MessageQ_unregisterHeap(UInt16 heapId);
623 /*!
624  *  @brief      Sets the message tracing flag on a given message
625  *
626  *  This function enables message tracing for a message.  Tracing is offered
627  *  in the form of Log messages that are output during operations on the
628  *  message (i.e. MessageQ_free(), MessageQ_put(), etc).
629  *
630  *  @param      msg         Message
631  *  @param      traceFlag   Message trace flag (TRUE = tracing enabled)
632  */
633 Void MessageQ_setMsgTrace(MessageQ_Msg msg, Bool traceFlag);
635 /*!
636  *  @brief      Initializes a message not obtained from MessageQ_alloc()
637  *
638  *  There are several fields in the #MessageQ_MsgHeader that
639  *  are initialized by the MessageQ_alloc() function. MessageQ_staticMsgInit()
640  *  can be used to initialize these fields for messages that are
641  *  not allocated from MessageQ.
642  *
643  *  There is one strict constraint with using messages not allocated
644  *  from MessageQ. The message cannot be freed via MessageQ_free().
645  *  This includes
646  *      - The application calling MessageQ_free() on the same processor
647  *      - The application calling MessageQ_free() on a different processor
648  *      - The application cannot send the message to another processor
649  *        where the transport might call MessageQ_free() on the message.
650  *        For example, copy based transport call MessageQ_free() after sending
651  *        the message.
652  *  If a staticMsgInit'd msg is passed to MessageQ_free() an assert will occur
653  *
654  *  @param      msg     Message to initialize
655  *  @param[in]  size    Size of the message in MAUs
656  *
657  *  @pre    @c size must be at least large enough to hold a #MessageQ_MsgHeader
658  */
659 Void MessageQ_staticMsgInit(MessageQ_Msg msg, UInt32 size);
661 /* =============================================================================
662  *  MessageQ Per-instance Functions
663  * =============================================================================
664  */
666 /*!
667  *  @brief      Gets a message from the message queue
668  *
669  *  This function returns a status. It also returns a message in msg.
670  *  If no message is available, it blocks on the synchronizer object
671  *  until the synchronizer is signaled or a timeout occurs.
672  *  The synchronizer is signaled, when Message_put is called on the MessageQ
673  *  handle. If a timeout occurs, the msg is set to NULL and the status is
674  *  #MessageQ_E_TIMEOUT. If a timeout of zero is specified, the function
675  *  returns immediately and if no message is available, the msg
676  *  is set to NULL and the status is #MessageQ_E_TIMEOUT. The
677  *  #MessageQ_E_UNBLOCKED status is return, if MessageQ_unblock is called
678  *  on the MessageQ handle. If a message is successfully retrieved, the msg
679  *  is set to the message and a #MessageQ_S_SUCCESS status is returned.
680  *
681  *  @param[in]  handle      MessageQ handle
682  *  @param[out] msg         Pointer to the message
683  *  @param[in]  timeout     Maximum duration to wait for a message in
684  *                          microseconds.
685  *
686  *  @return     MessageQ status:
687  *              - #MessageQ_S_SUCCESS: Message successfully returned
688  *              - #MessageQ_E_TIMEOUT: MessageQ_get() timed out
689  *              - #MessageQ_E_UNBLOCKED: MessageQ_get() was unblocked
690  *              - #MessageQ_E_FAIL:    A general failure has occurred
691  *
692  *  @sa         MessageQ_put()
693  *  @sa         MessageQ_unblock()
694  */
695 Int MessageQ_get(MessageQ_Handle handle, MessageQ_Msg *msg, UInt timeout);
697 /*!
698  *  @brief      Place a message onto a message queue
699  *
700  *  This call places the message onto the specified message queue. The
701  *  message queue could be local or remote. The MessageQ module manages
702  *  the delivery.
703  *
704  *  In the case where the queue is remote, MessageQ does not guarantee that
705  *  the message is actually delivered before the MessageQ_put() call returns
706  *
707  *  The queue id must have been returned from one of the following functions:
708  *  - MessageQ_open()
709  *  - MessageQ_getReplyQueue()
710  *  - MessageQ_getDstQueue()
711  *
712  *  After the message is placed onto the final destination, the queue's
713  *  #MessageQ_Params::synchronizer signal function is called.
714  *
715  *  The application loses ownership of the message once MessageQ_put() is called.
716  *
717  *  @param[in]  queueId     Destination MessageQ
718  *  @param[in]  msg         Message to be sent.
719  *
720  *  @return     Status of the call.
721  *              - #MessageQ_S_SUCCESS denotes success.
722  *              - #MessageQ_E_FAIL denotes failure. The put was not successful.
723  *                 The caller still owns the message.
724  */
725 Int MessageQ_put(MessageQ_QueueId queueId, MessageQ_Msg msg);
727 /*!
728  *  @brief      Returns the number of messages in a message queue
729  *
730  *  This function returns the number of messages in a message queue.
731  *
732  *  @param[in]  handle      MessageQ handle
733  *
734  *  @return     Number of messages in the message queue.
735  */
736 Int MessageQ_count(MessageQ_Handle handle);
738 /*!
739  *  @brief      Returns the QueueId associated with the handle
740  *
741  *  Since the MessageQ_put() function takes a QueueId, the creator
742  *  of a message queue cannot send a message to itself without
743  *  retrieving the QueueId. This function extracts the QueueId
744  *  from the object.
745  *
746  *  @param[in]  handle      MessageQ handle
747  *
748  *  @return     QueueId associated to the object
749  */
750 UInt32 MessageQ_getQueueId(MessageQ_Handle handle);
752 /*!
753  *  @brief      Embeds a source message queue into a message
754  *
755  *  This function along with MessageQ_getReplyQueue()
756  *  can be used instead of MessageQ_open(). The sender
757  *  of a message can embed a messageQ into the message with this
758  *  function. The receiver of the message can extract the message queue
759  *  id with the MessageQ_getReplyQueue() function.
760  *
761  *  This method is particularly useful in a client/server relationship
762  *  where the server does not want to know who the clients are. The
763  *  clients can embed their message queue into the message to the server
764  *  and the server extracts it and uses it to reply.
765  *
766  *  @param      handle      MessageQ handle
767  *  @param      msg         Message to embed queue into
768  */
769 Void MessageQ_setReplyQueue(MessageQ_Handle handle, MessageQ_Msg msg);
771 /*!
772  *  @brief      Unblocks a MessageQ
773  *
774  *  Unblocks a reader thread that is blocked on a MessageQ_get().  The
775  *  MessageQ_get() call will return with status #MessageQ_E_UNBLOCKED indicating
776  *  that it returned due to a MessageQ_unblock() rather than a timeout or a
777  *  received message.  This call should only be used during a shutdown sequence
778  *  in order to ensure that there is no blocked reader on a queue before
779  *  deleting the queue.  A queue may not be used after it has been unblocked.
780  *
781  *  MessageQ_unblock() works by raising a flag in the queue indicating that it
782  *  is unblocked and then signaling the synchronizer that is configured with
783  *  the target queue.  If MessageQ_unblock() is called upon a queue that has
784  *  no blocked listeners, then any subsequent MessageQ_get will not block and
785  *  will immediately return #MessageQ_E_UNBLOCKED regardless of whether there
786  *  is a message on the queue.
787  *
788  *  Restrictions:
789  *  -  A queue may not be used after it has been unblocked.
790  *  -  MessageQ_unblock() may only be called on a local queue.
791  *  -  May only be used with a queue configured with a blocking synchronizer.
792  *
793  *  @param[in]  handle      MessageQ handle
794  *
795  *  @sa         MessageQ_get
796  */
797 Void MessageQ_unblock(MessageQ_Handle handle);
799 #if defined (__cplusplus)
801 #endif /* defined (__cplusplus) */
802 #endif /* ti_ipc_MessageQ__include */