/**************************************************************************** * 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 #include #include #ifdef CONFIG_IOB_NOTIFIER # include #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 */