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:
parent
0028f0cae9
commit
40e62f4d43
2 changed files with 24 additions and 27 deletions
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue