This is an automated email from the ASF dual-hosted git repository.
xiaoxiang 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 607792d452 fs_files.c: make sure that fs_getfilep is not interrupted
when holding mutex
607792d452 is described below
commit 607792d4528a2cdc1d29c2692c304e11be397908
Author: raiden00pl <[email protected]>
AuthorDate: Fri Nov 3 14:16:43 2023 +0100
fs_files.c: make sure that fs_getfilep is not interrupted when holding mutex
this fixes the issue https://github.com/apache/nuttx/issues/6012
---
fs/inode/fs_files.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c
index dec3488fd0..bcb7638288 100644
--- a/fs/inode/fs_files.c
+++ b/fs/inode/fs_files.c
@@ -547,6 +547,7 @@ void files_close_onexec(FAR struct tcb_s *tcb)
int fs_getfilep(int fd, FAR struct file **filep)
{
FAR struct filelist *list;
+ irqstate_t flags;
int ret;
#ifdef CONFIG_FDCHECK
@@ -574,6 +575,27 @@ int fs_getfilep(int fd, FAR struct file **filep)
return -EBADF;
}
+ /* Protect this part with a critical section to make sure that we won't
+ * interrupt the mutex lock-unclock sequence below which may lead to the
+ * priority inversion. The case is as follows:
+ *
+ * We have two threads: low-priority thread A and high-priority thread B,
+ * both threads share the same task group data.
+ *
+ * Thread A performs IO on files periodically. Thread B is woken up by a
+ * high-frequency interrupts, and performs IO on files periodically.
+ *
+ * There is a chance that thread B wakes up exactly when thread A holds
+ * the mutex below, and consequently the file access in thread B will be
+ * delayed due to thread A holding the list->fl_lock mutex and execution
+ * will be returned to a thread with lower priority.
+ *
+ * The correct solution to this problem is to use the read-write lock,
+ * which is currently not supported by NuttX.
+ */
+
+ flags = enter_critical_section();
+
/* The descriptor is in a valid range to file descriptor... Get the
* thread-specific file list.
*/
@@ -583,6 +605,7 @@ int fs_getfilep(int fd, FAR struct file **filep)
ret = nxmutex_lock(&list->fl_lock);
if (ret < 0)
{
+ leave_critical_section(flags);
return ret;
}
@@ -598,6 +621,7 @@ int fs_getfilep(int fd, FAR struct file **filep)
}
nxmutex_unlock(&list->fl_lock);
+ leave_critical_section(flags);
return ret;
}