You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2020/07/19 20:14:00 UTC

[incubator-nuttx] branch master updated (4f22f74 -> aa57174)

This is an automated email from the ASF dual-hosted git repository.

btashton pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from 4f22f74  syscall: Remove g_funclookup and g_funcnparms
     new e7034c1  rwbuffer: Fix the wrong remaining block calculation in invalidation
     new aa57174  rwbuffer: Optimize the buffer algorithm

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 drivers/rwbuffer.c               | 213 ++++++++++++++++++++++++++-------------
 include/nuttx/drivers/rwbuffer.h |   1 -
 2 files changed, 145 insertions(+), 69 deletions(-)


[incubator-nuttx] 02/02: rwbuffer: Optimize the buffer algorithm

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btashton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit aa57174eb9ef4b58d96a827751a5f96b54d17a30
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Tue Jul 14 17:22:02 2020 +0800

    rwbuffer: Optimize the buffer algorithm
    
    avoid the buffer flush as much as possible
    
    Change-Id: I902f374e9540b36bd0b0c77a34cab5014a2c24fc
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 drivers/rwbuffer.c               | 207 +++++++++++++++++++++++++++------------
 include/nuttx/drivers/rwbuffer.h |   1 -
 2 files changed, 142 insertions(+), 66 deletions(-)

diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c
index d0d4b56..bd05adb 100644
--- a/drivers/rwbuffer.c
+++ b/drivers/rwbuffer.c
@@ -136,7 +136,6 @@ static inline void rwb_resetwrbuffer(FAR struct rwbuffer_s *rwb)
 
   rwb->wrnblocks       = 0;
   rwb->wrblockstart    = (off_t)-1;
-  rwb->wrexpectedblock = (off_t)-1;
 }
 #endif
 
