7a1becd16954a13b6e4cc144eb90773ac65e05dc
[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 MessageQ_create().
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  Structure defining parameters for MessageQ_create2().
429  *
430  *  MessageQ_Params2 is a superset of MessageQ_Params. It is used
431  *  with MessageQ_create2().
432  */
433 typedef struct {
434     Void *synchronizer;
435     /*!< Synchronizer instance used to signal IO completion
436      *
437      *  The synchronizer is used in MessageQ_put() and MessageQ_get().
438      *  The synchronizer signal is called as part of MessageQ_put().
439      *  The synchronizer waits in MessageQ_get() if there are no messages
440      *  present.
441      */
443      MessageQ_QueueIndex queueIndex;
444      /*!< Value used to specify the index in the MessageQ array
445       *
446       *  This parameter allows an application to specify a queueIndex to
447       *  be used for a message queue. To use this functionality, the
448       *  MessageQ.numReservedEntries static configuration parameter must be
449       *  set to one more than the highest requested queueIndex. The
450       *  MessageQ.numReservedEntries parameter reserves that number of
451       *  message queue slots starting at 0 and proceeding to
452       *  (MessageQ.numReservedEntries - 1).
453       *
454       *  The default is MessageQ_ANY, which means it is not taken from the
455       *  reserved slots.
456       */
458 } MessageQ_Params2;
460 /*!
461  *  @brief      Required first field in every message
462  */
463 typedef struct {
464     Bits32       reserved0;         /*!< reserved for List.elem->next       */
465     Bits32       reserved1;         /*!< reserved for List.elem->prev       */
466     Bits32       msgSize;           /*!< message size                       */
467     Bits16       flags;             /*!< bitmask of different flags         */
468     Bits16       msgId;             /*!< message id                         */
469     Bits16       dstId;             /*!< destination queue id               */
470     Bits16       dstProc;           /*!< destination processor id           */
471     Bits16       replyId;           /*!< reply id                           */
472     Bits16       replyProc;         /*!< reply processor                    */
473     Bits16       srcProc;           /*!< source processor                   */
474     Bits16       heapId;            /*!< heap id                            */
475     Bits16       seqNum;            /*!< sequence number                    */
476     Bits16       reserved;          /*!< reserved                           */
477 } MessageQ_MsgHeader;
479 /*!
480  *  @brief  Typedef for ease of use
481  */
482 typedef MessageQ_MsgHeader *MessageQ_Msg;
484 /*!
485  *  @brief      Message priority
486  */
487 typedef enum {
488     MessageQ_NORMALPRI      = 0,    /*!< Normal Priority                  */
489     MessageQ_HIGHPRI        = 1,    /*!< High Priority                    */
490     MessageQ_RESERVEDPRI    = 2,    /*!< Reserved Priority                */
491     MessageQ_URGENTPRI      = 3     /*!< Urgent Priority                  */
492 } MessageQ_Priority;
494 /*!
495  *  @brief      Denotes any queueId is acceptable.
496  *
497  *  This constant is the default for the queueId in the MessageQ_Params2
498  *  structure.
499  */
500 #define MessageQ_ANY (Bits16)~(0)
502 /*!
503  *  @brief      Free hook prototype
504  *
505  *  @param[in]  heapId      heapId of message that was freed
506  *  @param[in]  msgId       msgId of message that was freed
507  */
508 typedef Void (*MessageQ_FreeHookFxn)(Bits16 heapId, Bits16 msgId);
510 /* =============================================================================
511  *  MessageQ Module-wide Functions
512  * =============================================================================
513  */
515 /*!
516  *  @brief      Initialize MessageQ_Params
517  *
518  *  @param[in]  params      Parameters required to create a MessageQ
519  */
520 Void MessageQ_Params_init(MessageQ_Params *params);
522 /*!
523  *  @brief      Initialize MessageQ_Params2
524  *
525  *  @param[in]  params      Parameters required to create a MessageQ
526  */
527 Void MessageQ_Params2_init(MessageQ_Params2 *params);
529 /*!
530  *  @brief      Create a MessageQ instance
531  *
532  *  The name supplied here does not have to be in persistent memory.  The
533  *  maximum length of the string supplied here, including the '\\0' terminator,
534  *  is '32' by default.
535  *
536  *  There are no verifications to ensure that the name supplied in
537  *  MessageQ_create() is unique across all processors. Caution must be exercised
538  *  to ensure that each processor uses a unique name.
539  *
540  *  @param[in]  name        Name of the queue
541  *  @param[in]  params      Initialized MessageQ parameters
542  *
543  *  @return     MessageQ Handle
544  */
545 MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params);
547 /*!
548  *  @brief      Create a MessageQ instance with the MessageQ_Params2 structure
549  *
550  *  The name supplied here does not have to be in persistent memory.  The
551  *  maximum length of the string supplied here, including the '\\0' terminator,
552  *  is '32' by default.
553  *
554  *  There are no verifications to ensure that the name supplied in
555  *  MessageQ_create2() is unique across all processors. Caution must be exercised
556  *  to ensure that each processor uses a unique name.
557  *
558  *  @param[in]  name        Name of the queue
559  *  @param[in]  params      Initialized MessageQ_Params2
560  *
561  *  @return     MessageQ Handle
562  */
563 MessageQ_Handle MessageQ_create2(String name, const MessageQ_Params2 *params);
565 /*!
566  *  @brief      Delete a created MessageQ instance
567  *
568  *  This function deletes a created message queue instance. If the
569  *  message queue is non-empty, any messages remaining in the queue
570  *  will not be freed and will be lost.
571  *
572  *  @param[in,out]  handlePtr   Pointer to handle to delete.
573  *
574  *  @return     MessageQ status:
575  *              - #MessageQ_E_FAIL: delete failed
576  *              - #MessageQ_S_SUCCESS: delete successful
577  */
578 Int MessageQ_delete(MessageQ_Handle *handlePtr);
580 /*!
581  *  @brief      Open a message queue
582  *
583  *  MessageQ_open() is used to retrieve the queue id for a queue that has been
584  *  created either locally or remotely.  Note that the queueId is simply a
585  *  32 bit value that uniquely identifies a queue.  Therefore, it is also
586  *  possible to put a message on a queue whose queueId has been retrieved using
587  *  any other method.
588  *
589  *  @param[in]  name        Name of queue to open
590  *  @param[out] queueId     QueueId that can be used in MessageQ_put()
591  *
592  *  @return     MessageQ status:
593  *              - #MessageQ_E_NOTFOUND: open failed (name not found on any
594  *                processor)
595  *              - #MessageQ_S_SUCCESS: open successful
596  */
597 Int MessageQ_open(String name, MessageQ_QueueId *queueId);
599 /*!
600  *  @brief      Opens a MessageQ given the queue index and remote processor id
601  *
602  *  This function can be used instead of MessageQ_open() if the queue was created
603  *  with a specified QueueIndex.
604  *
605  *      @code
606  *      #define SERVERQUEUEINDEX  1
607  *      #define SERVERMULTIPROCID 2
608  *
609  *      serverFxn() {
610  *          MessageQ_Params2 params2;
611  *
612  *          MessageQ_Params2_init(&params2);
613  *          params2.queueIndex = SERVERQUEUEINDEX;
614  *          messageQ = MessageQ_create2("server", &params2);
615  *          ...
616  *
617  *      clientFxn() {
618  *          MessageQ_QueueId serverQueue;
619  *          serverQueue = MessageQ_openQueueId(SERVERQUEUEINDEX, SERVERMULTIPROCID);
620  *      @endcode
621  *
622  *  It is up to the application to guarantee that the queue that is being opened
623  *  has already been created.  MessageQ_openQueueId() does not validate that
624  *  the queue has been created (unlike the MessageQ_open() function).
625  *
626  *  @param[in] queueIndex   QueueIndex specified in MessageQ_Params2
627  *  @param[in] remoteProcId Multiproc_Id of where the created queue resides
628  *
629  *  @return     The MessageQ_QueueId associated with the queueIndex
630  *              and remoteProcId
631  */
632 MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 remoteProcId);
634 /*!
635  *  @brief      Close the opened handle
636  *
637  *  Only close a queueId that was returned from MessageQ_open().
638  *
639  *  @param[in]  queueId     Pointer to queueId to close
640  *
641  *  @return     MessageQ status:
642  *              - #MessageQ_E_FAIL: close failed
643  *              - #MessageQ_S_SUCCESS: close successful
644  */
645 Int MessageQ_close(MessageQ_QueueId *queueId);
647 /*!
648  *  @brief      Allocates a message from the heap
649  *
650  *  This function allocates a message from the heap associated with the heapId.
651  *  The first field of the message must be a #MessageQ_MsgHeader structure.
652  *  For example:
653  *      @code
654  *      typedef struct MyMsg {
655  *         MessageQ_MsgHeader header;
656  *         ...
657  *      } MyMsg;
658  *      @endcode
659  *
660  *  @param[in]  heapId      heapId
661  *  @param[in]  size        size of requested message (including the
662  *                          #MessageQ_MsgHeader).
663  *
664  *  @pre        @c size must be at least large enough to hold a
665  *              MessageQ_MsgHeader
666  *
667  *  @return    Allocated message or NULL if no memory.
668  */
669 MessageQ_Msg MessageQ_alloc(UInt16 heapId, UInt32 size);
671 /*!
672  *  @brief      Frees a message back to the heap
673  *
674  *  Frees the message back to the heap that was used to allocate it.
675  *
676  *  @param[in]  msg         Message to free.
677  *
678  *  @return     MessageQ status:
679  *              - #MessageQ_E_FAIL: failed to free message
680  *              - #MessageQ_S_SUCCESS: successfully freed the message
681  */
682 Int MessageQ_free(MessageQ_Msg msg);
684 /*!
685  *  @brief      Register a heap with MessageQ
686  *
687  *  This function registers a heap with MessageQ. The user selects a unique
688  *  heapId associated with this heap. When a message is allocated via
689  *  MessageQ_alloc(), the heapId is specified. Internally, MessageQ
690  *  uses the heapId to access the heap.
691  *
692  *  Care must be taken when assigning heapIds. Internally MessageQ stores
693  *  the heapId into the message. When the message is freed
694  *  (via MessageQ_free()), the heapId is used to determine which heap to use.
695  *  On systems with shared memory the heapIds must match on corresponding
696  *  processors. For example, assume there is a heap called myHeap which
697  *  acts on shared memory and processors 0 and 1 both use this heap.
698  *  When you register the heap with MessageQ, the same heapId must be used
699  *  on both processor 0 and 1.
700  *
701  *  If a heap is already registered for the specified heapId, no action is
702  *  taken and #MessageQ_E_ALREADYEXISTS is returned.
703  *
704  *  @param[in]  heap        Heap to register
705  *  @param[in]  heapId      heapId associated with the heap
706  *
707  *  @return     MessageQ status:
708  *              - #MessageQ_S_SUCCESS: heap successfully registered
709  *              - #MessageQ_E_ALREADYEXISTS: heap already exists with heapId
710  */
711 Int MessageQ_registerHeap(Ptr heap, UInt16 heapId);
713 /*!
714  *  @brief      Unregister a heap with MessageQ
715  *
716  *  This function unregisters the heap associated with the heapId.
717  *  Care must be taken to ensure that there are no outstanding messages
718  *  allocated from this heap. If there are outstanding messages, an attempt
719  *  to free the message will result in non-deterministic results.
720  *
721  *  @param[in]  heapId      Heap to unregister
722  *
723  *  @return     MessageQ status:
724  *              - #MessageQ_S_SUCCESS: heap successfully unregistered
725  */
726 Int MessageQ_unregisterHeap(UInt16 heapId);
728 /*!
729  *  @brief      Sets the message tracing flag on a given message
730  *
731  *  This function enables message tracing for a message.  Tracing is offered
732  *  in the form of Log messages that are output during operations on the
733  *  message (i.e. MessageQ_free(), MessageQ_put(), etc).
734  *
735  *  @param      msg         Message
736  *  @param      traceFlag   Message trace flag (TRUE = tracing enabled)
737  */
738 Void MessageQ_setMsgTrace(MessageQ_Msg msg, Bool traceFlag);
740 /*!
741  *  @brief      Initializes a message not obtained from MessageQ_alloc()
742  *
743  *  There are several fields in the #MessageQ_MsgHeader that
744  *  are initialized by the MessageQ_alloc() function. MessageQ_staticMsgInit()
745  *  can be used to initialize these fields for messages that are
746  *  not allocated from MessageQ.
747  *
748  *  There is one strict constraint with using messages not allocated
749  *  from MessageQ. The message cannot be freed via MessageQ_free().
750  *  This includes
751  *      - The application calling MessageQ_free() on the same processor
752  *      - The application calling MessageQ_free() on a different processor
753  *      - The application cannot send the message to another processor
754  *        where the transport might call MessageQ_free() on the message.
755  *        For example, copy based transport call MessageQ_free() after sending
756  *        the message.
757  *  If a staticMsgInit'd msg is passed to MessageQ_free() an assert will occur
758  *
759  *  @param      msg     Message to initialize
760  *  @param[in]  size    Size of the message in MAUs
761  *
762  *  @pre    @c size must be at least large enough to hold a #MessageQ_MsgHeader
763  */
764 Void MessageQ_staticMsgInit(MessageQ_Msg msg, UInt32 size);
766 /*!
767  *  @brief      Sets MessageQ's free hook function.
768  *
769  *  This API allows a user to specify a hook function which is called within
770  *  MessageQ_free(). The hook is called after a message is freed back to the
771  *  associated heap. The two parameters to the hook function are the heapId
772  *  and the msgId of the freed message.
773  *
774  *  The function is called within MessageQ_free(), so care must be taken to
775  *  minimize any performance or calling context impact.
776  *
777  *  MessageQ_setFreeHookFxn() is not thread safe. It should only
778  *  be called when no MessageQ_free()'s are happening.
779  *
780  *  To disable the hook function, call MessageQ_setFreeHookFxn() with NULL.
781  *
782  *  @param[in]  freeHookFxn  function to be called within MessageQ_free()
783  */
784 Void MessageQ_setFreeHookFxn(MessageQ_FreeHookFxn freeHookFxn);
786 /* =============================================================================
787  *  MessageQ Per-instance Functions
788  * =============================================================================
789  */
791 /*!
792  *  @brief      Gets a message from the message queue
793  *
794  *  This function returns a status. It also returns a message in msg.
795  *  If no message is available, it blocks on the synchronizer object
796  *  until the synchronizer is signaled or a timeout occurs.
797  *  The synchronizer is signaled, when Message_put is called on the MessageQ
798  *  handle. If a timeout occurs, the msg is set to NULL and the status is
799  *  #MessageQ_E_TIMEOUT. If a timeout of zero is specified, the function
800  *  returns immediately and if no message is available, the msg
801  *  is set to NULL and the status is #MessageQ_E_TIMEOUT. The
802  *  #MessageQ_E_UNBLOCKED status is return, if MessageQ_unblock is called
803  *  on the MessageQ handle. If a message is successfully retrieved, the msg
804  *  is set to the message and a #MessageQ_S_SUCCESS status is returned.
805  *
806  *  @param[in]  handle      MessageQ handle
807  *  @param[out] msg         Pointer to the message
808  *  @param[in]  timeout     Maximum duration to wait for a message in
809  *                          microseconds.
810  *
811  *  @return     MessageQ status:
812  *              - #MessageQ_S_SUCCESS: Message successfully returned
813  *              - #MessageQ_E_TIMEOUT: MessageQ_get() timed out
814  *              - #MessageQ_E_UNBLOCKED: MessageQ_get() was unblocked
815  *              - #MessageQ_E_FAIL:    A general failure has occurred
816  *
817  *  @sa         MessageQ_put()
818  *  @sa         MessageQ_unblock()
819  */
820 Int MessageQ_get(MessageQ_Handle handle, MessageQ_Msg *msg, UInt timeout);
822 /*!
823  *  @brief      Place a message onto a message queue
824  *
825  *  This call places the message onto the specified message queue. The
826  *  message queue could be local or remote. The MessageQ module manages
827  *  the delivery.
828  *
829  *  In the case where the queue is remote, MessageQ does not guarantee that
830  *  the message is actually delivered before the MessageQ_put() call returns
831  *
832  *  The queue id must have been returned from one of the following functions:
833  *  - MessageQ_open()
834  *  - MessageQ_getReplyQueue()
835  *  - MessageQ_getDstQueue()
836  *
837  *  After the message is placed onto the final destination, the queue's
838  *  #MessageQ_Params.synchronizer signal function is called.
839  *
840  *  The application loses ownership of the message once MessageQ_put() is called.
841  *
842  *  @param[in]  queueId     Destination MessageQ
843  *  @param[in]  msg         Message to be sent.
844  *
845  *  @return     Status of the call.
846  *              - #MessageQ_S_SUCCESS denotes success.
847  *              - #MessageQ_E_FAIL denotes failure. The put was not successful.
848  *                 The caller still owns the message.
849  */
850 Int MessageQ_put(MessageQ_QueueId queueId, MessageQ_Msg msg);
852 /*!
853  *  @brief      Returns the number of messages in a message queue
854  *
855  *  This function returns the number of messages in a message queue.
856  *
857  *  @param[in]  handle      MessageQ handle
858  *
859  *  @return     Number of messages in the message queue.
860  */
861 Int MessageQ_count(MessageQ_Handle handle);
863 /*!
864  *  @brief      Returns the QueueId associated with the handle
865  *
866  *  Since the MessageQ_put() function takes a QueueId, the creator
867  *  of a message queue cannot send a message to itself without
868  *  retrieving the QueueId. This function extracts the QueueId
869  *  from the object.
870  *
871  *  @param[in]  handle      MessageQ handle
872  *
873  *  @return     QueueId associated to the object
874  */
875 UInt32 MessageQ_getQueueId(MessageQ_Handle handle);
877 /*!
878  *  @brief      Embeds a source message queue into a message
879  *
880  *  This function along with MessageQ_getReplyQueue()
881  *  can be used instead of MessageQ_open(). The sender
882  *  of a message can embed a messageQ into the message with this
883  *  function. The receiver of the message can extract the message queue
884  *  id with the MessageQ_getReplyQueue() function.
885  *
886  *  This method is particularly useful in a client/server relationship
887  *  where the server does not want to know who the clients are. The
888  *  clients can embed their message queue into the message to the server
889  *  and the server extracts it and uses it to reply.
890  *
891  *  @param      handle      MessageQ handle
892  *  @param      msg         Message to embed queue into
893  */
894 Void MessageQ_setReplyQueue(MessageQ_Handle handle, MessageQ_Msg msg);
896 /*!
897  *  @brief      Unblocks a MessageQ
898  *
899  *  Unblocks a reader thread that is blocked on a MessageQ_get().  The
900  *  MessageQ_get() call will return with status #MessageQ_E_UNBLOCKED indicating
901  *  that it returned due to a MessageQ_unblock() rather than a timeout or a
902  *  received message.  This call should only be used during a shutdown sequence
903  *  in order to ensure that there is no blocked reader on a queue before
904  *  deleting the queue.  A queue may not be used after it has been unblocked.
905  *
906  *  MessageQ_unblock() works by raising a flag in the queue indicating that it
907  *  is unblocked and then signaling the synchronizer that is configured with
908  *  the target queue.  If MessageQ_unblock() is called upon a queue that has
909  *  no blocked listeners, then any subsequent MessageQ_get will not block and
910  *  will immediately return #MessageQ_E_UNBLOCKED regardless of whether there
911  *  is a message on the queue.
912  *
913  *  Restrictions:
914  *  -  A queue may not be used after it has been unblocked.
915  *  -  MessageQ_unblock() may only be called on a local queue.
916  *  -  May only be used with a queue configured with a blocking synchronizer.
917  *
918  *  @param[in]  handle      MessageQ handle
919  *
920  *  @sa         MessageQ_get
921  */
922 Void MessageQ_unblock(MessageQ_Handle handle);
924 #if defined (__cplusplus)
926 #endif /* defined (__cplusplus) */
927 #endif /* ti_ipc_MessageQ__include */