1 /*
2 * Copyright (c) 2012-2015 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 * @brief MessageQ was shutdown
259 */
260 #define MessageQ_E_SHUTDOWN (-20)
262 /* =============================================================================
263 * Macros
264 * =============================================================================
265 */
267 /*!
268 * @brief Used as the timeout value to specify wait forever
269 */
270 #define MessageQ_FOREVER (~(0))
272 /*!
273 * @brief Invalid message id
274 */
275 #define MessageQ_INVALIDMSGID (0xffff)
277 /*!
278 * @brief Invalid message queue
279 */
280 #define MessageQ_INVALIDMESSAGEQ (0xffff)
282 /*!
283 * @brief Mask to extract priority setting
284 */
285 #define MessageQ_PRIORITYMASK (0x3)
287 /** @cond INTERNAL */
288 /*!
289 * @brief Offset to avoid collision with reserved ports
290 *
291 * A queue's port number is computed by adding this offset to the
292 * queue index. Use the port number to address the message or when
293 * binding a socket. Computing a port number with this offset avoids
294 * collisions with reserved port numbers which are typically in the
295 * same range as the queue indexes.
296 */
297 #define MessageQ_PORTOFFSET (0x80)
298 /** @endcond INTERNAL */
300 /*!
301 * @brief Extract the destination queue ID from a message.
302 *
303 * This function is typically used be a transport.
304 *
305 * The destination address is written into the message header when
306 * calling MessageQ_put(). Therefore, you can only use this function
307 * to extract the destination queue ID after MessageQ_put() has been
308 * called on the given message. However, ownership rules dictate that
309 * you cannot dereference a message after calling MessageQ_put() (because
310 * you have transfered ownership to the transport).
311 *
312 * After receiving a message by calling MessageQ_get(), you may safely
313 * use this function. Although there is little benefit from doing so.
314 *
315 * When the message is given to the transport, the destination address
316 * has been written into the message header. In addition, the transport
317 * now has ownership of the message. So, it is appropriate for the transport
318 * to use this macro.
319 *
320 * @param[in] msg Message of type #MessageQ_Msg
321 *
322 * @retval queueId Destination message queue ID of type #MessageQ_QueueId
323 */
324 #define MessageQ_getDstQueue(msg) \
325 (((MessageQ_Msg)(msg))->dstId == \
326 (MessageQ_QueueIndex)MessageQ_INVALIDMESSAGEQ) ? \
327 (MessageQ_QueueId)MessageQ_INVALIDMESSAGEQ : \
328 (((MessageQ_QueueId)((MessageQ_Msg)(msg))->dstProc << 16u) \
329 | (((MessageQ_Msg)(msg))->dstId))
332 /*!
333 * @brief Retrieves the message ID of a message.
334 *
335 * This function retrieves the message ID from the message. The
336 * MessageQ_setMsgId() function is used to insert the message ID.
337 *
338 * The message id is part of the #MessageQ_MsgHeader header and is in every
339 * MessageQ message. All message ids are initialized to #MessageQ_INVALIDMSGID
340 * in the MessageQ_alloc() and MessageQ_staticMsgInit() calls.
341 *
342 * @param[in] msg Message of type #MessageQ_Msg
343 *
344 * @retval msgId 16-bit message ID from the message
345 */
346 #define MessageQ_getMsgId(msg) (((MessageQ_Msg) (msg))->msgId)
348 /*!
349 * @brief Returns the size of the specified message. This function is helpful
350 * when re-using a message.
351 *
352 * @param[in] msg Message of type #MessageQ_Msg
353 *
354 * @retval size Size of the message
355 */
356 #define MessageQ_getMsgSize(msg) (((MessageQ_Msg) (msg))->msgSize)
358 /*!
359 * @brief Gets the message priority of a message
360 *
361 * @param[in] msg Message of type #MessageQ_Msg
362 *
363 * @retval priority Priority of the message
364 */
365 #define MessageQ_getMsgPri(msg) \
366 ((((MessageQ_Msg) (msg))->flags & MessageQ_PRIORITYMASK))
368 /*!
369 * @brief Returns the MultiProc processor id on which the queue resides
370 *
371 * Message queues reside on the processor that created them. This function
372 * allows the caller to determined on which processor the queue resides.
373 *
374 * @param[in] queueId Unique #MessageQ_QueueId that identifies the queue
375 *
376 * @retval procId The MultiProc id on which the queue resides
377 */
378 #define MessageQ_getProcId(queueId) \
379 ((UInt16)((queueId) >> 16))
381 /*!
382 * @brief Extract the queue index from the given queue ID
383 *
384 * When creating and opening queues, the queue index is embedded
385 * into the queue ID using an implementation dependent format. This
386 * function extracts the queue index from the queue ID.
387 *
388 * For example, in the MessageQ_put() hook function, you might extract
389 * the queue index in order to set the transport ID.
390 *
391 * @code
392 * Void msgqPutHook(MessageQ_QueueId queueId, MessageQ_Msg msg)
393 * {
394 * MessageQ_QueueIndex queueIndex;
395 * UInt tid;
396 *
397 * queueIndex = MessageQ_getQueueIndex(queueId);
398 * ...
399 * MessageQ_setTransportId(msg, tid);
400 * }
401 * @endcode
402 *
403 * This function performs no error checking. Using an invalid queue ID
404 * will result in undefined behavior.
405 *
406 * @param[in] queueId Message queue ID of type #MessageQ_QueueId
407 *
408 * @retval queueIndex The queue index of type #MessageQ_QueueIndex
409 */
410 #define MessageQ_getQueueIndex(queueId) \
411 (((MessageQ_QueueIndex)((MessageQ_QueueId)0xFFFF & (queueId))) \
412 - MessageQ_PORTOFFSET)
414 /*!
415 * @brief Retrieves the message queue ID from a message.
416 *
417 * This function along with the MessageQ_setReplyQueue() function can be used
418 * instead of the open function. The sender of a message can embed a messageQ
419 * into the message with the MessageQ_setReplyQueue() function. The receiver of
420 * the message can extract the message queue ID with this function.
421 *
422 * This method is particularly useful in a client/server relationship where
423 * the server does not want to know who the clients are. The clients can embed
424 * their message queue into the message to the server and the server extracts
425 * it and uses it to reply.
426 *
427 * @param[in] msg Message of type #MessageQ_Msg
428 *
429 * @retval queueId Message queue ID of type #MessageQ_QueueId
430 */
431 #define MessageQ_getReplyQueue(msg) \
432 (MessageQ_QueueId)((((MessageQ_Msg) (msg))->replyProc << 16u) \
433 | ((MessageQ_Msg)(msg))->replyId)
435 /*!
436 * @brief Return the transport Id for the given message
437 *
438 * Extract the transport Id from the message header.
439 *
440 * @param[in] msg message of type #MessageQ_Msg
441 * @retval tid transport Id
442 */
443 #define MessageQ_getTransportId(msg) \
444 ((((MessageQ_Msg)(msg))->flags & (0x7 << 2)) >> 2)
446 /*!
447 * @brief Sets the message id in a message.
448 *
449 * This function sets the message ID in the message. The MessageQ_getMsgId()
450 * function is used to retrieve the message ID. The message id is part of the
451 * #MessageQ_MsgHeader header and is in every MessageQ message. All message ids
452 * are initialized to #MessageQ_INVALIDMSGID in the MessageQ_alloc() and
453 * MessageQ_staticMsgInit() calls.
454 *
455 * @param[in] msg Message of type #MessageQ_Msg
456 * @param[in] id 16-bit value
457 */
458 #define MessageQ_setMsgId(msg, id) ((MessageQ_Msg) (msg))->msgId = (id)
460 /*!
461 * @brief Sets the message priority of a message
462 *
463 * @param[in] msg Message of type #MessageQ_Msg
464 * @param[in] priority Priority of message to be set.
465 */
466 #define MessageQ_setMsgPri(msg, priority) \
467 ((MessageQ_Msg)(msg))->flags = \
468 (((MessageQ_Msg)(msg))->flags & ~(MessageQ_PRIORITYMASK)) \
469 | ((priority) & MessageQ_PRIORITYMASK)
471 /*!
472 * @brief Set the transport Id for the given message
473 *
474 * Set the transport Id in the flags field of the message header. When
475 * set to a non-zero value, the message will be given to the specified
476 * transport for delivery. The transport must be registered with MessageQ
477 * with the given Id.
478 *
479 * There is no error checking on the transport Id.
480 *
481 * @param[in] msg message of type #MessageQ_Msg
482 * @param[in] tid transport ID (1-7)
483 */
484 #define MessageQ_setTransportId(msg, tid) \
485 ((MessageQ_Msg)(msg))->flags = \
486 ((((MessageQ_Msg)(msg))->flags & ~(0x7 << 2)) | ((tid) << 2))
488 /* =============================================================================
489 * Structures & Enums
490 * =============================================================================
491 */
493 /*!
494 * @brief A 32-bit value that uniquely identifies a message queue
495 */
496 typedef UInt32 MessageQ_QueueId;
498 /*!
499 * @brief Local queue index
500 */
501 typedef UInt16 MessageQ_QueueIndex;
503 /*!
504 * @brief MessageQ_Handle type
505 */
506 typedef struct MessageQ_Object *MessageQ_Handle;
508 /*!
509 * @brief Structure defining parameters for MessageQ_create().
510 */
511 typedef struct {
512 /** @cond INTERNAL */
513 Int __version;
514 /* Used internally for tracking implementation evolution.
515 * For internal use only.
516 */
517 /** @endcond INTERNAL */
519 Void *synchronizer;
520 /*!< Synchronizer instance used to signal IO completion
521 *
522 * The synchronizer is used in MessageQ_put() and MessageQ_get().
523 * The synchronizer signal is called as part of MessageQ_put().
524 * The synchronizer waits in MessageQ_get() if there are no messages
525 * present.
526 */
528 MessageQ_QueueIndex queueIndex;
529 /*!< Value used to specify the index in the MessageQ array
530 *
531 * This parameter allows an application to specify a queueIndex to
532 * be used for a message queue. To use this functionality, the
533 * MessageQ.numReservedEntries static configuration parameter must be
534 * set to one more than the highest requested queueIndex. The
535 * MessageQ.numReservedEntries parameter reserves that number of
536 * message queue slots starting at 0 and proceeding to
537 * (MessageQ.numReservedEntries - 1).
538 *
539 * The default is MessageQ_ANY, which means it is not taken from the
540 * reserved slots.
541 */
543 } MessageQ_Params;
545 /** @cond INTERNAL */
546 /* Date: 02 Dec 2014
547 *
548 * Initial implementation of params structure which contains
549 * a version field. This allows for binary compatibility as
550 * the params structure is modified in the future.
551 */
552 #define MessageQ_Params_VERSION_2 2
553 /** @endcond INTERNAL */
555 /** @cond INTERNAL */
556 /*!
557 * @brief Defines the current params structure version
558 */
559 #define MessageQ_Params_VERSION MessageQ_Params_VERSION_2
560 /** @endcond INTERNAL */
562 /*!
563 * @brief Structure defining parameters for MessageQ_create2().
564 *
565 * MessageQ_Params2 is a superset of MessageQ_Params. It is used
566 * with MessageQ_create2().
567 *
568 * @deprecated This type has been deprecated. It will be removed
569 * in a future release. Please use MessageQ_Params instead.
570 */
571 typedef struct {
572 Void *synchronizer;
573 /*!< Synchronizer instance used to signal IO completion
574 *
575 * The synchronizer is used in MessageQ_put() and MessageQ_get().
576 * The synchronizer signal is called as part of MessageQ_put().
577 * The synchronizer waits in MessageQ_get() if there are no messages
578 * present.
579 */
581 MessageQ_QueueIndex queueIndex;
582 /*!< Value used to specify the index in the MessageQ array
583 *
584 * This parameter allows an application to specify a queueIndex to
585 * be used for a message queue. To use this functionality, the
586 * MessageQ.numReservedEntries static configuration parameter must be
587 * set to one more than the highest requested queueIndex. The
588 * MessageQ.numReservedEntries parameter reserves that number of
589 * message queue slots starting at 0 and proceeding to
590 * (MessageQ.numReservedEntries - 1).
591 *
592 * The default is MessageQ_ANY, which means it is not taken from the
593 * reserved slots.
594 */
596 } MessageQ_Params2;
598 /*!
599 * @brief Required first field in every message
600 */
601 typedef struct {
602 Bits32 reserved0; /*!< reserved for List.elem->next */
603 Bits32 reserved1; /*!< reserved for List.elem->prev */
604 Bits32 msgSize; /*!< message size */
605 Bits16 flags; /*!< bitmask of different flags */
606 Bits16 msgId; /*!< message id */
607 Bits16 dstId; /*!< destination queue id */
608 Bits16 dstProc; /*!< destination processor id */
609 Bits16 replyId; /*!< reply id */
610 Bits16 replyProc; /*!< reply processor */
611 Bits16 srcProc; /*!< source processor */
612 Bits16 heapId; /*!< heap id */
613 Bits16 seqNum; /*!< sequence number */
614 Bits16 reserved; /*!< reserved */
615 } MessageQ_MsgHeader;
617 /*!
618 * @brief Typedef for ease of use
619 */
620 typedef MessageQ_MsgHeader *MessageQ_Msg;
622 /*!
623 * @brief Message priority
624 */
625 typedef enum {
626 MessageQ_NORMALPRI = 0, /*!< Normal Priority */
627 MessageQ_HIGHPRI = 1, /*!< High Priority */
628 MessageQ_RESERVEDPRI = 2, /*!< Reserved Priority */
629 MessageQ_URGENTPRI = 3 /*!< Urgent Priority */
630 } MessageQ_Priority;
632 /*!
633 * @brief Denotes any queueId is acceptable.
634 *
635 * This constant is the default for the queueId in the MessageQ_Params
636 * structure.
637 */
638 #define MessageQ_ANY (Bits16)~(0)
640 /*!
641 * @brief Free hook prototype
642 *
643 * @param[in] heapId heapId of message that was freed
644 * @param[in] msgId msgId of message that was freed
645 */
646 typedef Void (*MessageQ_FreeHookFxn)(Bits16 heapId, Bits16 msgId);
648 /*!
649 * @brief Put hook function definition
650 *
651 * This function is invoked near the beginning of the MessageQ_put()
652 * function. It allows client code to augment the addressing of the
653 * given message before it is delivered.
654 *
655 * @param[in] queueId destination message queue
656 * @param[in] msg message to be sent
657 */
658 typedef Void (*MessageQ_PutHookFxn)(MessageQ_QueueId queueId, MessageQ_Msg msg);
660 #ifdef STD_H
661 #include <ti/ipc/interfaces/ITransport.h>
662 #include <ti/ipc/interfaces/IMessageQTransport.h>
663 #else
664 #include <ti/sdo/ipc/interfaces/ITransport.h>
665 #include <ti/sdo/ipc/interfaces/IMessageQTransport.h>
666 #endif
668 Bool MessageQ_registerTransport(IMessageQTransport_Handle handle,
669 UInt16 rprocId, UInt priority);
670 Void MessageQ_unregisterTransport(UInt16 rprocId, UInt priority);
673 /* =============================================================================
674 * MessageQ Module-wide Functions
675 * =============================================================================
676 */
678 /** @cond INTERNAL */
679 /* Returns the local handle associated with queueId. */
680 MessageQ_Handle MessageQ_getLocalHandle(MessageQ_QueueId queueId);
681 /** @endcond INTERNAL */
684 /** @cond INTERNAL */
685 Void MessageQ_Params_init__S(MessageQ_Params *params, Int version);
686 /** @endcond INTERNAL */
688 /*!
689 * @brief Initialize MessageQ_Params
690 *
691 * Initialized the given structure to its default values.
692 *
693 * @param[in] params Parameters required to create a MessageQ
694 */
695 #ifndef MessageQ_internal
696 static inline Void MessageQ_Params_init(MessageQ_Params *params)
697 {
698 if (params != NULL) {
699 MessageQ_Params_init__S(params, MessageQ_Params_VERSION);
700 }
701 }
702 #endif
704 /*!
705 * @brief Initialize MessageQ_Params2
706 *
707 * Initialized the given structure to its default values.
708 *
709 * @deprecated This function has been deprecated. It will be removed
710 * in a future release. Please use MessageQ_Params_init() instead.
711 *
712 * @param[in] params Parameters required to create a MessageQ
713 */
714 Void MessageQ_Params2_init(MessageQ_Params2 *params);
716 /*!
717 * @brief Create a MessageQ instance
718 *
719 * The name supplied here does not have to be in persistent memory. The
720 * maximum length of the string supplied here, including the '\\0' terminator,
721 * is '32' by default.
722 *
723 * There are no verifications to ensure that the name supplied in
724 * MessageQ_create() is unique across all processors. Caution must be exercised
725 * to ensure that each processor uses a unique name.
726 *
727 * @param[in] name Name of the queue
728 * @param[in] params Initialized MessageQ parameters
729 *
730 * @return MessageQ Handle
731 */
732 MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params);
734 /*!
735 * @brief Announce a previously created MessageQ to NameServer
736 * (Linux/Android only)
737 *
738 * The name supplied here does not have to be in persistent memory. The
739 * maximum length of the string supplied here, including the '\\0' terminator,
740 * is '32' by default.
741 *
742 * There are no verifications to ensure that the name supplied in
743 * MessageQ_announce() is unique across all processors. Caution must be
744 * exercised to ensure that each processor uses a unique name.
745 *
746 * @param[in] name Name of the queue
747 * @param[in] handlePtr Pointer to handle returned from MessageQ_create.
748 *
749 * @return MessageQ status:
750 * - #MessageQ_E_FAIL: announce failed
751 * - #MessageQ_S_SUCCESS: announce successful
752 */
753 Int MessageQ_announce(String name, MessageQ_Handle * handlePtr);
755 /*!
756 * @brief Create a MessageQ instance using the type MessageQ_Params2
757 *
758 * The name supplied here does not have to be in persistent memory. The
759 * maximum length of the string supplied here, including the '\\0' terminator,
760 * is '32' by default.
761 *
762 * There are no verifications to ensure that the name supplied in
763 * MessageQ_create2() is unique across all processors. Caution must
764 * be exercised to ensure that each processor uses a unique name.
765 *
766 * @deprecated This function has been deprecated. It will be removed
767 * in a future release. Please use MessageQ_create() instead.
768 *
769 * @param[in] name Name of the queue
770 * @param[in] params Initialized MessageQ_Params2
771 *
772 * @return MessageQ Handle
773 */
774 MessageQ_Handle MessageQ_create2(String name, const MessageQ_Params2 *params);
776 /*!
777 * @brief Delete a created MessageQ instance
778 *
779 * This function deletes a created message queue instance. If the
780 * message queue is non-empty, any messages remaining in the queue
781 * will not be freed and will be lost.
782 *
783 * @param[in,out] handlePtr Pointer to handle to delete.
784 *
785 * @return MessageQ status:
786 * - #MessageQ_E_FAIL: delete failed
787 * - #MessageQ_S_SUCCESS: delete successful
788 */
789 Int MessageQ_delete(MessageQ_Handle *handlePtr);
791 /*!
792 * @brief Open a message queue
793 *
794 * MessageQ_open() is used to retrieve the queue id for a queue that has been
795 * created either locally or remotely. Note that the queueId is simply a
796 * 32 bit value that uniquely identifies a queue. Therefore, it is also
797 * possible to put a message on a queue whose queueId has been retrieved using
798 * any other method.
799 *
800 * @param[in] name Name of queue to open
801 * @param[out] queueId QueueId that can be used in MessageQ_put()
802 *
803 * @return MessageQ status:
804 * - #MessageQ_E_NOTFOUND: open failed (name not found on any
805 * processor)
806 * - #MessageQ_S_SUCCESS: open successful
807 */
808 Int MessageQ_open(String name, MessageQ_QueueId *queueId);
810 /*!
811 * @brief Open a MessageQ given the queue index and processor ID
812 *
813 * This function can be used instead of MessageQ_open() if the queue
814 * was created with a reserved queue index. In the example below, the
815 * serverFxn function must be running on the processor with PROCID 2.
816 *
817 * @code
818 * #define SERVER_QUEIDX 1
819 * #define SERVER_PROCID 2
820 *
821 * serverFxn()
822 * {
823 * MessageQ_Params params;
824 *
825 * MessageQ_Params_init(¶ms);
826 * params.queueIndex = SERVER_QUEIDX;
827 * messageQ = MessageQ_create(NULL, ¶ms);
828 * ...
829 * }
830 *
831 * clientFxn()
832 * {
833 * MessageQ_QueueId serverQueue;
834 * serverQueue = MessageQ_openQueueId(SERVER_QUEIDX, SERVER_PROCID);
835 * }
836 * @endcode
837 *
838 * It is up to the application to guarantee that the queue which is being
839 * opened has already been created. MessageQ_openQueueId() does not validate
840 * that the queue has been created (unlike the MessageQ_open() function).
841 *
842 * @param[in] queueIndex QueueIndex specified in MessageQ_Params when
843 * the message queue was created.
844 * @param[in] procId Multiproc_Id of where the created queue resides.
845 *
846 * @return The MessageQ_QueueId associated with the queueIndex
847 * and remoteProcId
848 */
849 MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 procId);
851 /*!
852 * @brief Close the opened handle
853 *
854 * Only close a queueId that was returned from MessageQ_open().
855 *
856 * @param[in] queueId Pointer to queueId to close
857 *
858 * @return MessageQ status:
859 * - #MessageQ_E_FAIL: close failed
860 * - #MessageQ_S_SUCCESS: close successful
861 */
862 Int MessageQ_close(MessageQ_QueueId *queueId);
864 /*!
865 * @brief Allocates a message from the heap
866 *
867 * This function allocates a message from the heap associated with the heapId.
868 * The first field of the message must be a #MessageQ_MsgHeader structure.
869 * For example:
870 * @code
871 * typedef struct MyMsg {
872 * MessageQ_MsgHeader header;
873 * ...
874 * } MyMsg;
875 * @endcode
876 *
877 * @param[in] heapId heapId
878 * @param[in] size size of requested message (including the
879 * #MessageQ_MsgHeader).
880 *
881 * @pre @c size must be at least large enough to hold a
882 * MessageQ_MsgHeader
883 *
884 * @return Allocated message or NULL if no memory.
885 */
886 MessageQ_Msg MessageQ_alloc(UInt16 heapId, UInt32 size);
888 /*!
889 * @brief Frees a message back to the heap
890 *
891 * Frees the message back to the heap that was used to allocate it.
892 *
893 * @param[in] msg Message to free.
894 *
895 * @return MessageQ status:
896 * - #MessageQ_E_FAIL: failed to free message
897 * - #MessageQ_S_SUCCESS: successfully freed the message
898 */
899 Int MessageQ_free(MessageQ_Msg msg);
901 /*!
902 * @brief Register a heap with MessageQ
903 *
904 * This function registers a heap with MessageQ. The user selects a unique
905 * heapId associated with this heap. When a message is allocated via
906 * MessageQ_alloc(), the heapId is specified. Internally, MessageQ
907 * uses the heapId to access the heap.
908 *
909 * Care must be taken when assigning heapIds. Internally MessageQ stores
910 * the heapId into the message. When the message is freed
911 * (via MessageQ_free()), the heapId is used to determine which heap to use.
912 * On systems with shared memory the heapIds must match on corresponding
913 * processors. For example, assume there is a heap called myHeap which
914 * acts on shared memory and processors 0 and 1 both use this heap.
915 * When you register the heap with MessageQ, the same heapId must be used
916 * on both processor 0 and 1.
917 *
918 * If a heap is already registered for the specified heapId, no action is
919 * taken and #MessageQ_E_ALREADYEXISTS is returned.
920 *
921 * @param[in] heap Heap to register
922 * @param[in] heapId heapId associated with the heap
923 *
924 * @return MessageQ status:
925 * - #MessageQ_S_SUCCESS: heap successfully registered
926 * - #MessageQ_E_ALREADYEXISTS: heap already exists with heapId
927 */
928 Int MessageQ_registerHeap(Ptr heap, UInt16 heapId);
930 /*!
931 * @brief Register a transport instance for the given ID
932 *
933 * Additional transport instances can be registered with the MessageQ
934 * module. This allows for message delivery over selected transports.
935 *
936 * To arrange for a message to be delivered using a registered transport,
937 * the corresponding transport ID must be set in the message header by
938 * calling MessageQ_setTransportId().
939 *
940 * @param[in] tid Transport ID, must be 1-7 inclusive
941 * @param[in] inst Transport instance handle
942 *
943 * @return Status result
944 * - TRUE: transport handle successfully registered
945 * - FALSE: failure, most likely transport ID already in use
946 *
947 * @sa MessageQ_setTransportId()
948 * @sa MessageQ_unregisterTransportId()
949 */
950 Bool MessageQ_registerTransportId(UInt tid, ITransport_Handle inst);
952 /*!
953 * @brief Unregister a heap with MessageQ
954 *
955 * This function unregisters the heap associated with the heapId.
956 * Care must be taken to ensure that there are no outstanding messages
957 * allocated from this heap. If there are outstanding messages, an attempt
958 * to free the message will result in non-deterministic results.
959 *
960 * @param[in] heapId Heap to unregister
961 *
962 * @return MessageQ status:
963 * - #MessageQ_S_SUCCESS: heap successfully unregistered
964 */
965 Int MessageQ_unregisterHeap(UInt16 heapId);
967 /*!
968 * @brief Unregister the transport instance for the given ID
969 *
970 * Remove the registered transport instance for the give transport ID.
971 *
972 * @param[in] tid Transport ID, must be 1-7 inclusive
973 *
974 * @sa MessageQ_registerTransportId()
975 */
976 Void MessageQ_unregisterTransportId(UInt tid);
978 /*!
979 * @brief Sets the message tracing flag on a given message
980 *
981 * This function enables message tracing for a message. Tracing is offered
982 * in the form of Log messages that are output during operations on the
983 * message (i.e. MessageQ_free(), MessageQ_put(), etc).
984 *
985 * @param msg Message
986 * @param traceFlag Message trace flag (TRUE = tracing enabled)
987 */
988 Void MessageQ_setMsgTrace(MessageQ_Msg msg, Bool traceFlag);
990 /*!
991 * @brief Initializes a message not obtained from MessageQ_alloc()
992 *
993 * There are several fields in the #MessageQ_MsgHeader that
994 * are initialized by the MessageQ_alloc() function. MessageQ_staticMsgInit()
995 * can be used to initialize these fields for messages that are
996 * not allocated from MessageQ.
997 *
998 * There is one strict constraint with using messages not allocated
999 * from MessageQ. The message cannot be freed via MessageQ_free().
1000 * This includes
1001 * - The application calling MessageQ_free() on the same processor
1002 * - The application calling MessageQ_free() on a different processor
1003 * - The application cannot send the message to another processor
1004 * where the transport might call MessageQ_free() on the message.
1005 * For example, copy based transport call MessageQ_free() after sending
1006 * the message.
1007 * If a staticMsgInit'd msg is passed to MessageQ_free() an assert will occur
1008 *
1009 * @param msg Message to initialize
1010 * @param[in] size Size of the message in MAUs
1011 *
1012 * @pre @c size must be at least large enough to hold a #MessageQ_MsgHeader
1013 */
1014 Void MessageQ_staticMsgInit(MessageQ_Msg msg, UInt32 size);
1016 /*!
1017 * @brief Sets MessageQ's free hook function.
1018 *
1019 * This API allows a user to specify a hook function which is called within
1020 * MessageQ_free(). The hook is called after a message is freed back to the
1021 * associated heap. The two parameters to the hook function are the heapId
1022 * and the msgId of the freed message.
1023 *
1024 * The function is called within MessageQ_free(), so care must be taken to
1025 * minimize any performance or calling context impact.
1026 *
1027 * MessageQ_setFreeHookFxn() is not thread safe. It should only
1028 * be called when no MessageQ_free()'s are happening.
1029 *
1030 * To disable the hook function, call MessageQ_setFreeHookFxn() with NULL.
1031 *
1032 * @param[in] freeHookFxn function to be called within MessageQ_free()
1033 */
1034 Void MessageQ_setFreeHookFxn(MessageQ_FreeHookFxn freeHookFxn);
1036 /*!
1037 * @brief Set the function hook for the MessageQ_put() method
1038 *
1039 * Register a hook function which is called from the beginning of the
1040 * MessageQ_put() function. Only one hook may be registered at a time.
1041 * Subsequent calls to register a put function will overwrite the
1042 * previously registered function.
1043 *
1044 * To disable the hook function, call MessageQ_setPutHookFxn() with NULL.
1045 *
1046 * @param[in] putHookFxn function to be called within MessageQ_put()
1047 */
1048 Void MessageQ_setPutHookFxn(MessageQ_PutHookFxn putHookFxn);
1050 /* =============================================================================
1051 * MessageQ Per-instance Functions
1052 * =============================================================================
1053 */
1055 /*!
1056 * @brief Gets a message from the message queue
1057 *
1058 * This function returns a status. It also returns a message in msg.
1059 * If no message is available, it blocks on the synchronizer object
1060 * until the synchronizer is signaled or a timeout occurs.
1061 * The synchronizer is signaled, when Message_put is called on the MessageQ
1062 * handle. If a timeout occurs, the msg is set to NULL and the status is
1063 * #MessageQ_E_TIMEOUT. If a timeout of zero is specified, the function
1064 * returns immediately and if no message is available, the msg
1065 * is set to NULL and the status is #MessageQ_E_TIMEOUT. The
1066 * #MessageQ_E_UNBLOCKED status is return, if MessageQ_unblock is called
1067 * on the MessageQ handle. The #MessageQ_E_SHUTDOWN status is returned if
1068 * MessageQ_shutdown is called on the MessageQ handle. If a message is
1069 * successfully retrieved, the msg is set to the message and a
1070 * #MessageQ_S_SUCCESS status is returned.
1071 *
1072 * @param[in] handle MessageQ handle
1073 * @param[out] msg Pointer to the message
1074 * @param[in] timeout Maximum duration to wait for a message in
1075 * microseconds.
1076 *
1077 * @return MessageQ status:
1078 * - #MessageQ_S_SUCCESS: Message successfully returned
1079 * - #MessageQ_E_TIMEOUT: MessageQ_get() timed out
1080 * - #MessageQ_E_UNBLOCKED: MessageQ_get() was unblocked
1081 * - #MessageQ_E_FAIL: A general failure has occurred
1082 *
1083 * @sa MessageQ_put()
1084 * @sa MessageQ_unblock()
1085 * @sa MessageQ_shutdown()
1086 */
1087 Int MessageQ_get(MessageQ_Handle handle, MessageQ_Msg *msg, UInt timeout);
1089 /*!
1090 * @brief Place a message onto a message queue
1091 *
1092 * This call places the message onto the specified message queue. The
1093 * message queue could be local or remote. The MessageQ module manages
1094 * the delivery.
1095 *
1096 * In the case where the queue is remote, MessageQ does not guarantee that
1097 * the message is actually delivered before the MessageQ_put() call returns
1098 *
1099 * The queue id must have been returned from one of the following functions:
1100 * - MessageQ_open()
1101 * - MessageQ_getReplyQueue()
1102 * - MessageQ_getDstQueue()
1103 *
1104 * After the message is placed onto the final destination, the queue's
1105 * #MessageQ_Params.synchronizer signal function is called.
1106 *
1107 * The application loses ownership of the message once MessageQ_put() is called.
1108 *
1109 * @param[in] queueId Destination MessageQ
1110 * @param[in] msg Message to be sent.
1111 *
1112 * @return Status of the call.
1113 * - #MessageQ_S_SUCCESS denotes success.
1114 * - #MessageQ_E_FAIL denotes failure. The put was not successful.
1115 * The caller still owns the message.
1116 */
1117 Int MessageQ_put(MessageQ_QueueId queueId, MessageQ_Msg msg);
1119 /*!
1120 * @brief Returns the number of messages in a message queue
1121 *
1122 * This function returns the number of messages in a message queue.
1123 *
1124 * @param[in] handle MessageQ handle
1125 *
1126 * @return Number of messages in the message queue.
1127 */
1128 Int MessageQ_count(MessageQ_Handle handle);
1130 /*!
1131 * @brief Returns the QueueId associated with the handle
1132 *
1133 * Since the MessageQ_put() function takes a QueueId, the creator
1134 * of a message queue cannot send a message to itself without
1135 * retrieving the QueueId. This function extracts the QueueId
1136 * from the object.
1137 *
1138 * @param[in] handle MessageQ handle
1139 *
1140 * @return QueueId associated to the object
1141 */
1142 UInt32 MessageQ_getQueueId(MessageQ_Handle handle);
1144 /*!
1145 * @brief Embeds a source message queue into a message
1146 *
1147 * This function along with MessageQ_getReplyQueue()
1148 * can be used instead of MessageQ_open(). The sender
1149 * of a message can embed a messageQ into the message with this
1150 * function. The receiver of the message can extract the message queue
1151 * id with the MessageQ_getReplyQueue() function.
1152 *
1153 * This method is particularly useful in a client/server relationship
1154 * where the server does not want to know who the clients are. The
1155 * clients can embed their message queue into the message to the server
1156 * and the server extracts it and uses it to reply.
1157 *
1158 * @param handle MessageQ handle
1159 * @param msg Message to embed queue into
1160 */
1161 Void MessageQ_setReplyQueue(MessageQ_Handle handle, MessageQ_Msg msg);
1163 /*!
1164 * @brief Unblocks a MessageQ
1165 *
1166 * Unblocks a reader thread that is blocked on a MessageQ_get(). The
1167 * MessageQ_get() call will return with status #MessageQ_E_UNBLOCKED indicating
1168 * that it returned due to a MessageQ_unblock() rather than a timeout or a
1169 * received message. This call should only be used during a shutdown sequence
1170 * in order to ensure that there is no blocked reader on a queue before
1171 * deleting the queue. A queue may not be used after it has been unblocked.
1172 *
1173 * MessageQ_unblock() works by raising a flag in the queue indicating that it
1174 * is unblocked and then signaling the synchronizer that is configured with
1175 * the target queue. If MessageQ_unblock() is called upon a queue that has
1176 * no blocked listeners, then any subsequent MessageQ_get will not block and
1177 * will immediately return #MessageQ_E_UNBLOCKED regardless of whether there
1178 * is a message on the queue.
1179 *
1180 * Restrictions:
1181 * - A queue may not be used after it has been unblocked.
1182 * - MessageQ_unblock() may only be called on a local queue.
1183 * - May only be used with a queue configured with a blocking synchronizer.
1184 *
1185 * @param[in] handle MessageQ handle
1186 *
1187 * @sa MessageQ_get
1188 * @sa MessageQ_shutdown()
1189 */
1190 Void MessageQ_unblock(MessageQ_Handle handle);
1192 /*!
1193 * @brief Shuts down a MessageQ
1194 *
1195 * Similar to MessageQ_unblock(), MessageQ_shutdown() unblocks a reader thread
1196 * that is blocked on a MessageQ_get(), but causes a different return code
1197 * to be returned from MessageQ_get(). The MessageQ_get() call will return
1198 * with status #MessageQ_E_SHUTDOWN indicating that it returned due to a
1199 * MessageQ_shutdown() rather than MessageQ_unblock(), a timeout or a
1200 * received message. This call is intended to be used by MessageQ transports
1201 * when the transport detects that the transport framework corresponding to
1202 * the MessageQ has become unusable. This call should only be used during a
1203 * shutdown sequence in order to ensure that there is no blocked reader on a
1204 * queue before deleting the queue. A queue may not be used after it has been
1205 * shut down.
1206 *
1207 * MessageQ_shutdown() works by raising a flag in the queue indicating that it
1208 * is shut down and then signaling the synchronizer that is configured with
1209 * the target queue. If MessageQ_shutdown() is called upon a queue that has
1210 * no blocked listeners, then any subsequent MessageQ_get will not block and
1211 * will immediately return #MessageQ_E_SHUTDOWN regardless of whether there
1212 * is a message on the queue.
1213 *
1214 * Restrictions:
1215 * - A queue may not be used after it has been shut down.
1216 * - MessageQ_shutdown() may only be called on a local queue.
1217 * - May only be used with a queue configured with a blocking synchronizer.
1218 *
1219 * @param[in] handle MessageQ handle
1220 *
1221 * @sa MessageQ_get
1222 * @sa MessageQ_unblock
1223 */
1224 Void MessageQ_shutdown(MessageQ_Handle handle);
1226 #if defined (__cplusplus)
1227 }
1228 #endif /* defined (__cplusplus) */
1229 #endif /* ti_ipc_MessageQ__include */