OVMS3-idf/components/esp32/include/xtensa/xos_msgq.h

279 lines
11 KiB
C
Raw Normal View History

2016-08-17 15:08:22 +00:00
/** @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__