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