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