use atomic to protect f_refs

fix regresion from https://github.com/apache/nuttx/pull/14801

Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
hujun5 2024-12-13 16:50:59 +08:00 committed by Xiang Xiao
parent 0028f0cae9
commit 40e62f4d43
2 changed files with 24 additions and 27 deletions

View file

@ -76,33 +76,40 @@ static FAR struct file *files_fget_by_index(FAR struct filelist *list,
filep = &list->fl_files[l1][l2]; filep = &list->fl_files[l1][l2];
#ifdef CONFIG_FS_REFCOUNT #ifdef CONFIG_FS_REFCOUNT
int32_t refs = 0;
if (filep->f_inode != NULL) if (filep->f_inode != NULL)
{ {
/* When the reference count is zero but the inode has not yet been /* When the reference count is zero but the inode has not yet been
* released, At this point we should return a null pointer * released, At this point we should return a null pointer
*/ */
if (filep->f_refs == 0) do
{ {
filep = NULL; refs = atomic_read(&filep->f_refs);
} if (refs == 0)
else {
{ filep = NULL;
filep->f_refs++; break;
}
} }
while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1));
} }
else if (new == NULL) else if (new == NULL)
{ {
filep = NULL; filep = NULL;
} }
else if (filep->f_refs)
{
filep->f_refs++;
}
else else
{ {
filep->f_refs = 2; do
*new = true; {
if (atomic_cmpxchg(&filep->f_refs, &refs, 2))
{
*new = true;
break;
}
}
while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1));
} }
#else #else
if (filep->f_inode == NULL && new == NULL) if (filep->f_inode == NULL && new == NULL)
@ -617,7 +624,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode,
filep->f_inode = inode; filep->f_inode = inode;
filep->f_priv = priv; filep->f_priv = priv;
#ifdef CONFIG_FS_REFCOUNT #ifdef CONFIG_FS_REFCOUNT
filep->f_refs = 1; atomic_set(&filep->f_refs, 1);
#endif #endif
#ifdef CONFIG_FDSAN #ifdef CONFIG_FDSAN
filep->f_tag_fdsan = 0; filep->f_tag_fdsan = 0;
@ -847,12 +854,8 @@ void fs_reffilep(FAR struct file *filep)
{ {
/* This interface is used to increase the reference count of filep */ /* This interface is used to increase the reference count of filep */
irqstate_t flags;
DEBUGASSERT(filep); DEBUGASSERT(filep);
flags = spin_lock_irqsave(NULL); atomic_fetch_add(&filep->f_refs, 1);
filep->f_refs++;
spin_unlock_irqrestore(NULL, flags);
} }
/**************************************************************************** /****************************************************************************
@ -869,20 +872,13 @@ void fs_reffilep(FAR struct file *filep)
int fs_putfilep(FAR struct file *filep) int fs_putfilep(FAR struct file *filep)
{ {
irqstate_t flags;
int ret = 0; int ret = 0;
int refs;
DEBUGASSERT(filep); 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 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); ret = file_close(filep);
if (ret < 0) if (ret < 0)

View file

@ -50,6 +50,7 @@
#include <nuttx/queue.h> #include <nuttx/queue.h>
#include <nuttx/irq.h> #include <nuttx/irq.h>
#include <nuttx/spinlock_type.h> #include <nuttx/spinlock_type.h>
#include <nuttx/atomic.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -461,7 +462,7 @@ struct file
{ {
int f_oflags; /* Open mode flags */ int f_oflags; /* Open mode flags */
#ifdef CONFIG_FS_REFCOUNT #ifdef CONFIG_FS_REFCOUNT
int f_refs; /* Reference count */ atomic_t f_refs; /* Reference count */
#endif #endif
off_t f_pos; /* File position */ off_t f_pos; /* File position */
FAR struct inode *f_inode; /* Driver or file system interface */ FAR struct inode *f_inode; /* Driver or file system interface */