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 /** @cond INTERNAL */
445 Int __version;
446 /* Used internally for tracking implementation evolution.
447 * For internal use only.
448 */
449 /** @endcond INTERNAL */
451 Void *synchronizer;
452 /*!< Synchronizer instance used to signal IO completion
453 *
454 * The synchronizer is used in MessageQ_put() and MessageQ_get().
455 * The synchronizer signal is called as part of MessageQ_put().
456 * The synchronizer waits in MessageQ_get() if there are no messages
457 * present.
458 */
460 MessageQ_QueueIndex queueIndex;
461 /*!< Value used to specify the index in the MessageQ array
462 *
463 * This parameter allows an application to specify a queueIndex to
464 * be used for a message queue. To use this functionality, the
465 * MessageQ.numReservedEntries static configuration parameter must be
466 * set to one more than the highest requested queueIndex. The
467 * MessageQ.numReservedEntries parameter reserves that number of
468 * message queue slots starting at 0 and proceeding to
469 * (MessageQ.numReservedEntries - 1).
470 *
471 * The default is MessageQ_ANY, which means it is not taken from the
472 * reserved slots.
473 */
475 } MessageQ_Params;
477 /** @cond INTERNAL */
478 /* Date: 02 Dec 2014
479 *
480 * Initial implementation of params structure which contains
481 * a version field. This allows for binary compatibility as
482 * the params structure is modified in the future.
483 */
484 #define MessageQ_Params_VERSION_2 2
485 /** @endcond INTERNAL */
487 /** @cond INTERNAL */
488 /*!
489 * @brief Defines the current params structure version
490 */
491 #define MessageQ_Params_VERSION MessageQ_Params_VERSION_2
492 /** @endcond INTERNAL */
494 /*!
495 * @brief Structure defining parameters for MessageQ_create2().
496 *
497 * MessageQ_Params2 is a superset of MessageQ_Params. It is used
498 * with MessageQ_create2().
499 *
500 * @deprecated This type has been deprecated. It will be removed
501 * in a future release. Please use MessageQ_Params instead.
502 */
503 typedef struct {
504 Void *synchronizer;
505 /*!< Synchronizer instance used to signal IO completion
506 *
507 * The synchronizer is used in MessageQ_put() and MessageQ_get().
508 * The synchronizer signal is called as part of MessageQ_put().
509 * The synchronizer waits in MessageQ_get() if there are no messages
510 * present.
511 */
513 MessageQ_QueueIndex queueIndex;
514 /*!< Value used to specify the index in the MessageQ array
515 *
516 * This parameter allows an application to specify a queueIndex to
517 * be used for a message queue. To use this functionality, the
518 * MessageQ.numReservedEntries static configuration parameter must be
519 * set to one more than the highest requested queueIndex. The
520 * MessageQ.numReservedEntries parameter reserves that number of
521 * message queue slots starting at 0 and proceeding to
522 * (MessageQ.numReservedEntries - 1).
523 *
524 * The default is MessageQ_ANY, which means it is not taken from the
525 * reserved slots.
526 */
528 } MessageQ_Params2;
530 /*!
531 * @brief Required first field in every message
532 */
533 typedef struct {
534 Bits32 reserved0; /*!< reserved for List.elem->next */
535 Bits32 reserved1; /*!< reserved for List.elem->prev */
536 Bits32 msgSize; /*!< message size */
537 Bits16 flags; /*!< bitmask of different flags */
538 Bits16 msgId; /*!< message id */
539 Bits16 dstId; /*!< destination queue id */
540 Bits16 dstProc; /*!< destination processor id */
541 Bits16 replyId; /*!< reply id */
542 Bits16 replyProc; /*!< reply processor */
543 Bits16 srcProc; /*!< source processor */
544 Bits16 heapId; /*!< heap id */
545 Bits16 seqNum; /*!< sequence number */
546 Bits16 reserved; /*!< reserved */
547 } MessageQ_MsgHeader;
549 /*!
550 * @brief Typedef for ease of use
551 */
552 typedef MessageQ_MsgHeader *MessageQ_Msg;
554 /*!
555 * @brief Message priority
556 */
557 typedef enum {
558 MessageQ_NORMALPRI = 0, /*!< Normal Priority */
559 MessageQ_HIGHPRI = 1, /*!< High Priority */
560 MessageQ_RESERVEDPRI = 2, /*!< Reserved Priority */
561 MessageQ_URGENTPRI = 3 /*!< Urgent Priority */
562 } MessageQ_Priority;
564 /*!
565 * @brief Denotes any queueId is acceptable.
566 *
567 * This constant is the default for the queueId in the MessageQ_Params
568 * structure.
569 */
570 #define MessageQ_ANY (Bits16)~(0)
572 /*!
573 * @brief Free hook prototype
574 *
575 * @param[in] heapId heapId of message that was freed
576 * @param[in] msgId msgId of message that was freed
577 */
578 typedef Void (*MessageQ_FreeHookFxn)(Bits16 heapId, Bits16 msgId);
580 /*!
581 * @brief Put hook function definition
582 *
583 * This function is invoked near the beginning of the MessageQ_put()
584 * function. It allows client code to augment the addressing of the
585 * given message before it is delivered.
586 *
587 * @param[in] queueId destination message queue
588 * @param[in] msg message to be sent
589 */
590 typedef Void (*MessageQ_PutHookFxn)(MessageQ_QueueId queueId, MessageQ_Msg msg);
592 #ifdef STD_H
593 #include <ITransport.h>
594 #include <IMessageQTransport.h>
595 #else
596 #include <ti/sdo/ipc/interfaces/ITransport.h>
597 #include <ti/sdo/ipc/interfaces/IMessageQTransport.h>
598 #endif
600 Bool MessageQ_registerTransport(IMessageQTransport_Handle handle,
601 UInt16 rprocId, UInt priority);
602 Void MessageQ_unregisterTransport(UInt16 rprocId, UInt priority);
603 Bool MessageQ_registerTransportId(UInt tid, ITransport_Handle inst);
604 Void MessageQ_unregisterTransportId(UInt tid);
607 /* =============================================================================
608 * MessageQ Module-wide Functions
609 * =============================================================================
610 */
612 /** @cond INTERNAL */
613 Void MessageQ_Params_init__S(MessageQ_Params *params, Int version);
614 /** @endcond INTERNAL */
616 /*!
617 * @brief Initialize MessageQ_Params
618 *
619 * Initialized the given structure to its default values.
620 *
621 * @param[in] params Parameters required to create a MessageQ
622 */
623 #ifndef MessageQ_internal
624 static inline Void MessageQ_Params_init(MessageQ_Params *params)
625 {
626 if (params != NULL) {
627 MessageQ_Params_init__S(params, MessageQ_Params_VERSION);
628 }
629 }
630 #endif
632 /*!
633 * @brief Initialize MessageQ_Params2
634 *
635 * Initialized the given structure to its default values.
636 *
637 * @deprecated This function has been deprecated. It will be removed
638 * in a future release. Please use MessageQ_Params_init() instead.
639 *
640 * @param[in] params Parameters required to create a MessageQ
641 */
642 Void MessageQ_Params2_init(MessageQ_Params2 *params);
644 /*!
645 * @brief Create a MessageQ instance
646 *
647 * The name supplied here does not have to be in persistent memory. The
648 * maximum length of the string supplied here, including the '\\0' terminator,
649 * is '32' by default.
650 *
651 * There are no verifications to ensure that the name supplied in
652 * MessageQ_create() is unique across all processors. Caution must be exercised
653 * to ensure that each processor uses a unique name.
654 *
655 * @param[in] name Name of the queue
656 * @param[in] params Initialized MessageQ parameters
657 *
658 * @return MessageQ Handle
659 */
660 MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params);
662 /*!
663 * @brief Create a MessageQ instance using the type MessageQ_Params2
664 *
665 * The name supplied here does not have to be in persistent memory. The
666 * maximum length of the string supplied here, including the '\\0' terminator,
667 * is '32' by default.
668 *
669 * There are no verifications to ensure that the name supplied in
670 * MessageQ_create2() is unique across all processors. Caution must
671 * be exercised to ensure that each processor uses a unique name.
672 *
673 * @deprecated This function has been deprecated. It will be removed
674 * in a future release. Please use MessageQ_create() instead.
675 *
676 * @param[in] name Name of the queue
677 * @param[in] params Initialized MessageQ_Params2
678 *
679 * @return MessageQ Handle
680 */
681 MessageQ_Handle MessageQ_create2(String name, const MessageQ_Params2 *params);
683 /*!
684 * @brief Delete a created MessageQ instance
685 *
686 * This function deletes a created message queue instance. If the
687 * message queue is non-empty, any messages remaining in the queue
688 * will not be freed and will be lost.
689 *
690 * @param[in,out] handlePtr Pointer to handle to delete.
691 *
692 * @return MessageQ status:
693 * - #MessageQ_E_FAIL: delete failed
694 * - #MessageQ_S_SUCCESS: delete successful
695 */
696 Int MessageQ_delete(MessageQ_Handle *handlePtr);
698 /*!
699 * @brief Open a message queue
700 *
701 * MessageQ_open() is used to retrieve the queue id for a queue that has been
702 * created either locally or remotely. Note that the queueId is simply a
703 * 32 bit value that uniquely identifies a queue. Therefore, it is also
704 * possible to put a message on a queue whose queueId has been retrieved using
705 * any other method.
706 *
707 * @param[in] name Name of queue to open
708 * @param[out] queueId QueueId that can be used in MessageQ_put()
709 *
710 * @return MessageQ status:
711 * - #MessageQ_E_NOTFOUND: open failed (name not found on any
712 * processor)
713 * - #MessageQ_S_SUCCESS: open successful
714 */
715 Int MessageQ_open(String name, MessageQ_QueueId *queueId);
717 /*!
718 * @brief Opens a MessageQ given the queue index and remote processor ID
719 *
720 * This function can be used instead of MessageQ_open() if the queue
721 * was created with a specified QueueIndex. In the example below, the
722 * serverFxn function must be running on the processor with PROCID 2.
723 *
724 * @code
725 * #define SERVER_QUEIDX 1
726 * #define SERVER_PROCID 2
727 *
728 * serverFxn()
729 * {
730 * MessageQ_Params params;
731 *
732 * MessageQ_Params_init(¶ms);
733 * params.queueIndex = SERVER_QIDX;
734 * messageQ = MessageQ_create("server", ¶ms);
735 * ...
736 * }
737 *
738 * clientFxn()
739 * {
740 * MessageQ_QueueId serverQueue;
741 * serverQueue = MessageQ_openQueueId(SERVER_QUEIDX, SERVER_PROCID);
742 * }
743 * @endcode
744 *
745 * It is up to the application to guarantee that the queue which is being
746 * opened has already been created. MessageQ_openQueueId() does not validate
747 * that the queue has been created (unlike the MessageQ_open() function).
748 *
749 * @param[in] queueIndex QueueIndex specified in MessageQ_Params
750 * @param[in] remoteProcId Multiproc_Id of where the created queue resides
751 *
752 * @return The MessageQ_QueueId associated with the queueIndex
753 * and remoteProcId
754 */
755 MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 remoteProcId);
757 /*!
758 * @brief Close the opened handle
759 *
760 * Only close a queueId that was returned from MessageQ_open().
761 *
762 * @param[in] queueId Pointer to queueId to close
763 *
764 * @return MessageQ status:
765 * - #MessageQ_E_FAIL: close failed
766 * - #MessageQ_S_SUCCESS: close successful
767 */
768 Int MessageQ_close(MessageQ_QueueId *queueId);
770 /*!
771 * @brief Allocates a message from the heap
772 *
773 * This function allocates a message from the heap associated with the heapId.
774 * The first field of the message must be a #MessageQ_MsgHeader structure.
775 * For example:
776 * @code
777 * typedef struct MyMsg {
778 * MessageQ_MsgHeader header;
779 * ...
780 * } MyMsg;
781 * @endcode
782 *
783 * @param[in] heapId heapId
784 * @param[in] size size of requested message (including the
785 * #MessageQ_MsgHeader).
786 *
787 * @pre @c size must be at least large enough to hold a
788 * MessageQ_MsgHeader
789 *
790 * @return Allocated message or NULL if no memory.
791 */
792 MessageQ_Msg MessageQ_alloc(UInt16 heapId, UInt32 size);
794 /*!
795 * @brief Frees a message back to the heap
796 *
797 * Frees the message back to the heap that was used to allocate it.
798 *
799 * @param[in] msg Message to free.
800 *
801 * @return MessageQ status:
802 * - #MessageQ_E_FAIL: failed to free message
803 * - #MessageQ_S_SUCCESS: successfully freed the message
804 */
805 Int MessageQ_free(MessageQ_Msg msg);
807 /*!
808 * @brief Register a heap with MessageQ
809 *
810 * This function registers a heap with MessageQ. The user selects a unique
811 * heapId associated with this heap. When a message is allocated via
812 * MessageQ_alloc(), the heapId is specified. Internally, MessageQ
813 * uses the heapId to access the heap.
814 *
815 * Care must be taken when assigning heapIds. Internally MessageQ stores
816 * the heapId into the message. When the message is freed
817 * (via MessageQ_free()), the heapId is used to determine which heap to use.
818 * On systems with shared memory the heapIds must match on corresponding
819 * processors. For example, assume there is a heap called myHeap which
820 * acts on shared memory and processors 0 and 1 both use this heap.
821 * When you register the heap with MessageQ, the same heapId must be used
822 * on both processor 0 and 1.
823 *
824 * If a heap is already registered for the specified heapId, no action is
825 * taken and #MessageQ_E_ALREADYEXISTS is returned.
826 *
827 * @param[in] heap Heap to register
828 * @param[in] heapId heapId associated with the heap
829 *
830 * @return MessageQ status:
831 * - #MessageQ_S_SUCCESS: heap successfully registered
832 * - #MessageQ_E_ALREADYEXISTS: heap already exists with heapId
833 */
834 Int MessageQ_registerHeap(Ptr heap, UInt16 heapId);
836 /*!
837 * @brief Unregister a heap with MessageQ
838 *
839 * This function unregisters the heap associated with the heapId.
840 * Care must be taken to ensure that there are no outstanding messages
841 * allocated from this heap. If there are outstanding messages, an attempt
842 * to free the message will result in non-deterministic results.
843 *
844 * @param[in] heapId Heap to unregister
845 *
846 * @return MessageQ status:
847 * - #MessageQ_S_SUCCESS: heap successfully unregistered
848 */
849 Int MessageQ_unregisterHeap(UInt16 heapId);
851 /*!
852 * @brief Sets the message tracing flag on a given message
853 *
854 * This function enables message tracing for a message. Tracing is offered
855 * in the form of Log messages that are output during operations on the
856 * message (i.e. MessageQ_free(), MessageQ_put(), etc).
857 *
858 * @param msg Message
859 * @param traceFlag Message trace flag (TRUE = tracing enabled)
860 */
861 Void MessageQ_setMsgTrace(MessageQ_Msg msg, Bool traceFlag);
863 /*!
864 * @brief Initializes a message not obtained from MessageQ_alloc()
865 *
866 * There are several fields in the #MessageQ_MsgHeader that
867 * are initialized by the MessageQ_alloc() function. MessageQ_staticMsgInit()
868 * can be used to initialize these fields for messages that are
869 * not allocated from MessageQ.
870 *
871 * There is one strict constraint with using messages not allocated
872 * from MessageQ. The message cannot be freed via MessageQ_free().
873 * This includes
874 * - The application calling MessageQ_free() on the same processor
875 * - The application calling MessageQ_free() on a different processor
876 * - The application cannot send the message to another processor
877 * where the transport might call MessageQ_free() on the message.
878 * For example, copy based transport call MessageQ_free() after sending
879 * the message.
880 * If a staticMsgInit'd msg is passed to MessageQ_free() an assert will occur
881 *
882 * @param msg Message to initialize
883 * @param[in] size Size of the message in MAUs
884 *
885 * @pre @c size must be at least large enough to hold a #MessageQ_MsgHeader
886 */
887 Void MessageQ_staticMsgInit(MessageQ_Msg msg, UInt32 size);
889 /*!
890 * @brief Sets MessageQ's free hook function.
891 *
892 * This API allows a user to specify a hook function which is called within
893 * MessageQ_free(). The hook is called after a message is freed back to the
894 * associated heap. The two parameters to the hook function are the heapId
895 * and the msgId of the freed message.
896 *
897 * The function is called within MessageQ_free(), so care must be taken to
898 * minimize any performance or calling context impact.
899 *
900 * MessageQ_setFreeHookFxn() is not thread safe. It should only
901 * be called when no MessageQ_free()'s are happening.
902 *
903 * To disable the hook function, call MessageQ_setFreeHookFxn() with NULL.
904 *
905 * @param[in] freeHookFxn function to be called within MessageQ_free()
906 */
907 Void MessageQ_setFreeHookFxn(MessageQ_FreeHookFxn freeHookFxn);
909 /*!
910 * @brief Set the function hook for the MessageQ_put() method
911 *
912 * Register a hook function which is called from the beginning of the
913 * MessageQ_put() function. Only one hook may be registered at a time.
914 * Subsequent calls to register a put function will overwrite the
915 * previously registered function.
916 *
917 * To disable the hook function, call MessageQ_setPutHookFxn() with NULL.
918 *
919 * @param[in] putHookFxn function to be called within MessageQ_put()
920 */
921 Void MessageQ_setPutHookFxn(MessageQ_PutHookFxn putHookFxn);
923 /* =============================================================================
924 * MessageQ Per-instance Functions
925 * =============================================================================
926 */
928 /*!
929 * @brief Gets a message from the message queue
930 *
931 * This function returns a status. It also returns a message in msg.
932 * If no message is available, it blocks on the synchronizer object
933 * until the synchronizer is signaled or a timeout occurs.
934 * The synchronizer is signaled, when Message_put is called on the MessageQ
935 * handle. If a timeout occurs, the msg is set to NULL and the status is
936 * #MessageQ_E_TIMEOUT. If a timeout of zero is specified, the function
937 * returns immediately and if no message is available, the msg
938 * is set to NULL and the status is #MessageQ_E_TIMEOUT. The
939 * #MessageQ_E_UNBLOCKED status is return, if MessageQ_unblock is called
940 * on the MessageQ handle. If a message is successfully retrieved, the msg
941 * is set to the message and a #MessageQ_S_SUCCESS status is returned.
942 *
943 * @param[in] handle MessageQ handle
944 * @param[out] msg Pointer to the message
945 * @param[in] timeout Maximum duration to wait for a message in
946 * microseconds.
947 *
948 * @return MessageQ status:
949 * - #MessageQ_S_SUCCESS: Message successfully returned
950 * - #MessageQ_E_TIMEOUT: MessageQ_get() timed out
951 * - #MessageQ_E_UNBLOCKED: MessageQ_get() was unblocked
952 * - #MessageQ_E_FAIL: A general failure has occurred
953 *
954 * @sa MessageQ_put()
955 * @sa MessageQ_unblock()
956 */
957 Int MessageQ_get(MessageQ_Handle handle, MessageQ_Msg *msg, UInt timeout);
959 /*!
960 * @brief Place a message onto a message queue
961 *
962 * This call places the message onto the specified message queue. The
963 * message queue could be local or remote. The MessageQ module manages
964 * the delivery.
965 *
966 * In the case where the queue is remote, MessageQ does not guarantee that
967 * the message is actually delivered before the MessageQ_put() call returns
968 *
969 * The queue id must have been returned from one of the following functions:
970 * - MessageQ_open()
971 * - MessageQ_getReplyQueue()
972 * - MessageQ_getDstQueue()
973 *
974 * After the message is placed onto the final destination, the queue's
975 * #MessageQ_Params.synchronizer signal function is called.
976 *
977 * The application loses ownership of the message once MessageQ_put() is called.
978 *
979 * @param[in] queueId Destination MessageQ
980 * @param[in] msg Message to be sent.
981 *
982 * @return Status of the call.
983 * - #MessageQ_S_SUCCESS denotes success.
984 * - #MessageQ_E_FAIL denotes failure. The put was not successful.
985 * The caller still owns the message.
986 */
987 Int MessageQ_put(MessageQ_QueueId queueId, MessageQ_Msg msg);
989 /*!
990 * @brief Returns the number of messages in a message queue
991 *
992 * This function returns the number of messages in a message queue.
993 *
994 * @param[in] handle MessageQ handle
995 *
996 * @return Number of messages in the message queue.
997 */
998 Int MessageQ_count(MessageQ_Handle handle);
1000 /*!
1001 * @brief Returns the QueueId associated with the handle
1002 *
1003 * Since the MessageQ_put() function takes a QueueId, the creator
1004 * of a message queue cannot send a message to itself without
1005 * retrieving the QueueId. This function extracts the QueueId
1006 * from the object.
1007 *
1008 * @param[in] handle MessageQ handle
1009 *
1010 * @return QueueId associated to the object
1011 */
1012 UInt32 MessageQ_getQueueId(MessageQ_Handle handle);
1014 /*!
1015 * @brief Embeds a source message queue into a message
1016 *
1017 * This function along with MessageQ_getReplyQueue()
1018 * can be used instead of MessageQ_open(). The sender
1019 * of a message can embed a messageQ into the message with this
1020 * function. The receiver of the message can extract the message queue
1021 * id with the MessageQ_getReplyQueue() function.
1022 *
1023 * This method is particularly useful in a client/server relationship
1024 * where the server does not want to know who the clients are. The
1025 * clients can embed their message queue into the message to the server
1026 * and the server extracts it and uses it to reply.
1027 *
1028 * @param handle MessageQ handle
1029 * @param msg Message to embed queue into
1030 */
1031 Void MessageQ_setReplyQueue(MessageQ_Handle handle, MessageQ_Msg msg);
1033 /*!
1034 * @brief Unblocks a MessageQ
1035 *
1036 * Unblocks a reader thread that is blocked on a MessageQ_get(). The
1037 * MessageQ_get() call will return with status #MessageQ_E_UNBLOCKED indicating
1038 * that it returned due to a MessageQ_unblock() rather than a timeout or a
1039 * received message. This call should only be used during a shutdown sequence
1040 * in order to ensure that there is no blocked reader on a queue before
1041 * deleting the queue. A queue may not be used after it has been unblocked.
1042 *
1043 * MessageQ_unblock() works by raising a flag in the queue indicating that it
1044 * is unblocked and then signaling the synchronizer that is configured with
1045 * the target queue. If MessageQ_unblock() is called upon a queue that has
1046 * no blocked listeners, then any subsequent MessageQ_get will not block and
1047 * will immediately return #MessageQ_E_UNBLOCKED regardless of whether there
1048 * is a message on the queue.
1049 *
1050 * Restrictions:
1051 * - A queue may not be used after it has been unblocked.
1052 * - MessageQ_unblock() may only be called on a local queue.
1053 * - May only be used with a queue configured with a blocking synchronizer.
1054 *
1055 * @param[in] handle MessageQ handle
1056 *
1057 * @sa MessageQ_get
1058 */
1059 Void MessageQ_unblock(MessageQ_Handle handle);
1061 #if defined (__cplusplus)
1062 }
1063 #endif /* defined (__cplusplus) */
1064 #endif /* ti_ipc_MessageQ__include */