summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/jffs2/src/fs-rtems.c
diff options
context:
space:
mode:
authorKinsey Moore <kinsey.moore@oarcorp.com>2023-08-22 14:39:22 -0500
committerJoel Sherrill <joel@rtems.org>2023-09-06 08:53:02 -0500
commitfa85760c99a72b8186c70c896b98efe0d7cde2b6 (patch)
treed3a6bf42f1ced41f904e134d6c3fdcfefd6a5ddd /cpukit/libfs/src/jffs2/src/fs-rtems.c
parentmicroblaze: Add link options to dl07, dl08, and dl09 (diff)
downloadrtems-fa85760c99a72b8186c70c896b98efe0d7cde2b6.tar.bz2
cpukit/jffs2: Avoid delayed work lock inversion
This moves delayed work to a temporary chain to prevent a locking inversion between the delayed work lock and the alloc_sem lock. Delayed work is now processed after the delayed work lock is released. Locking order is any JFFS2 locks before the delayed work lock.
Diffstat (limited to '')
-rw-r--r--cpukit/libfs/src/jffs2/src/fs-rtems.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/cpukit/libfs/src/jffs2/src/fs-rtems.c b/cpukit/libfs/src/jffs2/src/fs-rtems.c
index 59d03effe6..1a677c9772 100644
--- a/cpukit/libfs/src/jffs2/src/fs-rtems.c
+++ b/cpukit/libfs/src/jffs2/src/fs-rtems.c
@@ -1282,6 +1282,8 @@ static void process_delayed_work(void)
rtems_chain_node* node;
mutex_lock(&delayed_work_mutex);
+ rtems_chain_control process_work_chain;
+ rtems_chain_initialize_empty(&process_work_chain);
if (rtems_chain_is_empty(&delayed_work_chain)) {
mutex_unlock(&delayed_work_mutex);
@@ -1294,12 +1296,22 @@ static void process_delayed_work(void)
rtems_chain_node* next_node = rtems_chain_next(node);
if (rtems_clock_get_uptime_nanoseconds() >= work->execution_time) {
rtems_chain_extract(node);
- work->callback(&work->work);
+ rtems_chain_append(&process_work_chain, node);
}
node = next_node;
}
mutex_unlock(&delayed_work_mutex);
+
+ node = rtems_chain_first(&process_work_chain);
+ while (!rtems_chain_is_tail(&process_work_chain, node)) {
+ work = (struct delayed_work*) node;
+ rtems_chain_node* next_node = rtems_chain_next(node);
+ rtems_chain_extract(node);
+ work->callback(&work->work);
+ node = next_node;
+ }
}
+
/* Task for processing delayed work */
static rtems_task delayed_work_task(
rtems_task_argument unused