index 6076189ef7dee4bcc18585ba814ab741a38ff099..194767210ff1dd110b9b131e37b7f1c9d51b666f 100644 (file)
*/
#define MessageQ_E_UNBLOCKED (-19)
+/*!
+ * @brief MessageQ was shutdown
+ */
+#define MessageQ_E_SHUTDOWN (-20)
+
/* =============================================================================
* Macros
* =============================================================================
*/
#define MessageQ_PRIORITYMASK (0x3)
+/** @cond INTERNAL */
+/*!
+ * @brief Offset to avoid collision with reserved ports
+ *
+ * A queue's port number is computed by adding this offset to the
+ * queue index. Use the port number to address the message or when
+ * binding a socket. Computing a port number with this offset avoids
+ * collisions with reserved port numbers which are typically in the
+ * same range as the queue indexes.
+ */
+#define MessageQ_PORTOFFSET (0x80)
+/** @endcond INTERNAL */
+
/*!
* @brief Extract the destination queue ID from a message.
*
- * Can only be used on the same processor where the destination queue resides.
- * This function should only be used by Message Queue Transport writers.
+ * This function is typically used be a transport.
+ *
+ * The destination address is written into the message header when
+ * calling MessageQ_put(). Therefore, you can only use this function
+ * to extract the destination queue ID after MessageQ_put() has been
+ * called on the given message. However, ownership rules dictate that
+ * you cannot dereference a message after calling MessageQ_put() (because
+ * you have transfered ownership to the transport).
+ *
+ * After receiving a message by calling MessageQ_get(), you may safely
+ * use this function. Although there is little benefit from doing so.
+ *
+ * When the message is given to the transport, the destination address
+ * has been written into the message header. In addition, the transport
+ * now has ownership of the message. So, it is appropriate for the transport
+ * to use this macro.
*
* @param[in] msg Message of type #MessageQ_Msg
*
* @retval queueId Destination message queue ID of type #MessageQ_QueueId
*/
-#define MessageQ_getDstQueue(msg) \
- ((msg)->dstId == (MessageQ_QueueIndex)MessageQ_INVALIDMESSAGEQ) ? \
- (MessageQ_QueueId)MessageQ_INVALIDMESSAGEQ : \
- (MessageQ_QueueId)(((MessageQ_QueueId)MultiProc_self() << 16u) \
- | (((MessageQ_Msg)(msg))->dstId))
+#define MessageQ_getDstQueue(msg) \
+ (((MessageQ_Msg)(msg))->dstId == \
+ (MessageQ_QueueIndex)MessageQ_INVALIDMESSAGEQ) ? \
+ (MessageQ_QueueId)MessageQ_INVALIDMESSAGEQ : \
+ (((MessageQ_QueueId)((MessageQ_Msg)(msg))->dstProc << 16u) \
+ | (((MessageQ_Msg)(msg))->dstId))
/*!
#define MessageQ_getProcId(queueId) \
((UInt16)((queueId) >> 16))
+/*!
+ * @brief Extract the queue index from the given queue ID
+ *
+ * When creating and opening queues, the queue index is embedded
+ * into the queue ID using an implementation dependent format. This
+ * function extracts the queue index from the queue ID.
+ *
+ * For example, in the MessageQ_put() hook function, you might extract
+ * the queue index in order to set the transport ID.
+ *
+ * @code
+ * Void msgqPutHook(MessageQ_QueueId queueId, MessageQ_Msg msg)
+ * {
+ * MessageQ_QueueIndex queueIndex;
+ * UInt tid;
+ *
+ * queueIndex = MessageQ_getQueueIndex(queueId);
+ * ...
+ * MessageQ_setTransportId(msg, tid);
+ * }
+ * @endcode
+ *
+ * This function performs no error checking. Using an invalid queue ID
+ * will result in undefined behavior.
+ *
+ * @param[in] queueId Message queue ID of type #MessageQ_QueueId
+ *
+ * @retval queueIndex The queue index of type #MessageQ_QueueIndex
+ */
+#define MessageQ_getQueueIndex(queueId) \
+ (((MessageQ_QueueIndex)((MessageQ_QueueId)0xFFFF & (queueId))) \
+ - MessageQ_PORTOFFSET)
+
/*!
* @brief Retrieves the message queue ID from a message.
*
* @brief Required first field in every message
*/
typedef struct {
- Bits32 reserved0; /*!< reserved for List.elem->next */
- Bits32 reserved1; /*!< reserved for List.elem->prev */
+ Bits64 reserved0; /*!< reserved for List.elem->next */
+ Bits64 reserved1; /*!< reserved for List.elem->prev */
Bits32 msgSize; /*!< message size */
Bits16 flags; /*!< bitmask of different flags */
Bits16 msgId; /*!< message id */
* =============================================================================
*/
+/** @cond INTERNAL */
+/* Returns the local handle associated with queueId. */
+MessageQ_Handle MessageQ_getLocalHandle(MessageQ_QueueId queueId);
+/** @endcond INTERNAL */
+
+
/** @cond INTERNAL */
Void MessageQ_Params_init__S(MessageQ_Params *params, Int version);
/** @endcond INTERNAL */
*/
MessageQ_Handle MessageQ_create(String name, const MessageQ_Params *params);
+/*!
+ * @brief Announce a previously created MessageQ to NameServer
+ * (Linux/Android only)
+ *
+ * The name supplied here does not have to be in persistent memory. The
+ * maximum length of the string supplied here, including the '\\0' terminator,
+ * is '32' by default.
+ *
+ * There are no verifications to ensure that the name supplied in
+ * MessageQ_announce() is unique across all processors. Caution must be
+ * exercised to ensure that each processor uses a unique name.
+ *
+ * @param[in] name Name of the queue
+ * @param[in] handlePtr Pointer to handle returned from MessageQ_create.
+ *
+ * @return MessageQ status:
+ * - #MessageQ_E_FAIL: announce failed
+ * - #MessageQ_S_SUCCESS: announce successful
+ */
+Int MessageQ_announce(String name, MessageQ_Handle * handlePtr);
+
/*!
* @brief Create a MessageQ instance using the type MessageQ_Params2
*
Int MessageQ_open(String name, MessageQ_QueueId *queueId);
/*!
- * @brief Opens a MessageQ given the queue index and remote processor ID
+ * @brief Open a MessageQ given the queue index and processor ID
*
* This function can be used instead of MessageQ_open() if the queue
- * was created with a specified QueueIndex. In the example below, the
+ * was created with a reserved queue index. In the example below, the
* serverFxn function must be running on the processor with PROCID 2.
*
* @code
* MessageQ_Params params;
*
* MessageQ_Params_init(¶ms);
- * params.queueIndex = SERVER_QIDX;
- * messageQ = MessageQ_create("server", ¶ms);
+ * params.queueIndex = SERVER_QUEIDX;
+ * messageQ = MessageQ_create(NULL, ¶ms);
* ...
* }
*
* opened has already been created. MessageQ_openQueueId() does not validate
* that the queue has been created (unlike the MessageQ_open() function).
*
- * @param[in] queueIndex QueueIndex specified in MessageQ_Params
- * @param[in] remoteProcId Multiproc_Id of where the created queue resides
+ * @param[in] queueIndex QueueIndex specified in MessageQ_Params when
+ * the message queue was created.
+ * @param[in] procId Multiproc_Id of where the created queue resides.
*
* @return The MessageQ_QueueId associated with the queueIndex
* and remoteProcId
*/
-MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 remoteProcId);
+MessageQ_QueueId MessageQ_openQueueId(UInt16 queueIndex, UInt16 procId);
/*!
* @brief Close the opened handle
* returns immediately and if no message is available, the msg
* is set to NULL and the status is #MessageQ_E_TIMEOUT. The
* #MessageQ_E_UNBLOCKED status is return, if MessageQ_unblock is called
- * on the MessageQ handle. If a message is successfully retrieved, the msg
- * is set to the message and a #MessageQ_S_SUCCESS status is returned.
+ * on the MessageQ handle. The #MessageQ_E_SHUTDOWN status is returned if
+ * MessageQ_shutdown is called on the MessageQ handle. If a message is
+ * successfully retrieved, the msg is set to the message and a
+ * #MessageQ_S_SUCCESS status is returned.
*
* @param[in] handle MessageQ handle
* @param[out] msg Pointer to the message
*
* @sa MessageQ_put()
* @sa MessageQ_unblock()
+ * @sa MessageQ_shutdown()
*/
Int MessageQ_get(MessageQ_Handle handle, MessageQ_Msg *msg, UInt timeout);
* @param[in] handle MessageQ handle
*
* @sa MessageQ_get
+ * @sa MessageQ_shutdown()
*/
Void MessageQ_unblock(MessageQ_Handle handle);
+/*!
+ * @brief Shuts down a MessageQ
+ *
+ * Similar to MessageQ_unblock(), MessageQ_shutdown() unblocks a reader thread
+ * that is blocked on a MessageQ_get(), but causes a different return code
+ * to be returned from MessageQ_get(). The MessageQ_get() call will return
+ * with status #MessageQ_E_SHUTDOWN indicating that it returned due to a
+ * MessageQ_shutdown() rather than MessageQ_unblock(), a timeout or a
+ * received message. This call is intended to be used by MessageQ transports
+ * when the transport detects that the transport framework corresponding to
+ * the MessageQ has become unusable. This call should only be used during a
+ * shutdown sequence in order to ensure that there is no blocked reader on a
+ * queue before deleting the queue. A queue may not be used after it has been
+ * shut down.
+ *
+ * MessageQ_shutdown() works by raising a flag in the queue indicating that it
+ * is shut down and then signaling the synchronizer that is configured with
+ * the target queue. If MessageQ_shutdown() is called upon a queue that has
+ * no blocked listeners, then any subsequent MessageQ_get will not block and
+ * will immediately return #MessageQ_E_SHUTDOWN regardless of whether there
+ * is a message on the queue.
+ *
+ * Restrictions:
+ * - A queue may not be used after it has been shut down.
+ * - MessageQ_shutdown() may only be called on a local queue.
+ * - May only be used with a queue configured with a blocking synchronizer.
+ *
+ * @param[in] handle MessageQ handle
+ *
+ * @sa MessageQ_get
+ * @sa MessageQ_unblock
+ */
+Void MessageQ_shutdown(MessageQ_Handle handle);
+
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */