From 4f239e145ece0dad8cb73f8c401ce4cc877a33bd Mon Sep 17 00:00:00 2001 From: chao an Date: Sun, 18 Dec 2022 23:08:04 +0800 Subject: [PATCH] Revert "mm/iob/contig: enhance iob contig to support iob chain" This reverts commit 56a4e90dc40f7fc15b8b0cb2a6855a2254e8fc48. --- Documentation/reference/os/iob.rst | 6 +- include/nuttx/mm/iob.h | 6 +- mm/iob/iob_contig.c | 119 +++++++++++++++++------------ 3 files changed, 79 insertions(+), 52 deletions(-) diff --git a/Documentation/reference/os/iob.rst b/Documentation/reference/os/iob.rst index 32c59a1842..2a84af0756 100644 --- a/Documentation/reference/os/iob.rst +++ b/Documentation/reference/os/iob.rst @@ -318,9 +318,11 @@ Public Function Prototypes 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. -.. c:function:: FAR struct iob_s *iob_contig(FAR struct iob_s *iob); +.. c:function:: int iob_contig(FAR struct iob_s *iob, unsigned int len); - Merge an ``iob`` chain into a continuous space, thereby reducing ``iob`` consumption + Ensure that there is ``len`` bytes of contiguous + space at the beginning of the I/O buffer chain starting at + ``iob``. .. c:function:: void iob_dump(FAR const char *msg, FAR struct iob_s *iob, unsigned int len, \ unsigned int offset); diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h index 0238761805..0bc5fe3614 100644 --- a/include/nuttx/mm/iob.h +++ b/include/nuttx/mm/iob.h @@ -562,12 +562,12 @@ FAR struct iob_s *iob_pack(FAR struct iob_s *iob); * Name: iob_contig * * Description: - * Merge an iob chain into a continuous space, thereby reducing iob - * consumption + * Ensure that there is 'len' bytes of contiguous space at the beginning + * of the I/O buffer chain starting at 'iob'. * ****************************************************************************/ -FAR struct iob_s *iob_contig(FAR struct iob_s *iob); +int iob_contig(FAR struct iob_s *iob, unsigned int len); /**************************************************************************** * Name: iob_reserve diff --git a/mm/iob/iob_contig.c b/mm/iob/iob_contig.c index 985d85c8c8..97d4e4c473 100644 --- a/mm/iob/iob_contig.c +++ b/mm/iob/iob_contig.c @@ -25,6 +25,9 @@ #include #include +#include +#include +#include #include @@ -46,55 +49,41 @@ * Name: iob_contig * * Description: - * Merge an iob chain into a continuous space, thereby reducing iob - * consumption + * Ensure that there is'len' bytes of contiguous space at the beginning + * of the I/O buffer chain starting at 'iob'. * ****************************************************************************/ -FAR struct iob_s *iob_contig(FAR struct iob_s *iob) +int iob_contig(FAR struct iob_s *iob, unsigned int len) { - FAR struct iob_s *head; FAR struct iob_s *next; unsigned int ncopy; - /* Trim empty iob header */ + /* We can't make more contiguous space that the size of one I/O buffer. + * If you get this assertion and really need that much contiguous data, + * then you will need to increase CONFIG_IOB_BUFSIZE. + */ - while (iob != NULL && iob->io_len == 0) + DEBUGASSERT(len <= CONFIG_IOB_BUFSIZE); + + /* Check if there is already sufficient, contiguous space at the beginning + * of the packet + */ + + if (len <= iob->io_len) { - iob = iob_free(iob); + /* Yes we are good */ + + return 0; } - if (iob == NULL) + /* Can we get the required amount of contiguous data by just packing the + * head I/0 buffer? + */ + + else if (len <= iob->io_pktlen) { - return NULL; - } - - /* Remember the chain header */ - - head = iob; - - while (iob != NULL && iob->io_flink != NULL) - { - next = iob->io_flink; - - /* Skip and free the empty next node */ - - if (next->io_len == 0) - { - next = iob_free(next); - iob->io_flink = next; - continue; - } - - /* Skip filled node */ - - if (iob->io_len == CONFIG_IOB_BUFSIZE) - { - iob = iob->io_flink; - continue; - } - - /* Eliminate any leading offset */ + /* Yes.. First eliminate any leading offset */ if (iob->io_offset > 0) { @@ -102,19 +91,55 @@ FAR struct iob_s *iob_contig(FAR struct iob_s *iob) iob->io_offset = 0; } - /* Copy what we need or what we can from the next buffer */ + /* Then move what we need from the next I/O buffer(s) */ - ncopy = CONFIG_IOB_BUFSIZE - iob->io_len; - ncopy = MIN(ncopy, next->io_len); - memcpy(&iob->io_data[iob->io_len], - &next->io_data[next->io_offset], ncopy); + do + { + /* Get the next I/O buffer in the chain */ - /* Adjust counts and offsets */ + next = iob->io_flink; + DEBUGASSERT(next != NULL); - iob->io_len += ncopy; - next->io_offset += ncopy; - next->io_len -= ncopy; + /* Copy what we need or what we can from the next buffer */ + + ncopy = len - iob->io_len; + ncopy = MIN(ncopy, next->io_len); + memcpy(&iob->io_data[iob->io_len], + &next->io_data[next->io_offset], ncopy); + + /* Adjust counts and offsets */ + + iob->io_len += ncopy; + next->io_offset += ncopy; + next->io_len -= ncopy; + + /* Handle a (improbable) case where we just emptied the second + * buffer in the chain. + */ + + if (next->io_len == 0) + { + iob->io_flink = iob_free(next); + } + } + while (len > iob->io_len); + + /* This should always succeed because we know that: + * + * pktlen >= CONFIG_IOB_BUFSIZE >= len + */ + + return 0; } - return head; + /* Otherwise, the request for contiguous data is larger then the entire + * packet. We can't do that without extending the I/O buffer chain with + * garbage (which would probably not be what the caller wants). + */ + + else + { + ioberr("ERROR: pktlen=%u < requested len=%u\n", iob->io_pktlen, len); + return -ENOSPC; + } }