@@ -240,56 +239,160 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
                                off_t startblock, uint32_t nblocks,
                                FAR const uint8_t *wrbuffer)
 {
-  int ret;
+  uint32_t nwritten = nblocks;
 
   /* Write writebuffer Logic */
 
   rwb_wrcanceltimeout(rwb);
 
-  /* First: Should we flush out our cache? We would do that if (1) we already
-   * buffering blocks and the next block writing is not in the same sequence,
-   * or (2) the number of blocks would exceed our allocated buffer capacity
-   */
+  /* Is data saved in the write buffer? */
 
-  if (((startblock != rwb->wrexpectedblock) && (rwb->wrnblocks)) ||
-      ((rwb->wrnblocks + nblocks) > rwb->wrmaxblocks))
+  if (rwb->wrnblocks > 0)
     {
-      finfo("writebuffer miss, expected: %08x, given: %08x\n",
-            rwb->wrexpectedblock, startblock);
+      off_t wrbend;
+      off_t newend;
 
-      /* Flush the write buffer */
+      /* Now there are five cases:
+       *
+       * 1. We update the non-overlapping region
+       */
 
-      ret = rwb->wrflush(rwb->dev, rwb->wrbuffer, rwb->wrblockstart,
-                         rwb->wrnblocks);
-      if (ret < 0)
+      wrbend = rwb->wrblockstart + rwb->wrnblocks;
+      newend = startblock + nblocks;
+
+      if (wrbend < startblock || rwb->wrblockstart > newend)
         {
-          ferr("ERROR: Error writing multiple from cache: %d\n", -ret);
-          return ret;
+          /* Nothing to do */;
         }
 
-      rwb_resetwrbuffer(rwb);
+      /* 2. We update the entire write buffer. */
+
+      else if (rwb->wrblockstart > startblock && wrbend < newend)
+        {
+          rwb->wrnblocks = 0;
+        }
+
+      /* We are going to update a subset of the write buffer.  Three
+       * more cases to consider:
+       *
+       * 3. We update a portion in the middle of the write buffer
+       */
+
+      else if (rwb->wrblockstart <= startblock && wrbend >= newend)
+        {
+          FAR uint8_t *dest;
+          size_t offset;
+
+          /* Copy the data to the middle of write buffer */
+
+          offset = startblock - rwb->wrblockstart;
+          dest   = rwb->wrbuffer + offset * rwb->blocksize;
+          memcpy(dest, wrbuffer, nblocks * rwb->blocksize);
+
+          nblocks = 0;
+        }
+
+      /* 4. We upate a portion at the end of the write buffer */
+
+      else if (wrbend >= startblock && wrbend <= newend)
+        {
+          FAR uint8_t *dest;
+          size_t offset;
+          size_t ncopy;
+
+          /* Copy the data from the updating region to the end
+           * of the write buffer.
+           */
+
+          offset = rwb->wrnblocks - (wrbend - startblock);
+          ncopy  = rwb->wrmaxblocks - offset;
+          if (ncopy > nblocks)
+            {
+              ncopy = nblocks;
+            }
+
+          dest = rwb->wrbuffer + offset * rwb->blocksize;
+          memcpy(dest, wrbuffer, ncopy * rwb->blocksize);
+
+          rwb->wrnblocks = offset + ncopy;
+          wrbuffer      += ncopy * rwb->blocksize;
+          startblock    += ncopy;
+          nblocks       -= ncopy;
+        }
+
+      /* 5. We update a portion at the beginning of the write buffer */
+
+      else /* if (rwb->wrblockstart >= startblock && wrbend >= newend) */
+        {
+          FAR uint8_t *dest;
+          FAR const uint8_t *src;
+          size_t ncopy;
+
+          DEBUGASSERT(rwb->wrblockstart >= startblock && wrbend >= newend);
+
+          /* Move the cached data to the end of the write buffer */
+
+          ncopy = rwb->wrblockstart - startblock;
+          if (ncopy > rwb->wrmaxblocks - rwb->wrnblocks)
+            {
+              ncopy = rwb->wrmaxblocks - rwb->wrnblocks;
+            }
+
+          dest = rwb->wrbuffer + ncopy * rwb->blocksize;
+          memmove(dest, rwb->wrbuffer, ncopy * rwb->blocksize);
+
+          rwb->wrblockstart -= ncopy;
+          rwb->wrnblocks    += ncopy;
+
+          /* Copy the data from the updating region to the beginning
+           * of the write buffer.
+           */
+
+          ncopy = newend - rwb->wrblockstart;
+          src   = wrbuffer + (nblocks - ncopy) * rwb->blocksize;
+          memcpy(rwb->wrbuffer, src, ncopy * rwb->blocksize);
+
+          nblocks -= ncopy;
+        }
     }
 
-  /* writebuffer is empty? Then initialize it */
+  /* Use the block cache unless the buffer size is bigger than block cache */
 
-  if (rwb->wrnblocks == 0)
+  if (nblocks > rwb->wrmaxblocks)
     {
-      finfo("Fresh cache starting at block: 0x%08x\n", startblock);
-      rwb->wrblockstart = startblock;
+      ssize_t ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks);
+      if (ret < 0)
+        {
+          return ret;
+        }
     }
+  else if (nblocks)
+    {
+      /* Flush the write buffer */
+
+      if (rwb->wrnblocks > 0)
+        {
+          ssize_t ret = rwb->wrflush(rwb->dev, rwb->wrbuffer,
+                                     rwb->wrblockstart, rwb->wrnblocks);
+          if (ret < 0)
+            {
+              return ret;
+            }
+        }
 
-  /* Add data to cache */
+      /* Buffer the data in the write buffer */
+
+      memcpy(rwb->wrbuffer, wrbuffer, nblocks * rwb->blocksize);
+      rwb->wrblockstart = startblock;
+      rwb->wrnblocks    = nblocks;
+    }
 
-  finfo("writebuffer: copying %d bytes from %p to %p\n",
-        nblocks * rwb->blocksize, wrbuffer,
-        &rwb->wrbuffer[rwb->wrnblocks * rwb->blocksize]);
-  memcpy(&rwb->wrbuffer[rwb->wrnblocks * rwb->blocksize],
-         wrbuffer, nblocks * rwb->blocksize);
+  if (rwb->wrnblocks > 0)
+    {
+      rwb_wrstarttimeout(rwb);
+    }
 
-  rwb->wrnblocks      += nblocks;
-  rwb->wrexpectedblock = rwb->wrblockstart + rwb->wrnblocks;
-  rwb_wrstarttimeout(rwb);
-  return nblocks;
+  return nwritten;
 }
 #endif
 
