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