/** @file */ // xos_msgq.h - XOS Message Queue API and data structures. // Copyright (c) 2003-2015 Cadence Design Systems, Inc. // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // NOTE: Do not include this file directly in your application. Including // xos.h will automatically include this file. #ifndef __XOS_MSGQ_H__ #define __XOS_MSGQ_H__ #include "xos_types.h" #ifdef __cplusplus extern "C" { #endif //----------------------------------------------------------------------------- // XosMsgQueue is a multi-writer multi-reader message queue implementation. // It is completely thread-safe and can be used by interrupt handlers. // Interrupt handlers are guaranteed not to block when trying to send or // receive a message. Messages are copied into the queue. The queue contains // storage for a fixed number of messages defined at queue creation time. // Messages must be a multiple of 4 bytes long (padded if necessary) and the // message buffers must be 4-byte aligned. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Message Queue flags. //----------------------------------------------------------------------------- #define XOS_MSGQ_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) #define XOS_MSGQ_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order #define XOS_MSGQ_FULL 0x0002 // Queue is full #define XOS_MSGQ_DELETED 0x8000 // Queue is deleted //----------------------------------------------------------------------------- /// /// XosMsgQueue object. /// //----------------------------------------------------------------------------- typedef struct XosMsgQueue { uint16_t flags; ///< queue flags uint16_t count; ///< # of messages queue can hold uint32_t msize; ///< message size in bytes uint16_t head; ///< write pointer uint16_t tail; ///< read pointer XosThreadQueue readq; ///< reader wait queue XosThreadQueue writeq; ///< writer wait queue #if XOS_MSGQ_DEBUG uint32_t sig; // debug signature #endif #if XOS_OPT_MSGQ_STATS uint32_t num_send; ///< # of messages put to queue uint32_t num_recv; ///< # of messages taken from queue uint32_t num_send_blks; ///< # of times thread blocked on send uint32_t num_recv_blks; ///< # of times thread blocked on recv #endif uint32_t msg[1]; ///< first word of message buffer } XosMsgQueue; //----------------------------------------------------------------------------- /// /// Use these macros to statically or dynamically allocate a message queue. /// XOS_MSGQ_ALLOC allocates a static queue, while XOS_MSGQ_SIZE can be used /// to allocate memory via malloc() etc. /// /// Static: this allocates a queue named "testq", containing 10 messages, /// each 16 bytes long. /// /// XOS_MSGQ_ALLOC(testq, 10, 16); /// /// Dynamic: this allocates a queue named "testq", containing 10 messages, /// each 16 bytes long. /// /// XosMsgQueue * testq = malloc( XOS_MSGQ_SIZE(10, 16) ); /// /// \param name The queue name, i.e. the name of the pointer /// to the queue. Used as the queue handle in /// queue API calls. /// /// \param num Number of messages to allocate in queue. Must be > 0. /// /// \param size Message size in bytes. Must be > 0 and multiple of 4. /// //----------------------------------------------------------------------------- #define XOS_MSGQ_ALLOC(name, num, size) \ static uint8_t name ## _buf[ sizeof(XosMsgQueue) + ((num) * (size)) ]; \ XosMsgQueue * name = (XosMsgQueue *) name ## _buf; #define XOS_MSGQ_SIZE(num, size) \ (sizeof(XosMsgQueue) + ((num) * (size))) //----------------------------------------------------------------------------- /// /// Create the message queue object. Memory for the queue must be allocated by /// the caller, either statically or via dynamic allocation. See the macros /// XOS_MSGQ_ALLOC and XOS_MSGQ_SIZE for examples. /// /// \param msgq Handle (pointer) to message queue. /// /// \param num Number of messages allocated in queue. Must be > 0. /// /// \param size Message size in bytes. Must be > 0 and multiple of 4. /// /// \param flags Queue flags: /// - XOS_MSGQ_WAIT_FIFO - blocked threads will be /// woken in FIFO order. /// - XOS_MSGQ_WAIT_PRIORITY - blocked threads will /// be woken in priority order (default). /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_msgq_create(XosMsgQueue * msgq, uint16_t num, uint32_t size, uint16_t flags); //----------------------------------------------------------------------------- /// /// Destroys the specified queue. Any waiting threads are unblocked with an /// error return. Any messages in the queue will be lost. /// /// \param msgq Pointer to message queue. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_msgq_delete(XosMsgQueue * msgq); //----------------------------------------------------------------------------- /// /// Put a message into the queue. The message contents are copied into the next /// available message slot. If no space is available, this function will block /// if called from a thread, but will return immediately if called from an /// interrupt handler. /// /// \param msgq Pointer to message queue. /// /// \param msg Pointer to message buffer. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_msgq_put(XosMsgQueue * msgq, const uint32_t * msg); //----------------------------------------------------------------------------- /// /// Put a message into the queue. The message contents are copied into the next /// available message slot. If no space is available, this function will block /// if called from a thread, but will return immediately if called from an /// interrupt handler. The thread will be unblocked when space frees up in the /// queue or the timeout expires. /// /// \param msgq Pointer to message queue. /// /// \param msg Pointer to message buffer. /// /// \param to_cycles Timeout in cycles. Convert from time to cycles /// using the helper functions provided in xos_timer. /// A value of zero indicates no timeout. /// /// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. /// /// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is /// ignored, and no timeout will occur. /// //----------------------------------------------------------------------------- int32_t xos_msgq_put_timeout(XosMsgQueue * msgq, const uint32_t * msg, uint64_t to_cycles); //----------------------------------------------------------------------------- /// /// Get a message from the queue. The message contents are copied into the /// buffer that must be provided. If no message is available, this function /// will block if called from a thread, but will return immediately if called /// from an interrupt handler. /// /// \param msgq Pointer to message queue. /// /// \param msg Pointer to message buffer. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_msgq_get(XosMsgQueue * msgq, uint32_t * msg); //----------------------------------------------------------------------------- /// /// Get a message from the queue. The message contents are copied into the /// buffer that must be provided. If no message is available, this function /// will block if called from a thread, but will return immediately if called /// from an interrupt handler. The thread will be unblocked when a message /// arrives in the queue or the timeout expires. /// /// \param msgq Pointer to message queue. /// /// \param msg Pointer to message buffer. /// /// \param to_cycles Timeout in cycles. Convert from time to cycles /// using the helper functions provided in xos_timer. /// A value of zero indicates no timeout. /// /// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. /// /// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is /// ignored, and no timeout will occur. /// //----------------------------------------------------------------------------- int32_t xos_msgq_get_timeout(XosMsgQueue * msgq, uint32_t * msg, uint64_t to_cycles); //----------------------------------------------------------------------------- /// /// Check if the queue is empty. /// /// \param msgq Pointer to message queue. /// /// \return Returns nonzero if queue is empty, zero if queue is not empty. /// //----------------------------------------------------------------------------- int32_t xos_msgq_empty(XosMsgQueue * msgq); //----------------------------------------------------------------------------- /// /// Check if the queue is full. /// /// \param msgq Pointer to message queue. /// /// \return Returns nonzero if queue is full, zero if queue is not full. /// //----------------------------------------------------------------------------- int32_t xos_msgq_full(XosMsgQueue * msgq); #ifdef __cplusplus } #endif #endif // __XOS_MSGQ_H__