@@ -454,7 +557,7 @@ int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
       /* We are going to invalidate a subset of the write buffer.  Three
        * more cases to consider:
        *
-       * 2. We invalidate a portion in the middle of the write buffer
+       * 3. We invalidate a portion in the middle of the write buffer
        */
 
       else if (rwb->wrblockstart < startblock && wrbend > invend)
@@ -488,7 +591,7 @@ int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
             }
         }
 
-      /* 3. We invalidate a portion at the end of the write buffer */
+      /* 4. We invalidate a portion at the end of the write buffer */
 
       else if (wrbend > startblock && wrbend <= invend)
         {
@@ -496,7 +599,7 @@ int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
           ret = OK;
         }
 
-      /* 4. We invalidate a portion at the beginning of the write buffer */
+      /* 5. We invalidate a portion at the beginning of the write buffer */
 
       else /* if (rwb->wrblockstart >= startblock && wrbend > invend) */
         {
@@ -1005,40 +1108,14 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
     {
       finfo("startblock=%d wrbuffer=%p\n", startblock, wrbuffer);
 
-      /* Use the block cache unless the buffer size is bigger than block
-       * cache.
-       */
-
-      if (nblocks > rwb->wrmaxblocks)
+      ret = nxsem_wait(&rwb->wrsem);
+      if (ret < 0)
         {
-          /* First flush the cache */
-
-          ret = nxsem_wait(&rwb->wrsem);
-          if (ret < 0)
-            {
-              return (ssize_t)ret;
-            }
-
-          rwb_wrflush(rwb);
-          rwb_semgive(&rwb->wrsem);
-
-          /* Then transfer the data directly to the media */
-
-          ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks);
+          return (ssize_t)ret;
         }
-      else
-        {
-          /* Buffer the data in the write buffer */
-
-          ret = nxsem_wait(&rwb->wrsem);
-          if (ret < 0)
-            {
-              return (ssize_t)ret;
-            }
 
-          ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer);
-          rwb_semgive(&rwb->wrsem);
-        }
+      ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer);
+      rwb_semgive(&rwb->wrsem);
 
       /* On success, return the number of blocks that we were requested to
        * write.  This is for compatibility with the normal return of a block
diff --git a/include/nuttx/drivers/rwbuffer.h b/include/nuttx/drivers/rwbuffer.h
index 89f09e9..9515926 100644
--- a/include/nuttx/drivers/rwbuffer.h
+++ b/include/nuttx/drivers/rwbuffer.h
@@ -144,7 +144,6 @@ struct rwbuffer_s
   uint8_t      *wrbuffer;        /* Allocated write buffer */
   uint16_t      wrnblocks;       /* Number of blocks in write buffer */
   off_t         wrblockstart;    /* First block in write buffer */
-  off_t         wrexpectedblock; /* Next block expected */
 #endif
 
   /* This is the state of the read-ahead buffering */


[incubator-nuttx] 01/02: rwbuffer: Fix the wrong remaining block calculation in invalidation

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btashton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit e7034c102fade1c5aea83dfc79dac4c1050697fe
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Tue Jul 14 12:08:40 2020 +0800

    rwbuffer: Fix the wrong remaining block calculation in invalidation
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
    Change-Id: I00e6e7332f397bcddfd44e1b3c5c514a8f07923f
---
 drivers/rwbuffer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c
index 6a88e03..d0d4b56 100644
--- a/drivers/rwbuffer.c
+++ b/drivers/rwbuffer.c
@@ -492,7 +492,7 @@ int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
 
       else if (wrbend > startblock && wrbend <= invend)
         {
-          rwb->wrnblocks = wrbend - startblock;
+          rwb->wrnblocks -= wrbend - startblock;
           ret = OK;
         }
 
@@ -612,11 +612,11 @@ int rwb_invalidate_readahead(FAR struct rwbuffer_s *rwb,
 
       else if (rhbend > startblock && rhbend <= invend)
         {
-          rwb->rhnblocks = rhbend - startblock;
+          rwb->rhnblocks -= rhbend - startblock;
           ret = OK;
         }
 
-      /* 4. We invalidate a portion at the beginning of the write buffer */
+      /* 4. We invalidate a portion at the begin of the read-ahead buffer */
 
       else /* if (rwb->rhblockstart >= startblock && rhbend > invend) */
         {