incubator-nuttx/include/nuttx/mm/iob.h

650 lines
21 KiB
C

/****************************************************************************
* include/nuttx/mm/iob.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_MM_IOB_H
#define __INCLUDE_NUTTX_MM_IOB_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef CONFIG_IOB_NOTIFIER
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_MM_IOB
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* I/O buffer allocation logic supports a throttle value for read-ahead
* buffering to prevent the read-ahead logic from consuming all available I/O
* buffers and blocking the write buffering logic. This throttle logic
* is only needed if both write buffering and read-ahead buffering are used.
*
* The correct way to disable throttling is to set the throttle value to
* zero.
*/
#if !defined(CONFIG_IOB_THROTTLE)
# define CONFIG_IOB_THROTTLE 0
#endif
/* Some I/O buffers should be allocated */
#if !defined(CONFIG_IOB_NBUFFERS)
# warning CONFIG_IOB_NBUFFERS not defined
# define CONFIG_IOB_NBUFFERS 0
#endif
#if CONFIG_IOB_NBUFFERS < 1
# error CONFIG_IOB_NBUFFERS is zero
#endif
#if CONFIG_IOB_NBUFFERS <= CONFIG_IOB_THROTTLE
# error CONFIG_IOB_NBUFFERS <= CONFIG_IOB_THROTTLE
#endif
/* IOB helpers */
#define IOB_DATA(p) (&(p)->io_data[(p)->io_offset])
#define IOB_FREESPACE(p) (CONFIG_IOB_BUFSIZE - (p)->io_len - (p)->io_offset)
#if CONFIG_IOB_NCHAINS > 0
/* Queue helpers */
# define IOB_QINIT(q) do { (q)->qh_head = 0; (q)->qh_tail = 0; } while (0)
# define IOB_QEMPTY(q) ((q)->qh_head == NULL)
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* Represents one I/O buffer. A packet is contained by one or more I/O
* buffers in a chain. The io_pktlen is only valid for the I/O buffer at
* the head of the chain.
*/
struct iob_s
{
/* Singly-link list support */
FAR struct iob_s *io_flink;
/* Payload */
#if CONFIG_IOB_BUFSIZE < 256
uint8_t io_len; /* Length of the data in the entry */
uint8_t io_offset; /* Data begins at this offset */
#else
uint16_t io_len; /* Length of the data in the entry */
uint16_t io_offset; /* Data begins at this offset */
#endif
unsigned int io_pktlen; /* Total length of the packet */
uint8_t io_data[CONFIG_IOB_BUFSIZE];
};
#if CONFIG_IOB_NCHAINS > 0
/* This container structure supports queuing of I/O buffer chains. This
* structure is intended only for internal use by the IOB module.
*/
struct iob_qentry_s
{
/* Singly-link list support */
FAR struct iob_qentry_s *qe_flink;
/* Payload -- Head of the I/O buffer chain */
FAR struct iob_s *qe_head;
};
/* The I/O buffer queue head structure */
struct iob_queue_s
{
/* Head of the I/O buffer chain list */
FAR struct iob_qentry_s *qh_head;
FAR struct iob_qentry_s *qh_tail;
};
#endif /* CONFIG_IOB_NCHAINS > 0 */
/* NOTE: When you change any logic here, you must change the logic in
* fs/procfs/fs_procfsiobinfo.c as it depends on having matching sequential
* logic.
*/
enum iob_user_e
{
IOBUSER_UNKNOWN = -1,
#ifdef CONFIG_SYSLOG_BUFFER
IOBUSER_SYSLOG,
#endif
#ifdef CONFIG_IOB_UNITTEST
IOBUSER_UNITTEST,
#endif
#ifdef CONFIG_NET_6LOWPAN
IOBUSER_NET_6LOWPAN,
#endif
#ifdef CONFIG_NET_ICMP_SOCKET
IOBUSER_NET_SOCK_ICMP,
#endif
#ifdef CONFIG_NET_ICMPv6_SOCKET
IOBUSER_NET_SOCK_ICMPv6,
#endif
#ifdef CONFIG_NET_UDP
IOBUSER_NET_SOCK_UDP,
#endif
#ifdef CONFIG_NET_TCP
IOBUSER_NET_SOCK_TCP,
#endif
#ifdef CONFIG_NET_IEEE802154
IOBUSER_NET_SOCK_IEEE802154,
#endif
#ifdef CONFIG_NET_BLUETOOTH
IOBUSER_NET_SOCK_BLUETOOTH,
#endif
#if defined(CONFIG_NET_UDP) && !defined(NET_UDP_NO_STACK)
IOBUSER_NET_UDP_READAHEAD,
#endif
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
IOBUSER_NET_UDP_WRITEBUFFER,
#endif
#if defined(CONFIG_NET_TCP) && !defined(NET_TCP_NO_STACK)
IOBUSER_NET_TCP_READAHEAD,
#endif
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
IOBUSER_NET_TCP_WRITEBUFFER,
#endif
#ifdef CONFIG_NET_IPFORWARD
IOBUSER_NET_IPFORWARD,
#endif
#ifdef CONFIG_WIRELESS_IEEE802154
IOBUSER_WIRELESS_RAD802154,
#endif
#ifdef CONFIG_IEEE802154_MAC
IOBUSER_WIRELESS_MAC802154,
#endif
#ifdef CONFIG_IEEE802154_MACDEV
IOBUSER_WIRELESS_MAC802154_CHARDEV,
#endif
#ifdef CONFIG_IEEE802154_NETDEV
IOBUSER_WIRELESS_MAC802154_NETDEV,
#endif
#ifdef CONFIG_WL_SPIRIT
IOBUSER_WIRELESS_PACKETRADIO,
#endif
#ifdef CONFIG_WIRELESS_BLUETOOTH
IOBUSER_WIRELESS_BLUETOOTH,
#endif
#ifdef CONFIG_NET_CAN
IOBUSER_NET_CAN_READAHEAD,
#endif
IOBUSER_GLOBAL,
IOBUSER_NENTRIES /* MUST BE LAST ENTRY */
};
struct iob_userstats_s
{
int totalconsumed;
int totalproduced;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: iob_initialize
*
* Description:
* Set up the I/O buffers for normal operations.
*
****************************************************************************/
void iob_initialize(void);
/****************************************************************************
* Name: iob_timedalloc
*
* Description:
* Allocate an I/O buffer by taking the buffer at the head of the free list.
* This wait will be terminated when the specified timeout expires.
*
* Input Parameters:
* throttled - An indication of the IOB allocation is "throttled"
* timeout - Timeout value in milliseconds.
* consumerid - id representing who is consuming the IOB
*
****************************************************************************/
FAR struct iob_s *iob_timedalloc(bool throttled, unsigned int timeout,
enum iob_user_e consumerid);
/****************************************************************************
* Name: iob_alloc
*
* Description:
* Allocate an I/O buffer by taking the buffer at the head of the free
* list.
*
****************************************************************************/
FAR struct iob_s *iob_alloc(bool throttled, enum iob_user_e consumerid);
/****************************************************************************
* Name: iob_tryalloc
*
* Description:
* Try to allocate an I/O buffer by taking the buffer at the head of the
* free list without waiting for a buffer to become free.
*
****************************************************************************/
FAR struct iob_s *iob_tryalloc(bool throttled, enum iob_user_e consumerid);
/****************************************************************************
* Name: iob_navail
*
* Description:
* Return the number of available IOBs.
*
****************************************************************************/
int iob_navail(bool throttled);
/****************************************************************************
* Name: iob_qentry_navail
*
* Description:
* Return the number of available IOB chains.
*
****************************************************************************/
int iob_qentry_navail(void);
/****************************************************************************
* Name: iob_free
*
* Description:
* Free the I/O buffer at the head of a buffer chain returning it to the
* free list. The link to the next I/O buffer in the chain is return.
*
****************************************************************************/
FAR struct iob_s *iob_free(FAR struct iob_s *iob,
enum iob_user_e producerid);
/****************************************************************************
* Name: iob_notifier_setup
*
* Description:
* Set up to perform a callback to the worker function when an IOB is
* available. The worker function will execute on the selected priority
* worker thread.
*
* Input Parameters:
* qid - Selects work queue. Must be HPWORK or LPWORK.
* worker - The worker function to execute on the high priority work queue
* when the event occurs.
* arg - A user-defined argument that will be available to the worker
* function when it runs.
*
* Returned Value:
* > 0 - The signal notification is in place. The returned value is a
* key that may be used later in a call to
* iob_notifier_teardown().
* == 0 - There are already free IOBs. No signal notification will be
* provided.
* < 0 - An unexpected error occurred and no signal will be sent. The
* returned value is a negated errno value that indicates the
* nature of the failure.
*
****************************************************************************/
#ifdef CONFIG_IOB_NOTIFIER
int iob_notifier_setup(int qid, worker_t worker, FAR void *arg);
#endif
/****************************************************************************
* Name: iob_notifier_teardown
*
* Description:
* Eliminate an IOB notification previously setup by iob_notifier_setup().
* This function should only be called if the notification should be
* aborted prior to the notification. The notification will automatically
* be torn down after the signal is sent.
*
* Input Parameters:
* key - The key value returned from a previous call to
* iob_notifier_setup().
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_IOB_NOTIFIER
void iob_notifier_teardown(int key);
#endif
/****************************************************************************
* Name: iob_free_chain
*
* Description:
* Free an entire buffer chain, starting at the beginning of the I/O
* buffer chain
*
****************************************************************************/
void iob_free_chain(FAR struct iob_s *iob, enum iob_user_e producerid);
/****************************************************************************
* Name: iob_add_queue
*
* Description:
* Add one I/O buffer chain to the end of a queue. May fail due to lack
* of resources.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
#endif /* CONFIG_IOB_NCHAINS > 0 */
/****************************************************************************
* Name: iob_tryadd_queue
*
* Description:
* Add one I/O buffer chain to the end of a queue without waiting for
* resources to become free.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
int iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
#endif /* CONFIG_IOB_NCHAINS > 0 */
/****************************************************************************
* Name: iob_remove_queue
*
* Description:
* Remove and return one I/O buffer chain from the head of a queue.
*
* Returned Value:
* Returns a reference to the I/O buffer chain at the head of the queue.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
FAR struct iob_s *iob_remove_queue(FAR struct iob_queue_s *iobq);
#endif /* CONFIG_IOB_NCHAINS > 0 */
/****************************************************************************
* Name: iob_peek_queue
*
* Description:
* Return a reference to the I/O buffer chain at the head of a queue. This
* is similar to iob_remove_queue except that the I/O buffer chain is in
* place at the head of the queue. The I/O buffer chain may safely be
* modified by the caller but must be removed from the queue before it can
* be freed.
*
* Returned Value:
* Returns a reference to the I/O buffer chain at the head of the queue.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
FAR struct iob_s *iob_peek_queue(FAR struct iob_queue_s *iobq);
#endif
/****************************************************************************
* Name: iob_free_queue
*
* Description:
* Free an entire queue of I/O buffer chains.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
void iob_free_queue(FAR struct iob_queue_s *qhead,
enum iob_user_e producerid);
#endif /* CONFIG_IOB_NCHAINS > 0 */
/****************************************************************************
* Name: iob_free_queue_qentry
*
* Description:
* Free an iob entire queue of I/O buffer chains.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
void iob_free_queue_qentry(FAR struct iob_s *iob,
FAR struct iob_queue_s *iobq,
enum iob_user_e producerid);
#endif /* CONFIG_IOB_NCHAINS > 0 */
/****************************************************************************
* Name: iob_get_queue_size
*
* Description:
* Queue helper for get the iob queue buffer size.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
unsigned int iob_get_queue_size(FAR struct iob_queue_s *queue);
#endif /* CONFIG_IOB_NCHAINS > 0 */
/****************************************************************************
* Name: iob_copyin
*
* Description:
* Copy data 'len' bytes from a user buffer into the I/O buffer chain,
* starting at 'offset', extending the chain as necessary.
*
****************************************************************************/
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
unsigned int len, unsigned int offset, bool throttled,
enum iob_user_e consumerid);
/****************************************************************************
* Name: iob_trycopyin
*
* Description:
* Copy data 'len' bytes from a user buffer into the I/O buffer chain,
* starting at 'offset', extending the chain as necessary BUT without
* waiting if buffers are not available.
*
****************************************************************************/
int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
unsigned int len, unsigned int offset, bool throttled,
enum iob_user_e consumerid);
/****************************************************************************
* Name: iob_copyout
*
* Description:
* Copy data 'len' bytes of data into the user buffer starting at 'offset'
* in the I/O buffer, returning that actual number of bytes copied out.
*
****************************************************************************/
int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
unsigned int len, unsigned int offset);
/****************************************************************************
* Name: iob_tailroom
*
* Description:
* Return the number of bytes at the tail of the I/O buffer chain which
* can be used to append data without additional allocations.
*
****************************************************************************/
unsigned int iob_tailroom(FAR struct iob_s *iob);
/****************************************************************************
* Name: iob_clone
*
* Description:
* Duplicate (and pack) the data in iob1 in iob2. iob2 must be empty.
*
****************************************************************************/
int iob_clone(FAR struct iob_s *iob1, FAR struct iob_s *iob2, bool throttled,
enum iob_user_e consumerid);
/****************************************************************************
* Name: iob_concat
*
* Description:
* Concatenate iob_s chain iob2 to iob1.
*
****************************************************************************/
void iob_concat(FAR struct iob_s *iob1, FAR struct iob_s *iob2);
/****************************************************************************
* Name: iob_trimhead
*
* Description:
* Remove bytes from the beginning of an I/O chain. Emptied I/O buffers
* are freed and, hence, the beginning of the chain may change.
*
****************************************************************************/
FAR struct iob_s *iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen,
enum iob_user_e producerid);
/****************************************************************************
* Name: iob_trimhead_queue
*
* Description:
* Remove bytes from the beginning of an I/O chain at the head of the
* queue. Emptied I/O buffers are freed and, hence, the head of the
* queue may change.
*
* This function is just a wrapper around iob_trimhead() that assures that
* the iob at the head of queue is modified with the trimming operations.
*
* Returned Value:
* The new iob at the head of the queue is returned.
*
****************************************************************************/
#if CONFIG_IOB_NCHAINS > 0
FAR struct iob_s *iob_trimhead_queue(FAR struct iob_queue_s *qhead,
unsigned int trimlen,
enum iob_user_e producerid);
#endif
/****************************************************************************
* Name: iob_trimtail
*
* Description:
* Remove bytes from the end of an I/O chain. Emptied I/O buffers are
* freed NULL will be returned in the special case where the entry I/O
* buffer chain is freed.
*
****************************************************************************/
FAR struct iob_s *iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen,
enum iob_user_e producerid);
/****************************************************************************
* Name: iob_pack
*
* Description:
* Pack all data in the I/O buffer chain so that the data offset is zero
* and all but the final buffer in the chain are filled. Any emptied
* buffers at the end of the chain are freed.
*
****************************************************************************/
FAR struct iob_s *iob_pack(FAR struct iob_s *iob,
enum iob_user_e producerid);
/****************************************************************************
* Name: iob_contig
*
* Description:
* Ensure that there is 'len' bytes of contiguous space at the beginning
* of the I/O buffer chain starting at 'iob'.
*
****************************************************************************/
int iob_contig(FAR struct iob_s *iob, unsigned int len,
enum iob_user_e producerid);
/****************************************************************************
* Name: iob_dump
*
* Description:
* Dump the contents of a I/O buffer chain
*
****************************************************************************/
#ifdef CONFIG_DEBUG_FEATURES
void iob_dump(FAR const char *msg, FAR struct iob_s *iob, unsigned int len,
unsigned int offset);
#else
# define iob_dump(wrb)
#endif
/****************************************************************************
* Name: iob_getuserstats
*
* Description:
* Return a reference to the IOB usage statistics for the IOB
* consumer/producer
*
* Input Parameters:
* userid - id representing the IOB producer/consumer
*
* Returned Value:
* None.
*
****************************************************************************/
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \
!defined(CONFIG_FS_PROCFS_EXCLUDE_IOBINFO)
FAR struct iob_userstats_s * iob_getuserstats(enum iob_user_e userid);
#endif
#endif /* CONFIG_MM_IOB */
#endif /* __INCLUDE_NUTTX_MM_IOB_H */