279 lines
11 KiB
C
279 lines
11 KiB
C
|
/** @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__
|
||
|
|