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

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


The following commit(s) were added to refs/heads/master by this push:
     new a459280fac use atomic to protect f_refs
a459280fac is described below

commit a459280fac220f137455059e635e65015d657e88
Author: hujun5 <[email protected]>
AuthorDate: Fri Dec 13 16:50:59 2024 +0800

    use atomic to protect f_refs
    
    fix regresion from https://github.com/apache/nuttx/pull/14801
    
    Signed-off-by: hujun5 <[email protected]>
---
 fs/inode/fs_files.c   | 48 ++++++++++++++++++++++--------------------------
 include/nuttx/fs/fs.h |  3 ++-
 2 files changed, 24 insertions(+), 27 deletions(-)

diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c
index c2268bb9e5..5135a856b6 100644
--- a/fs/inode/fs_files.c
+++ b/fs/inode/fs_files.c
@@ -76,33 +76,40 @@ static FAR struct file *files_fget_by_index(FAR struct 
filelist *list,
 
   filep = &list->fl_files[l1][l2];
 #ifdef CONFIG_FS_REFCOUNT
+  int32_t refs = 0;
+
   if (filep->f_inode != NULL)
     {
       /* When the reference count is zero but the inode has not yet been
        * released, At this point we should return a null pointer
        */
 
-      if (filep->f_refs == 0)
-        {
-          filep = NULL;
-        }
-      else
+      do
         {
-          filep->f_refs++;
+          refs = atomic_read(&filep->f_refs);
+          if (refs == 0)
+            {
+              filep = NULL;
+              break;
+            }
         }
+      while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1));
     }
   else if (new == NULL)
     {
       filep = NULL;
     }
-  else if (filep->f_refs)
-    {
-      filep->f_refs++;
-    }
   else
     {
-      filep->f_refs = 2;
-      *new = true;
+      do
+        {
+          if (atomic_cmpxchg(&filep->f_refs, &refs, 2))
+            {
+              *new = true;
+              break;
+            }
+        }
+      while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1));
     }
 #else
   if (filep->f_inode == NULL && new == NULL)
@@ -593,7 +600,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR 
struct inode *inode,
               filep->f_inode       = inode;
               filep->f_priv        = priv;
 #ifdef CONFIG_FS_REFCOUNT
-              filep->f_refs        = 1;
+              atomic_set(&filep->f_refs, 1);
 #endif
 #ifdef CONFIG_FDSAN
               filep->f_tag_fdsan   = 0;
@@ -823,12 +830,8 @@ void fs_reffilep(FAR struct file *filep)
 {
   /* This interface is used to increase the reference count of filep */
 
-  irqstate_t flags;
-
   DEBUGASSERT(filep);
-  flags = spin_lock_irqsave(NULL);
-  filep->f_refs++;
-  spin_unlock_irqrestore(NULL, flags);
+  atomic_fetch_add(&filep->f_refs, 1);
 }
 
 /****************************************************************************
@@ -845,20 +848,13 @@ void fs_reffilep(FAR struct file *filep)
 
 int fs_putfilep(FAR struct file *filep)
 {
-  irqstate_t flags;
   int ret = 0;
-  int refs;
 
   DEBUGASSERT(filep);
-  flags = spin_lock_irqsave(NULL);
-
-  refs = --filep->f_refs;
-
-  spin_unlock_irqrestore(NULL, flags);
 
   /* If refs is zero, the close() had called, closing it now. */
 
-  if (refs == 0)
+  if (atomic_fetch_sub(&filep->f_refs, 1) == 1)
     {
       ret = file_close(filep);
       if (ret < 0)
diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h
index 31e2158b26..dd3ff75403 100644
--- a/include/nuttx/fs/fs.h
+++ b/include/nuttx/fs/fs.h
@@ -50,6 +50,7 @@
 #include <nuttx/queue.h>
 #include <nuttx/irq.h>
 #include <nuttx/spinlock_type.h>
+#include <nuttx/atomic.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -461,7 +462,7 @@ struct file
 {
   int               f_oflags;   /* Open mode flags */
 #ifdef CONFIG_FS_REFCOUNT
-  int               f_refs;     /* Reference count */
+  atomic_t          f_refs;     /* Reference count */
 #endif
   off_t             f_pos;      /* File position */
   FAR struct inode *f_inode;    /* Driver or file system interface */

Reply via email to